| 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 441 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 452 // Manage live byte count (count of bytes known to be live, | 452 // Manage live byte count (count of bytes known to be live, |
| 453 // because they are marked black). | 453 // because they are marked black). |
| 454 void ResetLiveBytes() { | 454 void ResetLiveBytes() { |
| 455 if (FLAG_gc_verbose) { | 455 if (FLAG_gc_verbose) { |
| 456 PrintF("ResetLiveBytes:%p:%x->0\n", | 456 PrintF("ResetLiveBytes:%p:%x->0\n", |
| 457 static_cast<void*>(this), live_byte_count_); | 457 static_cast<void*>(this), live_byte_count_); |
| 458 } | 458 } |
| 459 live_byte_count_ = 0; | 459 live_byte_count_ = 0; |
| 460 } | 460 } |
| 461 void IncrementLiveBytes(int by) { | 461 void IncrementLiveBytes(int by) { |
| 462 ASSERT_LE(static_cast<unsigned>(live_byte_count_), size_); | |
| 463 if (FLAG_gc_verbose) { | 462 if (FLAG_gc_verbose) { |
| 464 printf("UpdateLiveBytes:%p:%x%c=%x->%x\n", | 463 printf("UpdateLiveBytes:%p:%x%c=%x->%x\n", |
| 465 static_cast<void*>(this), live_byte_count_, | 464 static_cast<void*>(this), live_byte_count_, |
| 466 ((by < 0) ? '-' : '+'), ((by < 0) ? -by : by), | 465 ((by < 0) ? '-' : '+'), ((by < 0) ? -by : by), |
| 467 live_byte_count_ + by); | 466 live_byte_count_ + by); |
| 468 } | 467 } |
| 469 live_byte_count_ += by; | 468 live_byte_count_ += by; |
| 470 ASSERT_LE(static_cast<unsigned>(live_byte_count_), size_); | 469 ASSERT_LE(static_cast<unsigned>(live_byte_count_), size_); |
| 471 } | 470 } |
| 472 int LiveBytes() { | 471 int LiveBytes() { |
| (...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 635 INLINE(static Page* FromAddress(Address a)) { | 634 INLINE(static Page* FromAddress(Address a)) { |
| 636 return reinterpret_cast<Page*>(OffsetFrom(a) & ~kPageAlignmentMask); | 635 return reinterpret_cast<Page*>(OffsetFrom(a) & ~kPageAlignmentMask); |
| 637 } | 636 } |
| 638 | 637 |
| 639 // Returns the page containing an allocation top. Because an allocation | 638 // Returns the page containing an allocation top. Because an allocation |
| 640 // top address can be the upper bound of the page, we need to subtract | 639 // top address can be the upper bound of the page, we need to subtract |
| 641 // it with kPointerSize first. The address ranges from | 640 // it with kPointerSize first. The address ranges from |
| 642 // [page_addr + kObjectStartOffset .. page_addr + kPageSize]. | 641 // [page_addr + kObjectStartOffset .. page_addr + kPageSize]. |
| 643 INLINE(static Page* FromAllocationTop(Address top)) { | 642 INLINE(static Page* FromAllocationTop(Address top)) { |
| 644 Page* p = FromAddress(top - kPointerSize); | 643 Page* p = FromAddress(top - kPointerSize); |
| 645 ASSERT_PAGE_OFFSET(p->Offset(top)); | |
| 646 return p; | 644 return p; |
| 647 } | 645 } |
| 648 | 646 |
| 649 // Returns the next page in the chain of pages owned by a space. | 647 // Returns the next page in the chain of pages owned by a space. |
| 650 inline Page* next_page(); | 648 inline Page* next_page(); |
| 651 inline Page* prev_page(); | 649 inline Page* prev_page(); |
| 652 inline void set_next_page(Page* page); | 650 inline void set_next_page(Page* page); |
| 653 inline void set_prev_page(Page* page); | 651 inline void set_prev_page(Page* page); |
| 654 | 652 |
| 655 // Returns the start address of the object area in this page. | 653 // Returns the start address of the object area in this page. |
| 656 Address ObjectAreaStart() { return address() + kObjectStartOffset; } | 654 Address ObjectAreaStart() { return address() + kObjectStartOffset; } |
| 657 | 655 |
| 658 // Returns the end address (exclusive) of the object area in this page. | 656 // Returns the end address (exclusive) of the object area in this page. |
| 659 Address ObjectAreaEnd() { return address() + Page::kPageSize; } | 657 Address ObjectAreaEnd() { return address() + Page::kPageSize; } |
| 660 | 658 |
| 661 // Checks whether an address is page aligned. | 659 // Checks whether an address is page aligned. |
| 662 static bool IsAlignedToPageSize(Address a) { | 660 static bool IsAlignedToPageSize(Address a) { |
| 663 return 0 == (OffsetFrom(a) & kPageAlignmentMask); | 661 return 0 == (OffsetFrom(a) & kPageAlignmentMask); |
| 664 } | 662 } |
| 665 | 663 |
| 666 // Returns the offset of a given address to this page. | 664 // Returns the offset of a given address to this page. |
| 667 INLINE(int Offset(Address a)) { | 665 INLINE(int Offset(Address a)) { |
| 668 int offset = static_cast<int>(a - address()); | 666 int offset = static_cast<int>(a - address()); |
| 669 ASSERT_PAGE_OFFSET(offset); | |
| 670 return offset; | 667 return offset; |
| 671 } | 668 } |
| 672 | 669 |
| 673 // Returns the address for a given offset to the this page. | 670 // Returns the address for a given offset to the this page. |
| 674 Address OffsetToAddress(int offset) { | 671 Address OffsetToAddress(int offset) { |
| 675 ASSERT_PAGE_OFFSET(offset); | 672 ASSERT_PAGE_OFFSET(offset); |
| 676 return address() + offset; | 673 return address() + offset; |
| 677 } | 674 } |
| 678 | 675 |
| 679 // --------------------------------------------------------------------- | 676 // --------------------------------------------------------------------- |
| (...skipping 447 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1127 // Slow path of next(), goes into the next page. Returns false if the | 1124 // Slow path of next(), goes into the next page. Returns false if the |
| 1128 // iteration has ended. | 1125 // iteration has ended. |
| 1129 bool AdvanceToNextPage(); | 1126 bool AdvanceToNextPage(); |
| 1130 | 1127 |
| 1131 // Initializes fields. | 1128 // Initializes fields. |
| 1132 inline void Initialize(PagedSpace* owner, | 1129 inline void Initialize(PagedSpace* owner, |
| 1133 Address start, | 1130 Address start, |
| 1134 Address end, | 1131 Address end, |
| 1135 PageMode mode, | 1132 PageMode mode, |
| 1136 HeapObjectCallback size_func); | 1133 HeapObjectCallback size_func); |
| 1137 | |
| 1138 #ifdef DEBUG | |
| 1139 // Verifies whether fields have valid values. | |
| 1140 void Verify(); | |
| 1141 #endif | |
| 1142 }; | 1134 }; |
| 1143 | 1135 |
| 1144 | 1136 |
| 1145 // ----------------------------------------------------------------------------- | 1137 // ----------------------------------------------------------------------------- |
| 1146 // A PageIterator iterates the pages in a paged space. | 1138 // A PageIterator iterates the pages in a paged space. |
| 1147 | 1139 |
| 1148 class PageIterator BASE_EMBEDDED { | 1140 class PageIterator BASE_EMBEDDED { |
| 1149 public: | 1141 public: |
| 1150 explicit inline PageIterator(PagedSpace* space); | 1142 explicit inline PageIterator(PagedSpace* space); |
| 1151 | 1143 |
| (...skipping 582 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1734 Address address() { | 1726 Address address() { |
| 1735 return reinterpret_cast<Address>(this); | 1727 return reinterpret_cast<Address>(this); |
| 1736 } | 1728 } |
| 1737 | 1729 |
| 1738 // Finds the NewSpacePage containg the given address. | 1730 // Finds the NewSpacePage containg the given address. |
| 1739 static inline NewSpacePage* FromAddress(Address address_in_page) { | 1731 static inline NewSpacePage* FromAddress(Address address_in_page) { |
| 1740 Address page_start = | 1732 Address page_start = |
| 1741 reinterpret_cast<Address>(reinterpret_cast<uintptr_t>(address_in_page) & | 1733 reinterpret_cast<Address>(reinterpret_cast<uintptr_t>(address_in_page) & |
| 1742 ~Page::kPageAlignmentMask); | 1734 ~Page::kPageAlignmentMask); |
| 1743 NewSpacePage* page = reinterpret_cast<NewSpacePage*>(page_start); | 1735 NewSpacePage* page = reinterpret_cast<NewSpacePage*>(page_start); |
| 1744 ASSERT(page->InNewSpace()); | |
| 1745 return page; | 1736 return page; |
| 1746 } | 1737 } |
| 1747 | 1738 |
| 1748 // Find the page for a limit address. A limit address is either an address | 1739 // Find the page for a limit address. A limit address is either an address |
| 1749 // inside a page, or the address right after the last byte of a page. | 1740 // inside a page, or the address right after the last byte of a page. |
| 1750 static inline NewSpacePage* FromLimit(Address address_limit) { | 1741 static inline NewSpacePage* FromLimit(Address address_limit) { |
| 1751 return NewSpacePage::FromAddress(address_limit - 1); | 1742 return NewSpacePage::FromAddress(address_limit - 1); |
| 1752 } | 1743 } |
| 1753 | 1744 |
| 1754 private: | 1745 private: |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1811 bool ShrinkTo(int new_capacity); | 1802 bool ShrinkTo(int new_capacity); |
| 1812 | 1803 |
| 1813 // Returns the start address of the first page of the space. | 1804 // Returns the start address of the first page of the space. |
| 1814 Address space_start() { | 1805 Address space_start() { |
| 1815 ASSERT(anchor_.next_page() != &anchor_); | 1806 ASSERT(anchor_.next_page() != &anchor_); |
| 1816 return anchor_.next_page()->body(); | 1807 return anchor_.next_page()->body(); |
| 1817 } | 1808 } |
| 1818 | 1809 |
| 1819 // Returns the start address of the current page of the space. | 1810 // Returns the start address of the current page of the space. |
| 1820 Address page_low() { | 1811 Address page_low() { |
| 1821 ASSERT(anchor_.next_page() != &anchor_); | |
| 1822 return current_page_->body(); | 1812 return current_page_->body(); |
| 1823 } | 1813 } |
| 1824 | 1814 |
| 1825 // Returns one past the end address of the space. | 1815 // Returns one past the end address of the space. |
| 1826 Address space_end() { | 1816 Address space_end() { |
| 1827 return anchor_.prev_page()->body_limit(); | 1817 return anchor_.prev_page()->body_limit(); |
| 1828 } | 1818 } |
| 1829 | 1819 |
| 1830 // Returns one past the end address of the current page of the space. | 1820 // Returns one past the end address of the current page of the space. |
| 1831 Address page_high() { | 1821 Address page_high() { |
| (...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2077 static_cast<int>(top() - to_space_.page_low()); | 2067 static_cast<int>(top() - to_space_.page_low()); |
| 2078 } | 2068 } |
| 2079 | 2069 |
| 2080 // The same, but returning an int. We have to have the one that returns | 2070 // The same, but returning an int. We have to have the one that returns |
| 2081 // intptr_t because it is inherited, but if we know we are dealing with the | 2071 // intptr_t because it is inherited, but if we know we are dealing with the |
| 2082 // new space, which can't get as big as the other spaces then this is useful: | 2072 // new space, which can't get as big as the other spaces then this is useful: |
| 2083 int SizeAsInt() { return static_cast<int>(Size()); } | 2073 int SizeAsInt() { return static_cast<int>(Size()); } |
| 2084 | 2074 |
| 2085 // Return the current capacity of a semispace. | 2075 // Return the current capacity of a semispace. |
| 2086 intptr_t EffectiveCapacity() { | 2076 intptr_t EffectiveCapacity() { |
| 2087 ASSERT(to_space_.Capacity() == from_space_.Capacity()); | 2077 SLOW_ASSERT(to_space_.Capacity() == from_space_.Capacity()); |
| 2088 return (to_space_.Capacity() / Page::kPageSize) * Page::kObjectAreaSize; | 2078 return (to_space_.Capacity() / Page::kPageSize) * Page::kObjectAreaSize; |
| 2089 } | 2079 } |
| 2090 | 2080 |
| 2091 // Return the current capacity of a semispace. | 2081 // Return the current capacity of a semispace. |
| 2092 intptr_t Capacity() { | 2082 intptr_t Capacity() { |
| 2093 ASSERT(to_space_.Capacity() == from_space_.Capacity()); | 2083 ASSERT(to_space_.Capacity() == from_space_.Capacity()); |
| 2094 return to_space_.Capacity(); | 2084 return to_space_.Capacity(); |
| 2095 } | 2085 } |
| 2096 | 2086 |
| 2097 // Return the total amount of memory committed for new space. | 2087 // Return the total amount of memory committed for new space. |
| 2098 intptr_t CommittedMemory() { | 2088 intptr_t CommittedMemory() { |
| 2099 if (from_space_.is_committed()) return 2 * Capacity(); | 2089 if (from_space_.is_committed()) return 2 * Capacity(); |
| 2100 return Capacity(); | 2090 return Capacity(); |
| 2101 } | 2091 } |
| 2102 | 2092 |
| 2103 // Return the available bytes without growing or switching page in the | 2093 // Return the available bytes without growing. |
| 2104 // active semispace. | |
| 2105 intptr_t Available() { | 2094 intptr_t Available() { |
| 2106 return allocation_info_.limit - allocation_info_.top; | 2095 return Capacity() - Size(); |
| 2107 } | 2096 } |
| 2108 | 2097 |
| 2109 // Return the maximum capacity of a semispace. | 2098 // Return the maximum capacity of a semispace. |
| 2110 int MaximumCapacity() { | 2099 int MaximumCapacity() { |
| 2111 ASSERT(to_space_.MaximumCapacity() == from_space_.MaximumCapacity()); | 2100 ASSERT(to_space_.MaximumCapacity() == from_space_.MaximumCapacity()); |
| 2112 return to_space_.MaximumCapacity(); | 2101 return to_space_.MaximumCapacity(); |
| 2113 } | 2102 } |
| 2114 | 2103 |
| 2115 // Returns the initial capacity of a semispace. | 2104 // Returns the initial capacity of a semispace. |
| 2116 int InitialCapacity() { | 2105 int InitialCapacity() { |
| (...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2310 } | 2299 } |
| 2311 | 2300 |
| 2312 public: | 2301 public: |
| 2313 TRACK_MEMORY("OldSpace") | 2302 TRACK_MEMORY("OldSpace") |
| 2314 }; | 2303 }; |
| 2315 | 2304 |
| 2316 | 2305 |
| 2317 // For contiguous spaces, top should be in the space (or at the end) and limit | 2306 // For contiguous spaces, top should be in the space (or at the end) and limit |
| 2318 // should be the end of the space. | 2307 // should be the end of the space. |
| 2319 #define ASSERT_SEMISPACE_ALLOCATION_INFO(info, space) \ | 2308 #define ASSERT_SEMISPACE_ALLOCATION_INFO(info, space) \ |
| 2320 ASSERT((space).page_low() <= (info).top \ | 2309 SLOW_ASSERT((space).page_low() <= (info).top \ |
| 2321 && (info).top <= (space).page_high() \ | 2310 && (info).top <= (space).page_high() \ |
| 2322 && (info).limit <= (space).page_high()) | 2311 && (info).limit <= (space).page_high()) |
| 2323 | 2312 |
| 2324 | 2313 |
| 2325 // ----------------------------------------------------------------------------- | 2314 // ----------------------------------------------------------------------------- |
| 2326 // Old space for objects of a fixed size | 2315 // Old space for objects of a fixed size |
| 2327 | 2316 |
| 2328 class FixedSpace : public PagedSpace { | 2317 class FixedSpace : public PagedSpace { |
| 2329 public: | 2318 public: |
| 2330 FixedSpace(Heap* heap, | 2319 FixedSpace(Heap* heap, |
| 2331 intptr_t max_capacity, | 2320 intptr_t max_capacity, |
| 2332 AllocationSpace id, | 2321 AllocationSpace id, |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2440 | 2429 |
| 2441 // ----------------------------------------------------------------------------- | 2430 // ----------------------------------------------------------------------------- |
| 2442 // Large objects ( > Page::kMaxHeapObjectSize ) are allocated and managed by | 2431 // Large objects ( > Page::kMaxHeapObjectSize ) are allocated and managed by |
| 2443 // the large object space. A large object is allocated from OS heap with | 2432 // the large object space. A large object is allocated from OS heap with |
| 2444 // extra padding bytes (Page::kPageSize + Page::kObjectStartOffset). | 2433 // extra padding bytes (Page::kPageSize + Page::kObjectStartOffset). |
| 2445 // A large object always starts at Page::kObjectStartOffset to a page. | 2434 // A large object always starts at Page::kObjectStartOffset to a page. |
| 2446 // Large objects do not move during garbage collections. | 2435 // Large objects do not move during garbage collections. |
| 2447 | 2436 |
| 2448 class LargeObjectSpace : public Space { | 2437 class LargeObjectSpace : public Space { |
| 2449 public: | 2438 public: |
| 2450 LargeObjectSpace(Heap* heap, AllocationSpace id); | 2439 LargeObjectSpace(Heap* heap, intptr_t max_capacity, AllocationSpace id); |
| 2451 virtual ~LargeObjectSpace() {} | 2440 virtual ~LargeObjectSpace() {} |
| 2452 | 2441 |
| 2453 // Initializes internal data structures. | 2442 // Initializes internal data structures. |
| 2454 bool Setup(); | 2443 bool Setup(); |
| 2455 | 2444 |
| 2456 // Releases internal resources, frees objects in this space. | 2445 // Releases internal resources, frees objects in this space. |
| 2457 void TearDown(); | 2446 void TearDown(); |
| 2458 | 2447 |
| 2459 static intptr_t ObjectSizeFor(intptr_t chunk_size) { | 2448 static intptr_t ObjectSizeFor(intptr_t chunk_size) { |
| 2460 if (chunk_size <= (Page::kPageSize + Page::kObjectStartOffset)) return 0; | 2449 if (chunk_size <= (Page::kPageSize + Page::kObjectStartOffset)) return 0; |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2510 virtual void Verify(); | 2499 virtual void Verify(); |
| 2511 virtual void Print(); | 2500 virtual void Print(); |
| 2512 void ReportStatistics(); | 2501 void ReportStatistics(); |
| 2513 void CollectCodeStatistics(); | 2502 void CollectCodeStatistics(); |
| 2514 #endif | 2503 #endif |
| 2515 // Checks whether an address is in the object area in this space. It | 2504 // Checks whether an address is in the object area in this space. It |
| 2516 // iterates all objects in the space. May be slow. | 2505 // iterates all objects in the space. May be slow. |
| 2517 bool SlowContains(Address addr) { return !FindObject(addr)->IsFailure(); } | 2506 bool SlowContains(Address addr) { return !FindObject(addr)->IsFailure(); } |
| 2518 | 2507 |
| 2519 private: | 2508 private: |
| 2509 intptr_t max_capacity_; |
| 2520 // The head of the linked list of large object chunks. | 2510 // The head of the linked list of large object chunks. |
| 2521 LargePage* first_page_; | 2511 LargePage* first_page_; |
| 2522 intptr_t size_; // allocated bytes | 2512 intptr_t size_; // allocated bytes |
| 2523 int page_count_; // number of chunks | 2513 int page_count_; // number of chunks |
| 2524 intptr_t objects_size_; // size of objects | 2514 intptr_t objects_size_; // size of objects |
| 2525 | 2515 |
| 2526 friend class LargeObjectIterator; | 2516 friend class LargeObjectIterator; |
| 2527 | 2517 |
| 2528 public: | 2518 public: |
| 2529 TRACK_MEMORY("LargeObjectSpace") | 2519 TRACK_MEMORY("LargeObjectSpace") |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2619 } | 2609 } |
| 2620 // Must be small, since an iteration is used for lookup. | 2610 // Must be small, since an iteration is used for lookup. |
| 2621 static const int kMaxComments = 64; | 2611 static const int kMaxComments = 64; |
| 2622 }; | 2612 }; |
| 2623 #endif | 2613 #endif |
| 2624 | 2614 |
| 2625 | 2615 |
| 2626 } } // namespace v8::internal | 2616 } } // namespace v8::internal |
| 2627 | 2617 |
| 2628 #endif // V8_SPACES_H_ | 2618 #endif // V8_SPACES_H_ |
| OLD | NEW |