| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 277 CellPrinter printer; | 277 CellPrinter printer; |
| 278 for (int i = 0; i < CellsCount(); i++) { | 278 for (int i = 0; i < CellsCount(); i++) { |
| 279 printer.Print(i, cells()[i]); | 279 printer.Print(i, cells()[i]); |
| 280 } | 280 } |
| 281 printer.Flush(); | 281 printer.Flush(); |
| 282 PrintF("\n"); | 282 PrintF("\n"); |
| 283 } | 283 } |
| 284 | 284 |
| 285 bool IsClean() { | 285 bool IsClean() { |
| 286 for (int i = 0; i < CellsCount(); i++) { | 286 for (int i = 0; i < CellsCount(); i++) { |
| 287 if (cells()[i] != 0) { | 287 if (cells()[i] != 0) return false; |
| 288 return false; | |
| 289 } | |
| 290 } | 288 } |
| 291 return true; | 289 return true; |
| 292 } | 290 } |
| 293 }; | 291 }; |
| 294 | 292 |
| 295 | 293 |
| 296 class SkipList; | 294 class SkipList; |
| 297 class SlotsBuffer; | 295 class SlotsBuffer; |
| 298 | 296 |
| 299 // MemoryChunk represents a memory region owned by a specific space. | 297 // MemoryChunk represents a memory region owned by a specific space. |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 368 return addr >= area_start() && addr < area_end(); | 366 return addr >= area_start() && addr < area_end(); |
| 369 } | 367 } |
| 370 | 368 |
| 371 // Checks whether addr can be a limit of addresses in this page. | 369 // Checks whether addr can be a limit of addresses in this page. |
| 372 // It's a limit if it's in the page, or if it's just after the | 370 // It's a limit if it's in the page, or if it's just after the |
| 373 // last byte of the page. | 371 // last byte of the page. |
| 374 bool ContainsLimit(Address addr) { | 372 bool ContainsLimit(Address addr) { |
| 375 return addr >= area_start() && addr <= area_end(); | 373 return addr >= area_start() && addr <= area_end(); |
| 376 } | 374 } |
| 377 | 375 |
| 378 // Every n write barrier invocations we go to runtime even though | |
| 379 // we could have handled it in generated code. This lets us check | |
| 380 // whether we have hit the limit and should do some more marking. | |
| 381 static const int kWriteBarrierCounterGranularity = 500; | |
| 382 | |
| 383 enum MemoryChunkFlags { | 376 enum MemoryChunkFlags { |
| 384 IS_EXECUTABLE, | 377 IS_EXECUTABLE, |
| 385 ABOUT_TO_BE_FREED, | 378 ABOUT_TO_BE_FREED, |
| 386 POINTERS_TO_HERE_ARE_INTERESTING, | 379 POINTERS_TO_HERE_ARE_INTERESTING, |
| 387 POINTERS_FROM_HERE_ARE_INTERESTING, | 380 POINTERS_FROM_HERE_ARE_INTERESTING, |
| 388 SCAN_ON_SCAVENGE, | 381 SCAN_ON_SCAVENGE, |
| 389 IN_FROM_SPACE, // Mutually exclusive with IN_TO_SPACE. | 382 IN_FROM_SPACE, // Mutually exclusive with IN_TO_SPACE. |
| 390 IN_TO_SPACE, // All pages in new space has one of these two set. | 383 IN_TO_SPACE, // All pages in new space has one of these two set. |
| 391 NEW_SPACE_BELOW_AGE_MARK, | 384 NEW_SPACE_BELOW_AGE_MARK, |
| 392 CONTAINS_ONLY_DATA, | 385 CONTAINS_ONLY_DATA, |
| 393 EVACUATION_CANDIDATE, | 386 EVACUATION_CANDIDATE, |
| 394 RESCAN_ON_EVACUATION, | 387 RESCAN_ON_EVACUATION, |
| 395 | 388 |
| 396 // Pages swept precisely can be iterated, hitting only the live objects. | 389 // Pages swept precisely can be iterated, hitting only the live objects. |
| 397 // Whereas those swept conservatively cannot be iterated over. Both flags | 390 // Whereas those swept conservatively cannot be iterated over. Both flags |
| 398 // indicate that marking bits have been cleared by the sweeper, otherwise | 391 // indicate that marking bits have been cleared by the sweeper, otherwise |
| 399 // marking bits are still intact. | 392 // marking bits are still intact. |
| 400 WAS_SWEPT_PRECISELY, | 393 WAS_SWEPT_PRECISELY, |
| 401 WAS_SWEPT_CONSERVATIVELY, | 394 WAS_SWEPT_CONSERVATIVELY, |
| 402 | 395 |
| 403 // Used for large objects only. Indicates that the object has been | |
| 404 // partially scanned by the incremental mark-sweep GC. Objects that have | |
| 405 // been partially scanned are marked black so that the write barrier | |
| 406 // triggers for them, and they are counted as live bytes. If the mutator | |
| 407 // writes to them they may be turned grey and subtracted from the live byte | |
| 408 // list. They move back to the marking deque either by an iteration over | |
| 409 // the large object space or in the write barrier. | |
| 410 IS_PARTIALLY_SCANNED, | |
| 411 | |
| 412 // Last flag, keep at bottom. | 396 // Last flag, keep at bottom. |
| 413 NUM_MEMORY_CHUNK_FLAGS | 397 NUM_MEMORY_CHUNK_FLAGS |
| 414 }; | 398 }; |
| 415 | 399 |
| 416 | 400 |
| 417 static const int kPointersToHereAreInterestingMask = | 401 static const int kPointersToHereAreInterestingMask = |
| 418 1 << POINTERS_TO_HERE_ARE_INTERESTING; | 402 1 << POINTERS_TO_HERE_ARE_INTERESTING; |
| 419 | 403 |
| 420 static const int kPointersFromHereAreInterestingMask = | 404 static const int kPointersFromHereAreInterestingMask = |
| 421 1 << POINTERS_FROM_HERE_ARE_INTERESTING; | 405 1 << POINTERS_FROM_HERE_ARE_INTERESTING; |
| 422 | 406 |
| 423 static const int kEvacuationCandidateMask = | 407 static const int kEvacuationCandidateMask = |
| 424 1 << EVACUATION_CANDIDATE; | 408 1 << EVACUATION_CANDIDATE; |
| 425 | 409 |
| 426 static const int kSkipEvacuationSlotsRecordingMask = | 410 static const int kSkipEvacuationSlotsRecordingMask = |
| 427 (1 << EVACUATION_CANDIDATE) | | 411 (1 << EVACUATION_CANDIDATE) | |
| 428 (1 << RESCAN_ON_EVACUATION) | | 412 (1 << RESCAN_ON_EVACUATION) | |
| 429 (1 << IN_FROM_SPACE) | | 413 (1 << IN_FROM_SPACE) | |
| 430 (1 << IN_TO_SPACE); | 414 (1 << IN_TO_SPACE); |
| 431 | 415 |
| 432 static const int kIsPartiallyScannedMask = 1 << IS_PARTIALLY_SCANNED; | |
| 433 | |
| 434 void SetPartiallyScannedProgress(int progress) { | |
| 435 SetFlag(IS_PARTIALLY_SCANNED); | |
| 436 partially_scanned_progress_ = progress; | |
| 437 } | |
| 438 | |
| 439 bool IsPartiallyScanned() { | |
| 440 return IsFlagSet(IS_PARTIALLY_SCANNED); | |
| 441 } | |
| 442 | |
| 443 void SetCompletelyScanned() { | |
| 444 ClearFlag(IS_PARTIALLY_SCANNED); | |
| 445 } | |
| 446 | |
| 447 int PartiallyScannedProgress() { | |
| 448 ASSERT(IsPartiallyScanned()); | |
| 449 return partially_scanned_progress_; | |
| 450 } | |
| 451 | 416 |
| 452 void SetFlag(int flag) { | 417 void SetFlag(int flag) { |
| 453 flags_ |= static_cast<uintptr_t>(1) << flag; | 418 flags_ |= static_cast<uintptr_t>(1) << flag; |
| 454 } | 419 } |
| 455 | 420 |
| 456 void ClearFlag(int flag) { | 421 void ClearFlag(int flag) { |
| 457 flags_ &= ~(static_cast<uintptr_t>(1) << flag); | 422 flags_ &= ~(static_cast<uintptr_t>(1) << flag); |
| 458 } | 423 } |
| 459 | 424 |
| 460 void SetFlagTo(int flag, bool value) { | 425 void SetFlagTo(int flag, bool value) { |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 496 live_byte_count_ + by); | 461 live_byte_count_ + by); |
| 497 } | 462 } |
| 498 live_byte_count_ += by; | 463 live_byte_count_ += by; |
| 499 ASSERT_LE(static_cast<unsigned>(live_byte_count_), size_); | 464 ASSERT_LE(static_cast<unsigned>(live_byte_count_), size_); |
| 500 } | 465 } |
| 501 int LiveBytes() { | 466 int LiveBytes() { |
| 502 ASSERT(static_cast<unsigned>(live_byte_count_) <= size_); | 467 ASSERT(static_cast<unsigned>(live_byte_count_) <= size_); |
| 503 return live_byte_count_; | 468 return live_byte_count_; |
| 504 } | 469 } |
| 505 | 470 |
| 506 int write_barrier_counter() { | |
| 507 return static_cast<int>(write_barrier_counter_); | |
| 508 } | |
| 509 | |
| 510 void set_write_barrier_counter(int counter) { | |
| 511 write_barrier_counter_ = counter; | |
| 512 } | |
| 513 | |
| 514 | |
| 515 static void IncrementLiveBytesFromGC(Address address, int by) { | 471 static void IncrementLiveBytesFromGC(Address address, int by) { |
| 516 MemoryChunk::FromAddress(address)->IncrementLiveBytes(by); | 472 MemoryChunk::FromAddress(address)->IncrementLiveBytes(by); |
| 517 } | 473 } |
| 518 | 474 |
| 519 static void IncrementLiveBytesFromMutator(Address address, int by); | 475 static void IncrementLiveBytesFromMutator(Address address, int by); |
| 520 | 476 |
| 521 static const intptr_t kAlignment = | 477 static const intptr_t kAlignment = |
| 522 (static_cast<uintptr_t>(1) << kPageSizeBits); | 478 (static_cast<uintptr_t>(1) << kPageSizeBits); |
| 523 | 479 |
| 524 static const intptr_t kAlignmentMask = kAlignment - 1; | 480 static const intptr_t kAlignmentMask = kAlignment - 1; |
| 525 | 481 |
| 526 static const intptr_t kSizeOffset = kPointerSize + kPointerSize; | 482 static const intptr_t kSizeOffset = kPointerSize + kPointerSize; |
| 527 | 483 |
| 528 static const intptr_t kLiveBytesOffset = | 484 static const intptr_t kLiveBytesOffset = |
| 529 kSizeOffset + kPointerSize + kPointerSize + kPointerSize + | 485 kSizeOffset + kPointerSize + kPointerSize + kPointerSize + |
| 530 kPointerSize + kPointerSize + | 486 kPointerSize + kPointerSize + |
| 531 kPointerSize + kPointerSize + kPointerSize + kIntSize; | 487 kPointerSize + kPointerSize + kPointerSize + kIntSize; |
| 532 | 488 |
| 533 static const size_t kSlotsBufferOffset = kLiveBytesOffset + kIntSize; | 489 static const size_t kSlotsBufferOffset = kLiveBytesOffset + kIntSize; |
| 534 | 490 |
| 535 static const size_t kWriteBarrierCounterOffset = | 491 static const size_t kHeaderSize = |
| 536 kSlotsBufferOffset + kPointerSize + kPointerSize; | 492 kSlotsBufferOffset + kPointerSize + kPointerSize; |
| 537 static const size_t kPartiallyScannedProgress = | |
| 538 kWriteBarrierCounterOffset + kPointerSize; | |
| 539 | |
| 540 // Actually the partially_scanned_progress_ member is only an int, but on | |
| 541 // 64 bit the size of MemoryChunk gets rounded up to a 64 bit size so we | |
| 542 // have to have the header start kPointerSize after the | |
| 543 // partially_scanned_progress_ member. | |
| 544 static const size_t kHeaderSize = kPartiallyScannedProgress + kPointerSize; | |
| 545 | 493 |
| 546 static const int kBodyOffset = | 494 static const int kBodyOffset = |
| 547 CODE_POINTER_ALIGN(MAP_POINTER_ALIGN(kHeaderSize + Bitmap::kSize)); | 495 CODE_POINTER_ALIGN(MAP_POINTER_ALIGN(kHeaderSize + Bitmap::kSize)); |
| 548 | 496 |
| 549 // The start offset of the object area in a page. Aligned to both maps and | 497 // The start offset of the object area in a page. Aligned to both maps and |
| 550 // code alignment to be suitable for both. Also aligned to 32 words because | 498 // code alignment to be suitable for both. Also aligned to 32 words because |
| 551 // the marking bitmap is arranged in 32 bit chunks. | 499 // the marking bitmap is arranged in 32 bit chunks. |
| 552 static const int kObjectStartAlignment = 32 * kPointerSize; | 500 static const int kObjectStartAlignment = 32 * kPointerSize; |
| 553 static const int kObjectStartOffset = kBodyOffset - 1 + | 501 static const int kObjectStartOffset = kBodyOffset - 1 + |
| 554 (kObjectStartAlignment - (kBodyOffset - 1) % kObjectStartAlignment); | 502 (kObjectStartAlignment - (kBodyOffset - 1) % kObjectStartAlignment); |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 670 // in a fixed array. | 618 // in a fixed array. |
| 671 Address owner_; | 619 Address owner_; |
| 672 Heap* heap_; | 620 Heap* heap_; |
| 673 // Used by the store buffer to keep track of which pages to mark scan-on- | 621 // Used by the store buffer to keep track of which pages to mark scan-on- |
| 674 // scavenge. | 622 // scavenge. |
| 675 int store_buffer_counter_; | 623 int store_buffer_counter_; |
| 676 // Count of bytes marked black on page. | 624 // Count of bytes marked black on page. |
| 677 int live_byte_count_; | 625 int live_byte_count_; |
| 678 SlotsBuffer* slots_buffer_; | 626 SlotsBuffer* slots_buffer_; |
| 679 SkipList* skip_list_; | 627 SkipList* skip_list_; |
| 680 intptr_t write_barrier_counter_; | |
| 681 int partially_scanned_progress_; | |
| 682 | 628 |
| 683 static MemoryChunk* Initialize(Heap* heap, | 629 static MemoryChunk* Initialize(Heap* heap, |
| 684 Address base, | 630 Address base, |
| 685 size_t size, | 631 size_t size, |
| 686 Address area_start, | 632 Address area_start, |
| 687 Address area_end, | 633 Address area_end, |
| 688 Executability executable, | 634 Executability executable, |
| 689 Space* owner); | 635 Space* owner); |
| 690 | 636 |
| 691 friend class MemoryAllocator; | 637 friend class MemoryAllocator; |
| (...skipping 2011 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2703 } | 2649 } |
| 2704 // Must be small, since an iteration is used for lookup. | 2650 // Must be small, since an iteration is used for lookup. |
| 2705 static const int kMaxComments = 64; | 2651 static const int kMaxComments = 64; |
| 2706 }; | 2652 }; |
| 2707 #endif | 2653 #endif |
| 2708 | 2654 |
| 2709 | 2655 |
| 2710 } } // namespace v8::internal | 2656 } } // namespace v8::internal |
| 2711 | 2657 |
| 2712 #endif // V8_SPACES_H_ | 2658 #endif // V8_SPACES_H_ |
| OLD | NEW |