[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:
parent
f9aacf1584
commit
8dd405e39a
@ -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.
|
||||||
|
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user