| 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 295 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 306 return reinterpret_cast<MemoryChunk*>(OffsetFrom(a) & ~kAlignmentMask); | 306 return reinterpret_cast<MemoryChunk*>(OffsetFrom(a) & ~kAlignmentMask); |
| 307 } | 307 } |
| 308 | 308 |
| 309 // Only works for addresses in pointer spaces, not data or code spaces. | 309 // Only works for addresses in pointer spaces, not data or code spaces. |
| 310 static inline MemoryChunk* FromAnyPointerAddress(Heap* heap, Address addr); | 310 static inline MemoryChunk* FromAnyPointerAddress(Heap* heap, Address addr); |
| 311 | 311 |
| 312 Address address() { return reinterpret_cast<Address>(this); } | 312 Address address() { return reinterpret_cast<Address>(this); } |
| 313 | 313 |
| 314 bool is_valid() { return address() != NULL; } | 314 bool is_valid() { return address() != NULL; } |
| 315 | 315 |
| 316 MemoryChunk* next_chunk() const { | 316 MemoryChunk* next_chunk() const { return next_chunk_; } |
| 317 return reinterpret_cast<MemoryChunk*>(Acquire_Load(&next_chunk_)); | 317 MemoryChunk* prev_chunk() const { return prev_chunk_; } |
| 318 } | |
| 319 | 318 |
| 320 MemoryChunk* prev_chunk() const { | 319 void set_next_chunk(MemoryChunk* next) { next_chunk_ = next; } |
| 321 return reinterpret_cast<MemoryChunk*>(Acquire_Load(&prev_chunk_)); | 320 void set_prev_chunk(MemoryChunk* prev) { prev_chunk_ = prev; } |
| 322 } | |
| 323 | |
| 324 void set_next_chunk(MemoryChunk* next) { | |
| 325 Release_Store(&next_chunk_, reinterpret_cast<AtomicWord>(next)); | |
| 326 } | |
| 327 | |
| 328 void set_prev_chunk(MemoryChunk* prev) { | |
| 329 Release_Store(&prev_chunk_, reinterpret_cast<AtomicWord>(prev)); | |
| 330 } | |
| 331 | 321 |
| 332 Space* owner() const { | 322 Space* owner() const { |
| 333 if ((reinterpret_cast<intptr_t>(owner_) & kFailureTagMask) == | 323 if ((reinterpret_cast<intptr_t>(owner_) & kFailureTagMask) == |
| 334 kFailureTag) { | 324 kFailureTag) { |
| 335 return reinterpret_cast<Space*>(reinterpret_cast<intptr_t>(owner_) - | 325 return reinterpret_cast<Space*>(reinterpret_cast<intptr_t>(owner_) - |
| 336 kFailureTag); | 326 kFailureTag); |
| 337 } else { | 327 } else { |
| 338 return NULL; | 328 return NULL; |
| 339 } | 329 } |
| 340 } | 330 } |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 460 // Set or clear multiple flags at a time. The flags in the mask | 450 // Set or clear multiple flags at a time. The flags in the mask |
| 461 // are set to the value in "flags", the rest retain the current value | 451 // are set to the value in "flags", the rest retain the current value |
| 462 // in flags_. | 452 // in flags_. |
| 463 void SetFlags(intptr_t flags, intptr_t mask) { | 453 void SetFlags(intptr_t flags, intptr_t mask) { |
| 464 flags_ = (flags_ & ~mask) | (flags & mask); | 454 flags_ = (flags_ & ~mask) | (flags & mask); |
| 465 } | 455 } |
| 466 | 456 |
| 467 // Return all current flags. | 457 // Return all current flags. |
| 468 intptr_t GetFlags() { return flags_; } | 458 intptr_t GetFlags() { return flags_; } |
| 469 | 459 |
| 470 | 460 intptr_t parallel_sweeping() const { |
| 471 // PARALLEL_SWEEPING_PENDING - This page is ready for parallel sweeping. | 461 return parallel_sweeping_; |
| 472 // PARALLEL_SWEEPING_IN_PROGRESS - This page is currently swept or was | |
| 473 // swept by a sweeper thread. | |
| 474 // PARALLEL_SWEEPING_DONE - The page state when sweeping is complete or | |
| 475 // sweeping must not be performed on that page. | |
| 476 enum ParallelSweepingState { | |
| 477 PARALLEL_SWEEPING_DONE, | |
| 478 PARALLEL_SWEEPING_IN_PROGRESS, | |
| 479 PARALLEL_SWEEPING_PENDING | |
| 480 }; | |
| 481 | |
| 482 ParallelSweepingState parallel_sweeping() { | |
| 483 return static_cast<ParallelSweepingState>( | |
| 484 NoBarrier_Load(¶llel_sweeping_)); | |
| 485 } | 462 } |
| 486 | 463 |
| 487 void set_parallel_sweeping(ParallelSweepingState state) { | 464 void set_parallel_sweeping(intptr_t state) { |
| 488 NoBarrier_Store(¶llel_sweeping_, state); | 465 parallel_sweeping_ = state; |
| 489 } | 466 } |
| 490 | 467 |
| 491 bool TryParallelSweeping() { | 468 bool TryParallelSweeping() { |
| 492 return NoBarrier_CompareAndSwap(¶llel_sweeping_, | 469 return NoBarrier_CompareAndSwap(¶llel_sweeping_, 1, 0) == 1; |
| 493 PARALLEL_SWEEPING_PENDING, | |
| 494 PARALLEL_SWEEPING_IN_PROGRESS) == | |
| 495 PARALLEL_SWEEPING_PENDING; | |
| 496 } | 470 } |
| 497 | 471 |
| 498 // Manage live byte count (count of bytes known to be live, | 472 // Manage live byte count (count of bytes known to be live, |
| 499 // because they are marked black). | 473 // because they are marked black). |
| 500 void ResetLiveBytes() { | 474 void ResetLiveBytes() { |
| 501 if (FLAG_gc_verbose) { | 475 if (FLAG_gc_verbose) { |
| 502 PrintF("ResetLiveBytes:%p:%x->0\n", | 476 PrintF("ResetLiveBytes:%p:%x->0\n", |
| 503 static_cast<void*>(this), live_byte_count_); | 477 static_cast<void*>(this), live_byte_count_); |
| 504 } | 478 } |
| 505 live_byte_count_ = 0; | 479 live_byte_count_ = 0; |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 555 MemoryChunk::FromAddress(address)->IncrementLiveBytes(by); | 529 MemoryChunk::FromAddress(address)->IncrementLiveBytes(by); |
| 556 } | 530 } |
| 557 | 531 |
| 558 static void IncrementLiveBytesFromMutator(Address address, int by); | 532 static void IncrementLiveBytesFromMutator(Address address, int by); |
| 559 | 533 |
| 560 static const intptr_t kAlignment = | 534 static const intptr_t kAlignment = |
| 561 (static_cast<uintptr_t>(1) << kPageSizeBits); | 535 (static_cast<uintptr_t>(1) << kPageSizeBits); |
| 562 | 536 |
| 563 static const intptr_t kAlignmentMask = kAlignment - 1; | 537 static const intptr_t kAlignmentMask = kAlignment - 1; |
| 564 | 538 |
| 565 static const intptr_t kSizeOffset = 0; | 539 static const intptr_t kSizeOffset = kPointerSize + kPointerSize; |
| 566 | 540 |
| 567 static const intptr_t kLiveBytesOffset = | 541 static const intptr_t kLiveBytesOffset = |
| 568 kSizeOffset + kPointerSize + kPointerSize + kPointerSize + | 542 kSizeOffset + kPointerSize + kPointerSize + kPointerSize + |
| 569 kPointerSize + kPointerSize + | 543 kPointerSize + kPointerSize + |
| 570 kPointerSize + kPointerSize + kPointerSize + kIntSize; | 544 kPointerSize + kPointerSize + kPointerSize + kIntSize; |
| 571 | 545 |
| 572 static const size_t kSlotsBufferOffset = kLiveBytesOffset + kIntSize; | 546 static const size_t kSlotsBufferOffset = kLiveBytesOffset + kIntSize; |
| 573 | 547 |
| 574 static const size_t kWriteBarrierCounterOffset = | 548 static const size_t kWriteBarrierCounterOffset = |
| 575 kSlotsBufferOffset + kPointerSize + kPointerSize; | 549 kSlotsBufferOffset + kPointerSize + kPointerSize; |
| 576 | 550 |
| 577 static const size_t kHeaderSize = kWriteBarrierCounterOffset + kPointerSize + | 551 static const size_t kHeaderSize = kWriteBarrierCounterOffset + kPointerSize + |
| 578 kIntSize + kIntSize + kPointerSize + | 552 kIntSize + kIntSize + kPointerSize + |
| 579 5 * kPointerSize + | 553 5 * kPointerSize; |
| 580 kPointerSize + kPointerSize; | |
| 581 | 554 |
| 582 static const int kBodyOffset = | 555 static const int kBodyOffset = |
| 583 CODE_POINTER_ALIGN(kHeaderSize + Bitmap::kSize); | 556 CODE_POINTER_ALIGN(kHeaderSize + Bitmap::kSize); |
| 584 | 557 |
| 585 // The start offset of the object area in a page. Aligned to both maps and | 558 // The start offset of the object area in a page. Aligned to both maps and |
| 586 // code alignment to be suitable for both. Also aligned to 32 words because | 559 // code alignment to be suitable for both. Also aligned to 32 words because |
| 587 // the marking bitmap is arranged in 32 bit chunks. | 560 // the marking bitmap is arranged in 32 bit chunks. |
| 588 static const int kObjectStartAlignment = 32 * kPointerSize; | 561 static const int kObjectStartAlignment = 32 * kPointerSize; |
| 589 static const int kObjectStartOffset = kBodyOffset - 1 + | 562 static const int kObjectStartOffset = kBodyOffset - 1 + |
| 590 (kObjectStartAlignment - (kBodyOffset - 1) % kObjectStartAlignment); | 563 (kObjectStartAlignment - (kBodyOffset - 1) % kObjectStartAlignment); |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 642 | 615 |
| 643 inline Address MarkbitIndexToAddress(uint32_t index) { | 616 inline Address MarkbitIndexToAddress(uint32_t index) { |
| 644 return this->address() + (index << kPointerSizeLog2); | 617 return this->address() + (index << kPointerSizeLog2); |
| 645 } | 618 } |
| 646 | 619 |
| 647 void InsertAfter(MemoryChunk* other); | 620 void InsertAfter(MemoryChunk* other); |
| 648 void Unlink(); | 621 void Unlink(); |
| 649 | 622 |
| 650 inline Heap* heap() { return heap_; } | 623 inline Heap* heap() { return heap_; } |
| 651 | 624 |
| 652 static const int kFlagsOffset = kPointerSize; | 625 static const int kFlagsOffset = kPointerSize * 3; |
| 653 | 626 |
| 654 bool IsEvacuationCandidate() { return IsFlagSet(EVACUATION_CANDIDATE); } | 627 bool IsEvacuationCandidate() { return IsFlagSet(EVACUATION_CANDIDATE); } |
| 655 | 628 |
| 656 bool ShouldSkipEvacuationSlotRecording() { | 629 bool ShouldSkipEvacuationSlotRecording() { |
| 657 return (flags_ & kSkipEvacuationSlotsRecordingMask) != 0; | 630 return (flags_ & kSkipEvacuationSlotsRecordingMask) != 0; |
| 658 } | 631 } |
| 659 | 632 |
| 660 inline SkipList* skip_list() { | 633 inline SkipList* skip_list() { |
| 661 return skip_list_; | 634 return skip_list_; |
| 662 } | 635 } |
| (...skipping 28 matching lines...) Expand all Loading... |
| 691 bool CommitArea(size_t requested); | 664 bool CommitArea(size_t requested); |
| 692 | 665 |
| 693 // Approximate amount of physical memory committed for this chunk. | 666 // Approximate amount of physical memory committed for this chunk. |
| 694 size_t CommittedPhysicalMemory() { | 667 size_t CommittedPhysicalMemory() { |
| 695 return high_water_mark_; | 668 return high_water_mark_; |
| 696 } | 669 } |
| 697 | 670 |
| 698 static inline void UpdateHighWaterMark(Address mark); | 671 static inline void UpdateHighWaterMark(Address mark); |
| 699 | 672 |
| 700 protected: | 673 protected: |
| 674 MemoryChunk* next_chunk_; |
| 675 MemoryChunk* prev_chunk_; |
| 701 size_t size_; | 676 size_t size_; |
| 702 intptr_t flags_; | 677 intptr_t flags_; |
| 703 | 678 |
| 704 // Start and end of allocatable memory on this chunk. | 679 // Start and end of allocatable memory on this chunk. |
| 705 Address area_start_; | 680 Address area_start_; |
| 706 Address area_end_; | 681 Address area_end_; |
| 707 | 682 |
| 708 // If the chunk needs to remember its memory reservation, it is stored here. | 683 // If the chunk needs to remember its memory reservation, it is stored here. |
| 709 VirtualMemory reservation_; | 684 VirtualMemory reservation_; |
| 710 // The identity of the owning space. This is tagged as a failure pointer, but | 685 // The identity of the owning space. This is tagged as a failure pointer, but |
| 711 // no failure can be in an object, so this can be distinguished from any entry | 686 // no failure can be in an object, so this can be distinguished from any entry |
| 712 // in a fixed array. | 687 // in a fixed array. |
| 713 Address owner_; | 688 Address owner_; |
| 714 Heap* heap_; | 689 Heap* heap_; |
| 715 // Used by the store buffer to keep track of which pages to mark scan-on- | 690 // Used by the store buffer to keep track of which pages to mark scan-on- |
| 716 // scavenge. | 691 // scavenge. |
| 717 int store_buffer_counter_; | 692 int store_buffer_counter_; |
| 718 // Count of bytes marked black on page. | 693 // Count of bytes marked black on page. |
| 719 int live_byte_count_; | 694 int live_byte_count_; |
| 720 SlotsBuffer* slots_buffer_; | 695 SlotsBuffer* slots_buffer_; |
| 721 SkipList* skip_list_; | 696 SkipList* skip_list_; |
| 722 intptr_t write_barrier_counter_; | 697 intptr_t write_barrier_counter_; |
| 723 // Used by the incremental marker to keep track of the scanning progress in | 698 // Used by the incremental marker to keep track of the scanning progress in |
| 724 // large objects that have a progress bar and are scanned in increments. | 699 // large objects that have a progress bar and are scanned in increments. |
| 725 int progress_bar_; | 700 int progress_bar_; |
| 726 // Assuming the initial allocation on a page is sequential, | 701 // Assuming the initial allocation on a page is sequential, |
| 727 // count highest number of bytes ever allocated on the page. | 702 // count highest number of bytes ever allocated on the page. |
| 728 int high_water_mark_; | 703 int high_water_mark_; |
| 729 | 704 |
| 730 AtomicWord parallel_sweeping_; | 705 intptr_t parallel_sweeping_; |
| 731 | 706 |
| 732 // PagedSpace free-list statistics. | 707 // PagedSpace free-list statistics. |
| 733 intptr_t available_in_small_free_list_; | 708 intptr_t available_in_small_free_list_; |
| 734 intptr_t available_in_medium_free_list_; | 709 intptr_t available_in_medium_free_list_; |
| 735 intptr_t available_in_large_free_list_; | 710 intptr_t available_in_large_free_list_; |
| 736 intptr_t available_in_huge_free_list_; | 711 intptr_t available_in_huge_free_list_; |
| 737 intptr_t non_available_small_blocks_; | 712 intptr_t non_available_small_blocks_; |
| 738 | 713 |
| 739 static MemoryChunk* Initialize(Heap* heap, | 714 static MemoryChunk* Initialize(Heap* heap, |
| 740 Address base, | 715 Address base, |
| 741 size_t size, | 716 size_t size, |
| 742 Address area_start, | 717 Address area_start, |
| 743 Address area_end, | 718 Address area_end, |
| 744 Executability executable, | 719 Executability executable, |
| 745 Space* owner); | 720 Space* owner); |
| 746 | 721 |
| 747 private: | |
| 748 // next_chunk_ holds a pointer of type MemoryChunk | |
| 749 AtomicWord next_chunk_; | |
| 750 // prev_chunk_ holds a pointer of type MemoryChunk | |
| 751 AtomicWord prev_chunk_; | |
| 752 | |
| 753 friend class MemoryAllocator; | 722 friend class MemoryAllocator; |
| 754 }; | 723 }; |
| 755 | 724 |
| 756 | 725 |
| 757 STATIC_CHECK(sizeof(MemoryChunk) <= MemoryChunk::kHeaderSize); | 726 STATIC_CHECK(sizeof(MemoryChunk) <= MemoryChunk::kHeaderSize); |
| 758 | 727 |
| 759 | 728 |
| 760 // ----------------------------------------------------------------------------- | 729 // ----------------------------------------------------------------------------- |
| 761 // A page is a memory chunk of a size 1MB. Large object pages may be larger. | 730 // A page is a memory chunk of a size 1MB. Large object pages may be larger. |
| 762 // | 731 // |
| (...skipping 764 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1527 | 1496 |
| 1528 DISALLOW_IMPLICIT_CONSTRUCTORS(FreeListNode); | 1497 DISALLOW_IMPLICIT_CONSTRUCTORS(FreeListNode); |
| 1529 }; | 1498 }; |
| 1530 | 1499 |
| 1531 | 1500 |
| 1532 // The free list category holds a pointer to the top element and a pointer to | 1501 // The free list category holds a pointer to the top element and a pointer to |
| 1533 // the end element of the linked list of free memory blocks. | 1502 // the end element of the linked list of free memory blocks. |
| 1534 class FreeListCategory { | 1503 class FreeListCategory { |
| 1535 public: | 1504 public: |
| 1536 FreeListCategory() : | 1505 FreeListCategory() : |
| 1537 top_(0), | 1506 top_(NULL), |
| 1538 end_(NULL), | 1507 end_(NULL), |
| 1539 available_(0) {} | 1508 available_(0) {} |
| 1540 | 1509 |
| 1541 intptr_t Concatenate(FreeListCategory* category); | 1510 intptr_t Concatenate(FreeListCategory* category); |
| 1542 | 1511 |
| 1543 void Reset(); | 1512 void Reset(); |
| 1544 | 1513 |
| 1545 void Free(FreeListNode* node, int size_in_bytes); | 1514 void Free(FreeListNode* node, int size_in_bytes); |
| 1546 | 1515 |
| 1547 FreeListNode* PickNodeFromList(int *node_size); | 1516 FreeListNode* PickNodeFromList(int *node_size); |
| 1548 FreeListNode* PickNodeFromList(int size_in_bytes, int *node_size); | 1517 FreeListNode* PickNodeFromList(int size_in_bytes, int *node_size); |
| 1549 | 1518 |
| 1550 intptr_t EvictFreeListItemsInList(Page* p); | 1519 intptr_t EvictFreeListItemsInList(Page* p); |
| 1551 bool ContainsPageFreeListItemsInList(Page* p); | 1520 bool ContainsPageFreeListItemsInList(Page* p); |
| 1552 | 1521 |
| 1553 void RepairFreeList(Heap* heap); | 1522 void RepairFreeList(Heap* heap); |
| 1554 | 1523 |
| 1555 FreeListNode* top() const { | 1524 FreeListNode** GetTopAddress() { return &top_; } |
| 1556 return reinterpret_cast<FreeListNode*>(NoBarrier_Load(&top_)); | 1525 FreeListNode* top() const { return top_; } |
| 1557 } | 1526 void set_top(FreeListNode* top) { top_ = top; } |
| 1558 | |
| 1559 void set_top(FreeListNode* top) { | |
| 1560 NoBarrier_Store(&top_, reinterpret_cast<AtomicWord>(top)); | |
| 1561 } | |
| 1562 | 1527 |
| 1563 FreeListNode** GetEndAddress() { return &end_; } | 1528 FreeListNode** GetEndAddress() { return &end_; } |
| 1564 FreeListNode* end() const { return end_; } | 1529 FreeListNode* end() const { return end_; } |
| 1565 void set_end(FreeListNode* end) { end_ = end; } | 1530 void set_end(FreeListNode* end) { end_ = end; } |
| 1566 | 1531 |
| 1567 int* GetAvailableAddress() { return &available_; } | 1532 int* GetAvailableAddress() { return &available_; } |
| 1568 int available() const { return available_; } | 1533 int available() const { return available_; } |
| 1569 void set_available(int available) { available_ = available; } | 1534 void set_available(int available) { available_ = available; } |
| 1570 | 1535 |
| 1571 Mutex* mutex() { return &mutex_; } | 1536 Mutex* mutex() { return &mutex_; } |
| 1572 | 1537 |
| 1573 bool IsEmpty() { | 1538 bool IsEmpty() { |
| 1574 return top() == 0; | 1539 return top_ == NULL; |
| 1575 } | 1540 } |
| 1576 | 1541 |
| 1577 #ifdef DEBUG | 1542 #ifdef DEBUG |
| 1578 intptr_t SumFreeList(); | 1543 intptr_t SumFreeList(); |
| 1579 int FreeListLength(); | 1544 int FreeListLength(); |
| 1580 #endif | 1545 #endif |
| 1581 | 1546 |
| 1582 private: | 1547 private: |
| 1583 // top_ points to the top FreeListNode* in the free list category. | 1548 FreeListNode* top_; |
| 1584 AtomicWord top_; | |
| 1585 FreeListNode* end_; | 1549 FreeListNode* end_; |
| 1586 Mutex mutex_; | 1550 Mutex mutex_; |
| 1587 | 1551 |
| 1588 // Total available bytes in all blocks of this free list category. | 1552 // Total available bytes in all blocks of this free list category. |
| 1589 int available_; | 1553 int available_; |
| 1590 }; | 1554 }; |
| 1591 | 1555 |
| 1592 | 1556 |
| 1593 // The free list for the old space. The free list is organized in such a way | 1557 // The free list for the old space. The free list is organized in such a way |
| 1594 // as to encourage objects allocated around the same time to be near each | 1558 // as to encourage objects allocated around the same time to be near each |
| (...skipping 1383 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2978 } | 2942 } |
| 2979 // Must be small, since an iteration is used for lookup. | 2943 // Must be small, since an iteration is used for lookup. |
| 2980 static const int kMaxComments = 64; | 2944 static const int kMaxComments = 64; |
| 2981 }; | 2945 }; |
| 2982 #endif | 2946 #endif |
| 2983 | 2947 |
| 2984 | 2948 |
| 2985 } } // namespace v8::internal | 2949 } } // namespace v8::internal |
| 2986 | 2950 |
| 2987 #endif // V8_SPACES_H_ | 2951 #endif // V8_SPACES_H_ |
| OLD | NEW |