[heap] introduce SpaceWithLinearArea class

NewSpace and OldSpace have linear allocation areas, but presently the
implementation doesn't share any code and there are subtle differences.
This CL introduces a superclass 'SpaceWithLinearArea' that will be used
to refactor and share code.

Change-Id: I741e6a6ebb9e75c111287214fd1f555fba62c452
Reviewed-on: https://chromium-review.googlesource.com/809504
Reviewed-by: Ulan Degenbaev <ulan@chromium.org>
Commit-Queue: Ali Ijaz Sheikh <ofrobots@google.com>
Cr-Commit-Position: refs/heads/master@{#49890}
This commit is contained in:
Ali Ijaz Sheikh 2017-12-05 10:42:45 -08:00 committed by Commit Bot
parent f9aacf1584
commit 8dd405e39a
2 changed files with 59 additions and 111 deletions

View File

@ -1374,14 +1374,11 @@ intptr_t Space::GetNextInlineAllocationStepSize() {
PagedSpace::PagedSpace(Heap* heap, AllocationSpace space, PagedSpace::PagedSpace(Heap* heap, AllocationSpace space,
Executability executable) Executability executable)
: Space(heap, space, executable), : SpaceWithLinearArea(heap, space, executable),
anchor_(this), anchor_(this),
free_list_(this), free_list_(this) {
top_on_previous_step_(0) {
area_size_ = MemoryAllocator::PageAreaSize(space); area_size_ = MemoryAllocator::PageAreaSize(space);
accounting_stats_.Clear(); accounting_stats_.Clear();
allocation_info_.Reset(nullptr, nullptr);
} }
@ -1641,6 +1638,7 @@ Address PagedSpace::ComputeLimit(Address start, Address end,
} }
} }
// TODO(ofrobots): refactor this code into SpaceWithLinearArea
void PagedSpace::StartNextInlineAllocationStep() { void PagedSpace::StartNextInlineAllocationStep() {
if (!allocation_observers_paused_ && SupportsInlineAllocation()) { if (!allocation_observers_paused_ && SupportsInlineAllocation()) {
top_on_previous_step_ = allocation_observers_.empty() ? 0 : top(); top_on_previous_step_ = allocation_observers_.empty() ? 0 : top();
@ -2150,7 +2148,7 @@ bool NewSpace::EnsureAllocation(int size_in_bytes,
return true; return true;
} }
// TODO(ofrobots): refactor this code into SpaceWithLinearArea
void NewSpace::StartNextInlineAllocationStep() { void NewSpace::StartNextInlineAllocationStep() {
if (!allocation_observers_paused_) { if (!allocation_observers_paused_) {
top_on_previous_step_ = top_on_previous_step_ =
@ -2159,26 +2157,13 @@ void NewSpace::StartNextInlineAllocationStep() {
} }
} }
// TODO(ofrobots): refactor into SpaceWithLinearArea void SpaceWithLinearArea::AddAllocationObserver(AllocationObserver* observer) {
void NewSpace::AddAllocationObserver(AllocationObserver* observer) {
InlineAllocationStep(top(), top(), nullptr, 0); InlineAllocationStep(top(), top(), nullptr, 0);
Space::AddAllocationObserver(observer); Space::AddAllocationObserver(observer);
} }
// TODO(ofrobots): refactor into SpaceWithLinearArea void SpaceWithLinearArea::RemoveAllocationObserver(
void PagedSpace::AddAllocationObserver(AllocationObserver* observer) { AllocationObserver* observer) {
InlineAllocationStep(top(), top(), nullptr, 0);
Space::AddAllocationObserver(observer);
}
// TODO(ofrobots): refactor into SpaceWithLinearArea
void NewSpace::RemoveAllocationObserver(AllocationObserver* observer) {
InlineAllocationStep(top(), top(), nullptr, 0);
Space::RemoveAllocationObserver(observer);
}
// TODO(ofrobots): refactor into SpaceWithLinearArea
void PagedSpace::RemoveAllocationObserver(AllocationObserver* observer) {
InlineAllocationStep(top(), top(), nullptr, 0); InlineAllocationStep(top(), top(), nullptr, 0);
Space::RemoveAllocationObserver(observer); Space::RemoveAllocationObserver(observer);
} }
@ -2193,43 +2178,22 @@ void NewSpace::PauseAllocationObservers() {
void PagedSpace::PauseAllocationObservers() { void PagedSpace::PauseAllocationObservers() {
// Do a step to account for memory allocated so far. // Do a step to account for memory allocated so far.
// TODO(ofrobots): Refactor into SpaceWithLinearArea. Note subtle difference
// from NewSpace version.
InlineAllocationStep(top(), nullptr, nullptr, 0); InlineAllocationStep(top(), nullptr, nullptr, 0);
Space::PauseAllocationObservers(); Space::PauseAllocationObservers();
top_on_previous_step_ = 0; top_on_previous_step_ = 0;
} }
void NewSpace::ResumeAllocationObservers() { void SpaceWithLinearArea::ResumeAllocationObservers() {
DCHECK_NULL(top_on_previous_step_); DCHECK_NULL(top_on_previous_step_);
Space::ResumeAllocationObservers(); Space::ResumeAllocationObservers();
StartNextInlineAllocationStep(); StartNextInlineAllocationStep();
} }
// TODO(ofrobots): refactor into SpaceWithLinearArea void SpaceWithLinearArea::InlineAllocationStep(Address top, Address new_top,
void PagedSpace::ResumeAllocationObservers() { Address soon_object,
DCHECK_NULL(top_on_previous_step_); size_t size) {
Space::ResumeAllocationObservers();
StartNextInlineAllocationStep();
}
// TODO(ofrobots): refactor into SpaceWithLinearArea
void PagedSpace::InlineAllocationStep(Address top, Address new_top,
Address soon_object, size_t size) {
if (top_on_previous_step_) {
if (top < top_on_previous_step_) {
// Generated code decreased the top pointer to do folded allocations.
DCHECK_NOT_NULL(top);
DCHECK_EQ(Page::FromAllocationAreaAddress(top),
Page::FromAllocationAreaAddress(top_on_previous_step_));
top_on_previous_step_ = top;
}
int bytes_allocated = static_cast<int>(top - top_on_previous_step_);
AllocationStep(bytes_allocated, soon_object, static_cast<int>(size));
top_on_previous_step_ = new_top;
}
}
void NewSpace::InlineAllocationStep(Address top, Address new_top,
Address soon_object, size_t size) {
if (top_on_previous_step_) { if (top_on_previous_step_) {
if (top < top_on_previous_step_) { if (top < top_on_previous_step_) {
// Generated code decreased the top pointer to do folded allocations. // Generated code decreased the top pointer to do folded allocations.

View File

@ -1966,7 +1966,50 @@ class LocalAllocationBuffer {
AllocationInfo allocation_info_; AllocationInfo allocation_info_;
}; };
class V8_EXPORT_PRIVATE PagedSpace : NON_EXPORTED_BASE(public Space) { class SpaceWithLinearArea : public Space {
public:
SpaceWithLinearArea(Heap* heap, AllocationSpace id, Executability executable)
: Space(heap, id, executable), top_on_previous_step_(0) {
allocation_info_.Reset(nullptr, nullptr);
}
// Returns the allocation pointer in this space.
Address top() { return allocation_info_.top(); }
Address limit() { return allocation_info_.limit(); }
// The allocation top address.
Address* allocation_top_address() { return allocation_info_.top_address(); }
// The allocation limit address.
Address* allocation_limit_address() {
return allocation_info_.limit_address();
}
// If we are doing inline allocation in steps, this method performs the 'step'
// operation. top is the memory address of the bump pointer at the last
// inline allocation (i.e. it determines the numbers of bytes actually
// allocated since the last step.) new_top is the address of the bump pointer
// where the next byte is going to be allocated from. top and new_top may be
// different when we cross a page boundary or reset the space.
// TODO(ofrobots): clarify the precise difference between this and
// Space::AllocationStep.
void InlineAllocationStep(Address top, Address new_top, Address soon_object,
size_t size);
V8_EXPORT_PRIVATE void AddAllocationObserver(
AllocationObserver* observer) override;
V8_EXPORT_PRIVATE void RemoveAllocationObserver(
AllocationObserver* observer) override;
V8_EXPORT_PRIVATE void ResumeAllocationObservers() override;
protected:
// TODO(ofrobots): make these private after refactoring is complete.
AllocationInfo allocation_info_;
Address top_on_previous_step_;
};
class V8_EXPORT_PRIVATE PagedSpace
: NON_EXPORTED_BASE(public SpaceWithLinearArea) {
public: public:
typedef PageIterator iterator; typedef PageIterator iterator;
@ -2038,18 +2081,6 @@ class V8_EXPORT_PRIVATE PagedSpace : NON_EXPORTED_BASE(public Space) {
// due to being too small to use for allocation. // due to being too small to use for allocation.
virtual size_t Waste() { return free_list_.wasted_bytes(); } virtual size_t Waste() { return free_list_.wasted_bytes(); }
// Returns the allocation pointer in this space.
Address top() { return allocation_info_.top(); }
Address limit() { return allocation_info_.limit(); }
// The allocation top address.
Address* allocation_top_address() { return allocation_info_.top_address(); }
// The allocation limit address.
Address* allocation_limit_address() {
return allocation_info_.limit_address();
}
enum UpdateSkipList { UPDATE_SKIP_LIST, IGNORE_SKIP_LIST }; enum UpdateSkipList { UPDATE_SKIP_LIST, IGNORE_SKIP_LIST };
// Allocate the requested number of bytes in the space if possible, return a // Allocate the requested number of bytes in the space if possible, return a
@ -2090,13 +2121,7 @@ class V8_EXPORT_PRIVATE PagedSpace : NON_EXPORTED_BASE(public Space) {
void ResetFreeList() { free_list_.Reset(); } void ResetFreeList() { free_list_.Reset(); }
void AddAllocationObserver(AllocationObserver* observer) override;
void RemoveAllocationObserver(AllocationObserver* observer) override;
void PauseAllocationObservers() override; void PauseAllocationObservers() override;
void ResumeAllocationObservers() override;
void InlineAllocationStep(Address top, Address new_top, Address soon_object,
size_t size);
// Empty space allocation info, returning unused area to free list. // Empty space allocation info, returning unused area to free list.
void EmptyAllocationInfo(); void EmptyAllocationInfo();
@ -2271,14 +2296,9 @@ class V8_EXPORT_PRIVATE PagedSpace : NON_EXPORTED_BASE(public Space) {
// The space's free list. // The space's free list.
FreeList free_list_; FreeList free_list_;
// Normal allocation information.
AllocationInfo allocation_info_;
// Mutex guarding any concurrent access to the space. // Mutex guarding any concurrent access to the space.
base::Mutex space_mutex_; base::Mutex space_mutex_;
Address top_on_previous_step_;
friend class IncrementalMarking; friend class IncrementalMarking;
friend class MarkCompactCollector; friend class MarkCompactCollector;
@ -2489,13 +2509,12 @@ class SemiSpaceIterator : public ObjectIterator {
// The new space consists of a contiguous pair of semispaces. It simply // The new space consists of a contiguous pair of semispaces. It simply
// forwards most functions to the appropriate semispace. // forwards most functions to the appropriate semispace.
class NewSpace : public Space { class NewSpace : public SpaceWithLinearArea {
public: public:
typedef PageIterator iterator; typedef PageIterator iterator;
explicit NewSpace(Heap* heap) explicit NewSpace(Heap* heap)
: Space(heap, NEW_SPACE, NOT_EXECUTABLE), : SpaceWithLinearArea(heap, NEW_SPACE, NOT_EXECUTABLE),
top_on_previous_step_(0),
to_space_(heap, kToSpace), to_space_(heap, kToSpace),
from_space_(heap, kFromSpace), from_space_(heap, kFromSpace),
reservation_(), reservation_(),
@ -2620,18 +2639,6 @@ class NewSpace : public Space {
return to_space_.minimum_capacity(); return to_space_.minimum_capacity();
} }
// Return the address of the allocation pointer in the active semispace.
Address top() {
DCHECK(to_space_.current_page()->ContainsLimit(allocation_info_.top()));
return allocation_info_.top();
}
// Return the address of the allocation pointer limit in the active semispace.
Address limit() {
DCHECK(to_space_.current_page()->ContainsLimit(allocation_info_.limit()));
return allocation_info_.limit();
}
void ResetOriginalTop() { void ResetOriginalTop() {
DCHECK_GE(top(), original_top()); DCHECK_GE(top(), original_top());
DCHECK_LE(top(), original_limit()); DCHECK_LE(top(), original_limit());
@ -2649,14 +2656,6 @@ class NewSpace : public Space {
// Set the age mark in the active semispace. // Set the age mark in the active semispace.
void set_age_mark(Address mark) { to_space_.set_age_mark(mark); } void set_age_mark(Address mark) { to_space_.set_age_mark(mark); }
// The allocation top and limit address.
Address* allocation_top_address() { return allocation_info_.top_address(); }
// The allocation limit address.
Address* allocation_limit_address() {
return allocation_info_.limit_address();
}
MUST_USE_RESULT INLINE(AllocationResult AllocateRawAligned( MUST_USE_RESULT INLINE(AllocationResult AllocateRawAligned(
int size_in_bytes, AllocationAlignment alignment)); int size_in_bytes, AllocationAlignment alignment));
@ -2746,10 +2745,7 @@ class NewSpace : public Space {
SemiSpace* active_space() { return &to_space_; } SemiSpace* active_space() { return &to_space_; }
void AddAllocationObserver(AllocationObserver* observer) override;
void RemoveAllocationObserver(AllocationObserver* observer) override;
void PauseAllocationObservers() override; void PauseAllocationObservers() override;
void ResumeAllocationObservers() override;
iterator begin() { return to_space_.begin(); } iterator begin() { return to_space_.begin(); }
iterator end() { return to_space_.end(); } iterator end() { return to_space_.end(); }
@ -2765,10 +2761,6 @@ class NewSpace : public Space {
base::Mutex mutex_; base::Mutex mutex_;
// Allocation pointer and limit for normal allocation and allocation during
// mark-compact collection.
AllocationInfo allocation_info_;
Address top_on_previous_step_;
// The top and the limit at the time of setting the allocation info. // The top and the limit at the time of setting the allocation info.
// These values can be accessed by background tasks. // These values can be accessed by background tasks.
base::AtomicValue<Address> original_top_; base::AtomicValue<Address> original_top_;
@ -2784,14 +2776,6 @@ class NewSpace : public Space {
bool EnsureAllocation(int size_in_bytes, AllocationAlignment alignment); bool EnsureAllocation(int size_in_bytes, AllocationAlignment alignment);
// If we are doing inline allocation in steps, this method performs the 'step'
// operation. top is the memory address of the bump pointer at the last
// inline allocation (i.e. it determines the numbers of bytes actually
// allocated since the last step.) new_top is the address of the bump pointer
// where the next byte is going to be allocated from. top and new_top may be
// different when we cross a page boundary or reset the space.
void InlineAllocationStep(Address top, Address new_top, Address soon_object,
size_t size);
void StartNextInlineAllocationStep() override; void StartNextInlineAllocationStep() override;
friend class SemiSpaceIterator; friend class SemiSpaceIterator;