| Index: src/heap/spaces.h
|
| diff --git a/src/heap/spaces.h b/src/heap/spaces.h
|
| index 41e0727a3fbe9a634dff2bde325fd996b9951de9..b15a3c050e303eb148adc4a0e1539996943ac4b1 100644
|
| --- a/src/heap/spaces.h
|
| +++ b/src/heap/spaces.h
|
| @@ -234,10 +234,14 @@ class MemoryChunk {
|
| IS_EXECUTABLE = 1u << 0,
|
| POINTERS_TO_HERE_ARE_INTERESTING = 1u << 1,
|
| POINTERS_FROM_HERE_ARE_INTERESTING = 1u << 2,
|
| +
|
| // A page in new space has one of the next to flags set.
|
| IN_FROM_SPACE = 1u << 3,
|
| IN_TO_SPACE = 1u << 4,
|
| - NEW_SPACE_BELOW_AGE_MARK = 1u << 5,
|
| + // |IN_INTERMEDIATE_GENERATION|: Flag indicates whether this page contains
|
| + // objects that have already been copied once.
|
| + IN_INTERMEDIATE_GENERATION = 1u << 5,
|
| +
|
| EVACUATION_CANDIDATE = 1u << 6,
|
| NEVER_EVACUATE = 1u << 7,
|
|
|
| @@ -559,6 +563,10 @@ class MemoryChunk {
|
|
|
| bool InFromSpace() { return IsFlagSet(IN_FROM_SPACE); }
|
|
|
| + bool InIntermediateGeneration() {
|
| + return IsFlagSet(IN_INTERMEDIATE_GENERATION);
|
| + }
|
| +
|
| MemoryChunk* next_chunk() { return next_chunk_.Value(); }
|
|
|
| MemoryChunk* prev_chunk() { return prev_chunk_.Value(); }
|
| @@ -2224,7 +2232,6 @@ class SemiSpace : public Space {
|
| current_capacity_(0),
|
| maximum_capacity_(0),
|
| minimum_capacity_(0),
|
| - age_mark_(nullptr),
|
| committed_(false),
|
| id_(semispace),
|
| anchor_(this),
|
| @@ -2293,10 +2300,6 @@ class SemiSpace : public Space {
|
| void RemovePage(Page* page);
|
| void PrependPage(Page* page);
|
|
|
| - // Age mark accessors.
|
| - Address age_mark() { return age_mark_; }
|
| - void set_age_mark(Address mark);
|
| -
|
| // Returns the current capacity of the semispace.
|
| int current_capacity() { return current_capacity_; }
|
|
|
| @@ -2363,9 +2366,6 @@ class SemiSpace : public Space {
|
| // The minimum capacity for the space. A space cannot shrink below this size.
|
| int minimum_capacity_;
|
|
|
| - // Used to govern object promotion during mark-compact collection.
|
| - Address age_mark_;
|
| -
|
| bool committed_;
|
| SemiSpaceId id_;
|
|
|
| @@ -2416,7 +2416,8 @@ class NewSpace : public Space {
|
| reservation_(),
|
| top_on_previous_step_(0),
|
| allocated_histogram_(nullptr),
|
| - promoted_histogram_(nullptr) {}
|
| + promoted_histogram_(nullptr),
|
| + fragmentation_in_intermediate_generation_(0) {}
|
|
|
| inline bool Contains(HeapObject* o);
|
| inline bool ContainsSlow(Address a);
|
| @@ -2449,6 +2450,11 @@ class NewSpace : public Space {
|
| static_cast<int>(top() - to_space_.page_low());
|
| }
|
|
|
| + intptr_t SizeOfObjects() override {
|
| + return Size() -
|
| + static_cast<intptr_t>(fragmentation_in_intermediate_generation_);
|
| + }
|
| +
|
| // The same, but returning an int. We have to have the one that returns
|
| // intptr_t because it is inherited, but if we know we are dealing with the
|
| // new space, which can't get as big as the other spaces then this is useful:
|
| @@ -2485,42 +2491,7 @@ class NewSpace : public Space {
|
| // Return the available bytes without growing.
|
| intptr_t Available() override { return Capacity() - Size(); }
|
|
|
| - size_t AllocatedSinceLastGC() {
|
| - bool seen_age_mark = false;
|
| - Address age_mark = to_space_.age_mark();
|
| - Page* current_page = to_space_.first_page();
|
| - Page* age_mark_page = Page::FromAddress(age_mark);
|
| - Page* last_page = Page::FromAddress(top() - kPointerSize);
|
| - if (age_mark_page == last_page) {
|
| - if (top() - age_mark >= 0) {
|
| - return top() - age_mark;
|
| - }
|
| - // Top was reset at some point, invalidating this metric.
|
| - return 0;
|
| - }
|
| - while (current_page != last_page) {
|
| - if (current_page == age_mark_page) {
|
| - seen_age_mark = true;
|
| - break;
|
| - }
|
| - current_page = current_page->next_page();
|
| - }
|
| - if (!seen_age_mark) {
|
| - // Top was reset at some point, invalidating this metric.
|
| - return 0;
|
| - }
|
| - intptr_t allocated = age_mark_page->area_end() - age_mark;
|
| - DCHECK_EQ(current_page, age_mark_page);
|
| - current_page = age_mark_page->next_page();
|
| - while (current_page != last_page) {
|
| - allocated += Page::kAllocatableMemory;
|
| - current_page = current_page->next_page();
|
| - }
|
| - allocated += top() - current_page->area_start();
|
| - DCHECK_LE(0, allocated);
|
| - DCHECK_LE(allocated, Size());
|
| - return static_cast<size_t>(allocated);
|
| - }
|
| + inline size_t AllocatedSinceLastGC();
|
|
|
| void MovePageFromSpaceToSpace(Page* page) {
|
| DCHECK(page->InFromSpace());
|
| @@ -2559,10 +2530,8 @@ class NewSpace : public Space {
|
| // Return the address of the first object in the active semispace.
|
| Address bottom() { return to_space_.space_start(); }
|
|
|
| - // Get the age mark of the inactive semispace.
|
| - Address age_mark() { return from_space_.age_mark(); }
|
| - // Set the age mark in the active semispace.
|
| - void set_age_mark(Address mark) { to_space_.set_age_mark(mark); }
|
| + // Seal the intermediate generation of the active semispace.
|
| + void SealIntermediateGeneration();
|
|
|
| // The allocation top and limit address.
|
| Address* allocation_top_address() { return allocation_info_.top_address(); }
|
| @@ -2587,6 +2556,10 @@ class NewSpace : public Space {
|
| // Reset the allocation pointer to the beginning of the active semispace.
|
| void ResetAllocationInfo();
|
|
|
| + void SetAllocationInfo(Address top, Address limit) {
|
| + allocation_info_.Reset(top, limit);
|
| + }
|
| +
|
| // When inline allocation stepping is active, either because of incremental
|
| // marking, idle scavenge, or allocation statistics gathering, we 'interrupt'
|
| // inline allocation every once in a while. This is done by setting
|
| @@ -2695,6 +2668,8 @@ class NewSpace : public Space {
|
| HistogramInfo* allocated_histogram_;
|
| HistogramInfo* promoted_histogram_;
|
|
|
| + size_t fragmentation_in_intermediate_generation_;
|
| +
|
| bool EnsureAllocation(int size_in_bytes, AllocationAlignment alignment);
|
|
|
| // If we are doing inline allocation in steps, this method performs the 'step'
|
|
|