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' |