Chromium Code Reviews| Index: src/spaces.h |
| diff --git a/src/spaces.h b/src/spaces.h |
| index ae5a2d5a7ea11f6bbadccb687fa7d5c91d87178e..242968e9d343354e959e6ecdb6f8f70d626fbdd6 100644 |
| --- a/src/spaces.h |
| +++ b/src/spaces.h |
| @@ -371,6 +371,13 @@ class MemoryChunk { |
| return addr >= body() && addr < address() + size(); |
| } |
| + // Checks whether addr can be a limit of addresses in this page. |
| + // It's a limit if it's in the page, or if it's just after the |
| + // last byte of the page. |
| + bool ContainsLimit(Address addr) { |
| + return addr >= body() && addr <= address() + size(); |
| + } |
| + |
| enum MemoryChunkFlags { |
| IS_EXECUTABLE, |
| WAS_SWEPT_CONSERVATIVELY, |
| @@ -1329,7 +1336,7 @@ class PagedSpace : public Space { |
| bool EnsureCapacity(int capacity); |
| // The dummy page that anchors the linked list of pages. |
| - Page *anchor() { return &anchor_; } |
| + Page* anchor() { return &anchor_; } |
| #ifdef ENABLE_HEAP_PROTECTION |
| // Protect/unprotect the space by marking it read-only/writable. |
| @@ -1509,17 +1516,29 @@ class NewSpacePage : public MemoryChunk { |
| return reinterpret_cast<SemiSpace*>(owner()); |
| } |
| - private: |
| - NewSpacePage(SemiSpace* owner) { |
| - InitializeAsAnchor(owner); |
| - } |
| + bool is_anchor() { return !this->InNewSpace(); } |
| // Finds the NewSpacePage containg the given address. |
| - static NewSpacePage* FromAddress(Address address_in_page) { |
| + static inline NewSpacePage* FromAddress(Address address_in_page) { |
| Address page_start = |
| reinterpret_cast<Address>(reinterpret_cast<uintptr_t>(address_in_page) & |
| ~Page::kPageAlignmentMask); |
| - return reinterpret_cast<NewSpacePage*>(page_start); |
| + NewSpacePage* page = reinterpret_cast<NewSpacePage*>(page_start); |
| + ASSERT(page->InNewSpace()); |
| + return page; |
| + } |
| + |
| + // Find the page for a limit address. A limit address is either an address |
| + // inside a page, or the address right after the last byte of a page. |
| + static inline NewSpacePage* FromLimit(Address address_limit) { |
| + return NewSpacePage::FromAddress(address_limit - 1); |
| + } |
| + |
| + private: |
| + // Create a NewSpacePage object that is only used as anchor |
| + // for the doubly-linked list of real pages. |
| + explicit NewSpacePage(SemiSpace* owner) { |
| + InitializeAsAnchor(owner); |
| } |
| static NewSpacePage* Initialize(Heap* heap, |
| @@ -1528,7 +1547,7 @@ class NewSpacePage : public MemoryChunk { |
| // Intialize a fake NewSpacePage used as sentinel at the ends |
| // of a doubly-linked list of real NewSpacePages. |
| - // Only uses the prev/next links. |
| + // Only uses the prev/next links, and sets flags to not be in new-space. |
| void InitializeAsAnchor(SemiSpace* owner); |
| friend class SemiSpace; |
| @@ -1580,7 +1599,7 @@ class SemiSpace : public Space { |
| bool ShrinkTo(int new_capacity); |
| // Returns the start address of the first page of the space. |
| - Address low() { |
| + Address space_low() { |
| ASSERT(anchor_.next_page() != &anchor_); |
| return anchor_.next_page()->body(); |
| } |
| @@ -1592,11 +1611,22 @@ class SemiSpace : public Space { |
| } |
| // Returns one past the end address of the space. |
| - Address high() { |
| - // TODO(gc): Change when there is more than one page. |
| + Address space_high() { |
| + return anchor_.prev_page()->body_limit(); |
| + } |
| + |
| + // Returns one past the end address of the current page of the space. |
| + Address page_high() { |
| return current_page_->body_limit(); |
| } |
| + bool AdvancePage() { |
| + NewSpacePage* next_page = current_page_->next_page(); |
| + if (next_page == &anchor_) return false; |
| + current_page_ = next_page; |
| + return true; |
| + } |
| + |
| // Resets the space to using the first page. |
| void Reset(); |
| @@ -1606,7 +1636,8 @@ class SemiSpace : public Space { |
| // The offset of an address from the beginning of the space. |
|
Erik Corry
2011/06/07 08:49:55
We can't delete this function?
Lasse Reichstein
2011/06/07 09:36:06
Whaddayaknow, we can!
And there was much rejoycing
|
| int SpaceOffsetForAddress(Address addr) { |
| - return static_cast<int>(addr - low()); |
| + // TODO(gc): This generally won't make sense for paged new-space. |
| + return static_cast<int>(addr - space_low()); |
| } |
| // If we don't have these here then SemiSpace will be abstract. However |
| @@ -1625,7 +1656,7 @@ class SemiSpace : public Space { |
| bool Commit(); |
| bool Uncommit(); |
| - NewSpacePage* first_page() { return NewSpacePage::FromAddress(start_); } |
| + NewSpacePage* first_page() { return anchor_.next_page(); } |
| NewSpacePage* current_page() { return current_page_; } |
| #ifdef ENABLE_HEAP_PROTECTION |
| @@ -1637,6 +1668,7 @@ class SemiSpace : public Space { |
| #ifdef DEBUG |
| virtual void Print(); |
| virtual void Verify(); |
| + static void ValidateRange(Address from, Address to); |
| #endif |
| // Returns the current capacity of the semi space. |
| @@ -1657,6 +1689,8 @@ class SemiSpace : public Space { |
| // Copies the flags into the masked positions on all pages in the space. |
| void FlipPages(intptr_t flags, intptr_t flag_mask); |
| + NewSpacePage* anchor() { return &anchor_; } |
| + |
| // The current and maximum capacity of the space. |
| int capacity_; |
| int maximum_capacity_; |
| @@ -1678,6 +1712,8 @@ class SemiSpace : public Space { |
| NewSpacePage anchor_; |
| NewSpacePage* current_page_; |
| + friend class SemiSpaceIterator; |
| + friend class NewSpacePageIterator; |
| public: |
| TRACK_MEMORY("SemiSpace") |
| }; |
| @@ -1693,15 +1729,26 @@ class SemiSpaceIterator : public ObjectIterator { |
| // Create an iterator over the objects in the given space. If no start |
| // address is given, the iterator starts from the bottom of the space. If |
| // no size function is given, the iterator calls Object::Size(). |
| + |
| + // Iterate over all of allocated to-space. |
| explicit SemiSpaceIterator(NewSpace* space); |
| + // Iterate over all of allocated to-space, with a custome size function. |
| SemiSpaceIterator(NewSpace* space, HeapObjectCallback size_func); |
| + // Iterate over part of allocated to-space, from start to the end |
| + // of allocation. |
| SemiSpaceIterator(NewSpace* space, Address start); |
| + // Iterate from one address to another in the same semi-space. |
| + SemiSpaceIterator(Address from, Address to); |
| HeapObject* Next() { |
| + if (current_ == limit_) return NULL; |
| if (current_ == current_page_limit_) { |
| - // TODO(gc): Add something here when we have more than one page. |
| + NewSpacePage* page = NewSpacePage::FromAddress(current_ - 1); |
| + page = page->next_page(); |
| + ASSERT(!page->is_anchor()); |
| + current_ = page->body(); |
| + if (current_ == limit_) return NULL; |
| } |
| - if (current_ == limit_) return NULL; |
| HeapObject* object = HeapObject::FromAddress(current_); |
| int size = (size_func_ == NULL) ? object->Size() : size_func_(object); |
| @@ -1714,13 +1761,10 @@ class SemiSpaceIterator : public ObjectIterator { |
| virtual HeapObject* next_object() { return Next(); } |
| private: |
| - void Initialize(NewSpace* space, |
| - Address start, |
| + void Initialize(Address start, |
| Address end, |
| HeapObjectCallback size_func); |
| - // The semispace. |
| - SemiSpace* space_; |
| // The current iteration point. |
| Address current_; |
| // The end of the current page. |
| @@ -1733,6 +1777,30 @@ class SemiSpaceIterator : public ObjectIterator { |
| // ----------------------------------------------------------------------------- |
| +// A PageIterator iterates the pages in a semi-space. |
| +class NewSpacePageIterator BASE_EMBEDDED { |
| + public: |
| + // Make an iterator that runs over all pages in the given semispace, |
| + // even those not used in allocation. |
| + explicit inline NewSpacePageIterator(SemiSpace* space); |
| + // Make iterator that iterates from the page containing start |
| + // to the page that contains limit in the same semispace. |
| + inline NewSpacePageIterator(Address start, Address limit); |
| + |
| + inline bool has_next(); |
| + inline NewSpacePage* next(); |
| + |
| + private: |
| + NewSpacePage* prev_page_; // Previous page returned. |
| + // Next page that will be returned. Cached here so that we can use this |
| + // iterator for operations that deallocate pages. |
| + NewSpacePage* next_page_; |
| + // Last page returned. |
| + NewSpacePage* last_page_; |
| +}; |
| + |
| + |
| +// ----------------------------------------------------------------------------- |
| // The young generation space. |
| // |
| // The new space consists of a contiguous pair of semispaces. It simply |
| @@ -1818,8 +1886,11 @@ class NewSpace : public Space { |
| return Capacity(); |
| } |
| - // Return the available bytes without growing in the active semispace. |
| - intptr_t Available() { return Capacity() - Size(); } |
| + // Return the available bytes without growing or switching page in the |
| + // active semispace. |
| + intptr_t Available() { |
| + return allocation_info_.limit - allocation_info_.top; |
| + } |
| // Return the maximum capacity of a semispace. |
| int MaximumCapacity() { |
| @@ -1836,7 +1907,7 @@ class NewSpace : public Space { |
| // Return the address of the allocation pointer in the active semispace. |
| Address top() { return allocation_info_.top; } |
| // Return the address of the first object in the active semispace. |
| - Address bottom() { return to_space_.low(); } |
| + Address bottom() { return to_space_.space_low(); } |
| // Get the age mark of the inactive semispace. |
| Address age_mark() { return from_space_.age_mark(); } |
| @@ -1873,7 +1944,7 @@ class NewSpace : public Space { |
| void LowerInlineAllocationLimit(intptr_t step) { |
| inline_alloction_limit_step_ = step; |
| if (step == 0) { |
| - allocation_info_.limit = to_space_.high(); |
| + allocation_info_.limit = to_space_.page_high(); |
| } else { |
| allocation_info_.limit = Min( |
| allocation_info_.top + inline_alloction_limit_step_, |
| @@ -1882,14 +1953,16 @@ class NewSpace : public Space { |
| top_on_previous_step_ = allocation_info_.top; |
| } |
| - // Get the extent of the inactive semispace (for use as a marking stack). |
| - Address FromSpaceLow() { return from_space_.low(); } |
| - Address FromSpaceHigh() { return from_space_.high(); } |
| + // Get the extent of the inactive semispace (for use as a marking stack, |
| + // or to zap it). |
| + Address FromSpacePageLow() { return from_space_.page_low(); } |
| + Address FromSpaceLow() { return from_space_.space_low(); } |
| + Address FromSpaceHigh() { return from_space_.space_high(); } |
| // Get the extent of the active semispace (to sweep newly copied objects |
| // during a scavenge collection). |
| - Address ToSpaceLow() { return to_space_.low(); } |
| - Address ToSpaceHigh() { return to_space_.high(); } |
| + Address ToSpaceLow() { return to_space_.space_low(); } |
|
Erik Corry
2011/06/07 08:49:55
This does not really make sense, at least for the
Lasse Reichstein
2011/06/07 09:36:06
Did it ever? The to_space_.high() value is the end
|
| + Address ToSpaceHigh() { return to_space_.space_high(); } |
| // Offsets from the beginning of the semispaces. |
| int ToSpaceOffsetForAddress(Address a) { |
| @@ -1924,6 +1997,8 @@ class NewSpace : public Space { |
| return FromSpaceContains(address); |
| } |
|
Erik Corry
2011/06/07 08:49:55
Comment on what the return value means.
Lasse Reichstein
2011/06/07 09:36:06
Done.
|
| + bool AddFreshPage(); |
| + |
| virtual bool ReserveSpace(int bytes); |
| // Resizes a sequential string which must be the most recent thing that was |
| @@ -1983,6 +2058,9 @@ class NewSpace : public Space { |
| } |
| private: |
| + // Update allocation info to match the current to-space page. |
| + void UpdateAllocationInfo(); |
| + |
| Address chunk_base_; |
| uintptr_t chunk_size_; |
| @@ -2055,9 +2133,9 @@ class OldSpace : public PagedSpace { |
| // For contiguous spaces, top should be in the space (or at the end) and limit |
| // should be the end of the space. |
| #define ASSERT_SEMISPACE_ALLOCATION_INFO(info, space) \ |
| - ASSERT((space).low() <= (info).top \ |
| - && (info).top <= (space).high() \ |
| - && (info).limit <= (space).high()) |
| + ASSERT((space).page_low() <= (info).top \ |
| + && (info).top <= (space).page_high() \ |
| + && (info).limit <= (space).page_high()) |
| // ----------------------------------------------------------------------------- |