Skip to content

Commit 672a41c

Browse files
ofrobotsCommit Bot
authored andcommitted
[profiler] proper observation of old space inline allocations
Bug: chromium:633920 Change-Id: I9a2f4a89f6b9c0f63cb3b166b06a88a12f0a203c Reviewed-on: https://chromium-review.googlesource.com/631696 Commit-Queue: Ali Ijaz Sheikh <[email protected]> Reviewed-by: Ulan Degenbaev <[email protected]> Cr-Commit-Position: refs/heads/master@{#48043}
1 parent 5719ca6 commit 672a41c

6 files changed

Lines changed: 194 additions & 69 deletions

File tree

src/heap/spaces-inl.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -369,6 +369,11 @@ AllocationResult PagedSpace::AllocateRawAligned(int size_in_bytes,
369369

370370
AllocationResult PagedSpace::AllocateRaw(int size_in_bytes,
371371
AllocationAlignment alignment) {
372+
DCHECK(top() >= top_on_previous_step_);
373+
size_t bytes_since_last =
374+
top_on_previous_step_ ? top() - top_on_previous_step_ : 0;
375+
376+
DCHECK_IMPLIES(!SupportsInlineAllocation(), bytes_since_last == 0);
372377
#ifdef V8_HOST_ARCH_32_BIT
373378
AllocationResult result =
374379
alignment == kDoubleAligned
@@ -378,11 +383,13 @@ AllocationResult PagedSpace::AllocateRaw(int size_in_bytes,
378383
AllocationResult result = AllocateRawUnaligned(size_in_bytes);
379384
#endif
380385
HeapObject* heap_obj = nullptr;
381-
if (!result.IsRetry() && result.To(&heap_obj)) {
382-
AllocationStep(heap_obj->address(), size_in_bytes);
386+
if (!result.IsRetry() && result.To(&heap_obj) && !is_local()) {
387+
AllocationStep(static_cast<int>(size_in_bytes + bytes_since_last),
388+
heap_obj->address(), size_in_bytes);
383389
DCHECK_IMPLIES(
384390
heap()->incremental_marking()->black_allocation(),
385391
heap()->incremental_marking()->marking_state()->IsBlack(heap_obj));
392+
StartNextInlineAllocationStep();
386393
}
387394
return result;
388395
}

src/heap/spaces.cc

Lines changed: 81 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1332,13 +1332,15 @@ STATIC_ASSERT(static_cast<ObjectSpace>(1 << AllocationSpace::MAP_SPACE) ==
13321332

13331333
void Space::AddAllocationObserver(AllocationObserver* observer) {
13341334
allocation_observers_.push_back(observer);
1335+
StartNextInlineAllocationStep();
13351336
}
13361337

13371338
void Space::RemoveAllocationObserver(AllocationObserver* observer) {
13381339
auto it = std::find(allocation_observers_.begin(),
13391340
allocation_observers_.end(), observer);
13401341
DCHECK(allocation_observers_.end() != it);
13411342
allocation_observers_.erase(it);
1343+
StartNextInlineAllocationStep();
13421344
}
13431345

13441346
void Space::PauseAllocationObservers() { allocation_observers_paused_ = true; }
@@ -1347,11 +1349,12 @@ void Space::ResumeAllocationObservers() {
13471349
allocation_observers_paused_ = false;
13481350
}
13491351

1350-
void Space::AllocationStep(Address soon_object, int size) {
1352+
void Space::AllocationStep(int bytes_since_last, Address soon_object,
1353+
int size) {
13511354
if (!allocation_observers_paused_) {
13521355
heap()->CreateFillerObjectAt(soon_object, size, ClearRecordedSlots::kNo);
13531356
for (AllocationObserver* observer : allocation_observers_) {
1354-
observer->AllocationStep(size, soon_object, size);
1357+
observer->AllocationStep(bytes_since_last, soon_object, size);
13551358
}
13561359
}
13571360
}
@@ -1371,7 +1374,8 @@ PagedSpace::PagedSpace(Heap* heap, AllocationSpace space,
13711374
: Space(heap, space, executable),
13721375
anchor_(this),
13731376
free_list_(this),
1374-
locked_page_(nullptr) {
1377+
locked_page_(nullptr),
1378+
top_on_previous_step_(0) {
13751379
area_size_ = MemoryAllocator::PageAreaSize(space);
13761380
accounting_stats_.Clear();
13771381

@@ -1600,6 +1604,48 @@ void PagedSpace::SetAllocationInfo(Address top, Address limit) {
16001604
}
16011605
}
16021606

1607+
void PagedSpace::DecreaseLimit(Address new_limit) {
1608+
Address old_limit = limit();
1609+
DCHECK_LE(top(), new_limit);
1610+
DCHECK_GE(old_limit, new_limit);
1611+
if (new_limit != old_limit) {
1612+
SetTopAndLimit(top(), new_limit);
1613+
Free(new_limit, old_limit - new_limit);
1614+
if (heap()->incremental_marking()->black_allocation()) {
1615+
Page::FromAllocationAreaAddress(new_limit)->DestroyBlackArea(new_limit,
1616+
old_limit);
1617+
}
1618+
}
1619+
}
1620+
1621+
Address PagedSpace::ComputeLimit(Address start, Address end,
1622+
size_t size_in_bytes) {
1623+
DCHECK_GE(end - start, size_in_bytes);
1624+
1625+
if (heap()->inline_allocation_disabled()) {
1626+
// Keep the linear allocation area to fit exactly the requested size.
1627+
return start + size_in_bytes;
1628+
} else if (!allocation_observers_paused_ && !allocation_observers_.empty() &&
1629+
identity() == OLD_SPACE && !is_local()) {
1630+
// Generated code may allocate inline from the linear allocation area for
1631+
// Old Space. To make sure we can observe these allocations, we use a lower
1632+
// limit.
1633+
size_t step = RoundSizeDownToObjectAlignment(
1634+
static_cast<int>(GetNextInlineAllocationStepSize()));
1635+
return Max(start + size_in_bytes, Min(start + step, end));
1636+
} else {
1637+
// The entire node can be used as the linear allocation area.
1638+
return end;
1639+
}
1640+
}
1641+
1642+
void PagedSpace::StartNextInlineAllocationStep() {
1643+
if (!allocation_observers_paused_ && SupportsInlineAllocation()) {
1644+
top_on_previous_step_ = allocation_observers_.empty() ? 0 : top();
1645+
DecreaseLimit(ComputeLimit(top(), limit(), 0));
1646+
}
1647+
}
1648+
16031649
void PagedSpace::MarkAllocationInfoBlack() {
16041650
DCHECK(heap()->incremental_marking()->black_allocation());
16051651
Address current_top = top();
@@ -1645,6 +1691,12 @@ void PagedSpace::EmptyAllocationInfo() {
16451691
}
16461692
}
16471693

1694+
if (top_on_previous_step_) {
1695+
DCHECK(current_top >= top_on_previous_step_);
1696+
AllocationStep(static_cast<int>(current_top - top_on_previous_step_),
1697+
nullptr, 0);
1698+
top_on_previous_step_ = 0;
1699+
}
16481700
SetTopAndLimit(NULL, NULL);
16491701
DCHECK_GE(current_limit, current_top);
16501702
Free(current_top, current_limit - current_top);
@@ -2087,16 +2139,6 @@ void NewSpace::StartNextInlineAllocationStep() {
20872139
}
20882140
}
20892141

2090-
void NewSpace::AddAllocationObserver(AllocationObserver* observer) {
2091-
Space::AddAllocationObserver(observer);
2092-
StartNextInlineAllocationStep();
2093-
}
2094-
2095-
void NewSpace::RemoveAllocationObserver(AllocationObserver* observer) {
2096-
Space::RemoveAllocationObserver(observer);
2097-
StartNextInlineAllocationStep();
2098-
}
2099-
21002142
void NewSpace::PauseAllocationObservers() {
21012143
// Do a step to account for memory allocated so far.
21022144
InlineAllocationStep(top(), top(), nullptr, 0);
@@ -2105,12 +2147,28 @@ void NewSpace::PauseAllocationObservers() {
21052147
UpdateInlineAllocationLimit(0);
21062148
}
21072149

2150+
void PagedSpace::PauseAllocationObservers() {
2151+
// Do a step to account for memory allocated so far.
2152+
if (top_on_previous_step_) {
2153+
int bytes_allocated = static_cast<int>(top() - top_on_previous_step_);
2154+
AllocationStep(bytes_allocated, nullptr, 0);
2155+
}
2156+
Space::PauseAllocationObservers();
2157+
top_on_previous_step_ = 0;
2158+
}
2159+
21082160
void NewSpace::ResumeAllocationObservers() {
21092161
DCHECK(top_on_previous_step_ == 0);
21102162
Space::ResumeAllocationObservers();
21112163
StartNextInlineAllocationStep();
21122164
}
21132165

2166+
// TODO(ofrobots): refactor into SpaceWithLinearArea
2167+
void PagedSpace::ResumeAllocationObservers() {
2168+
DCHECK(top_on_previous_step_ == 0);
2169+
Space::ResumeAllocationObservers();
2170+
StartNextInlineAllocationStep();
2171+
}
21142172

21152173
void NewSpace::InlineAllocationStep(Address top, Address new_top,
21162174
Address soon_object, size_t size) {
@@ -2885,7 +2943,6 @@ bool FreeList::Allocate(size_t size_in_bytes) {
28852943
if (new_node == nullptr) return false;
28862944

28872945
DCHECK_GE(new_node_size, size_in_bytes);
2888-
size_t bytes_left = new_node_size - size_in_bytes;
28892946

28902947
#ifdef DEBUG
28912948
for (size_t i = 0; i < size_in_bytes / kPointerSize; i++) {
@@ -2899,38 +2956,21 @@ bool FreeList::Allocate(size_t size_in_bytes) {
28992956
// candidate.
29002957
DCHECK(!MarkCompactCollector::IsOnEvacuationCandidate(new_node));
29012958

2902-
const size_t kThreshold = IncrementalMarking::kAllocatedThreshold;
2903-
29042959
// Memory in the linear allocation area is counted as allocated. We may free
29052960
// a little of this again immediately - see below.
29062961
owner_->IncreaseAllocatedBytes(new_node_size,
29072962
Page::FromAddress(new_node->address()));
29082963

2909-
if (owner_->heap()->inline_allocation_disabled()) {
2910-
// Keep the linear allocation area to fit exactly the requested size.
2911-
// Return the rest to the free list.
2912-
owner_->Free(new_node->address() + size_in_bytes, bytes_left);
2913-
owner_->SetAllocationInfo(new_node->address(),
2914-
new_node->address() + size_in_bytes);
2915-
} else if (bytes_left > kThreshold &&
2916-
owner_->heap()->incremental_marking()->IsMarkingIncomplete() &&
2917-
FLAG_incremental_marking &&
2918-
!owner_->is_local()) { // Not needed on CompactionSpaces.
2919-
size_t linear_size = owner_->RoundSizeDownToObjectAlignment(kThreshold);
2920-
// We don't want to give too large linear areas to the allocator while
2921-
// incremental marking is going on, because we won't check again whether
2922-
// we want to do another increment until the linear area is used up.
2923-
DCHECK_GE(new_node_size, size_in_bytes + linear_size);
2924-
owner_->Free(new_node->address() + size_in_bytes + linear_size,
2925-
new_node_size - size_in_bytes - linear_size);
2926-
owner_->SetAllocationInfo(
2927-
new_node->address(), new_node->address() + size_in_bytes + linear_size);
2928-
} else {
2929-
// Normally we give the rest of the node to the allocator as its new
2930-
// linear allocation area.
2931-
owner_->SetAllocationInfo(new_node->address(),
2932-
new_node->address() + new_node_size);
2964+
Address start = new_node->address();
2965+
Address end = new_node->address() + new_node_size;
2966+
Address limit = owner_->ComputeLimit(start, end, size_in_bytes);
2967+
DCHECK_LE(limit, end);
2968+
DCHECK_LE(size_in_bytes, limit - start);
2969+
if (limit != end) {
2970+
owner_->Free(limit, end - limit);
29332971
}
2972+
owner_->SetAllocationInfo(start, limit);
2973+
29342974
return true;
29352975
}
29362976

@@ -3318,7 +3358,7 @@ AllocationResult LargeObjectSpace::AllocateRaw(int object_size,
33183358
if (heap()->incremental_marking()->black_allocation()) {
33193359
heap()->incremental_marking()->marking_state()->WhiteToBlack(object);
33203360
}
3321-
AllocationStep(object->address(), object_size);
3361+
AllocationStep(object_size, object->address(), object_size);
33223362
DCHECK_IMPLIES(
33233363
heap()->incremental_marking()->black_allocation(),
33243364
heap()->incremental_marking()->marking_state()->IsBlack(object));

src/heap/spaces.h

Lines changed: 24 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -903,17 +903,17 @@ class Space : public Malloced {
903903
// Identity used in error reporting.
904904
AllocationSpace identity() { return id_; }
905905

906-
V8_EXPORT_PRIVATE virtual void AddAllocationObserver(
907-
AllocationObserver* observer);
906+
void AddAllocationObserver(AllocationObserver* observer);
908907

909-
V8_EXPORT_PRIVATE virtual void RemoveAllocationObserver(
910-
AllocationObserver* observer);
908+
void RemoveAllocationObserver(AllocationObserver* observer);
911909

912910
V8_EXPORT_PRIVATE virtual void PauseAllocationObservers();
913911

914912
V8_EXPORT_PRIVATE virtual void ResumeAllocationObservers();
915913

916-
void AllocationStep(Address soon_object, int size);
914+
V8_EXPORT_PRIVATE virtual void StartNextInlineAllocationStep() {}
915+
916+
void AllocationStep(int bytes_since_last, Address soon_object, int size);
917917

918918
// Return the total amount committed memory for this space, i.e., allocatable
919919
// memory and page headers.
@@ -2071,15 +2071,8 @@ class V8_EXPORT_PRIVATE PagedSpace : NON_EXPORTED_BASE(public Space) {
20712071

20722072
void ResetFreeList() { free_list_.Reset(); }
20732073

2074-
// Set space allocation info.
2075-
void SetTopAndLimit(Address top, Address limit) {
2076-
DCHECK(top == limit ||
2077-
Page::FromAddress(top) == Page::FromAddress(limit - 1));
2078-
MemoryChunk::UpdateHighWaterMark(allocation_info_.top());
2079-
allocation_info_.Reset(top, limit);
2080-
}
2081-
2082-
void SetAllocationInfo(Address top, Address limit);
2074+
void PauseAllocationObservers() override;
2075+
void ResumeAllocationObservers() override;
20832076

20842077
// Empty space allocation info, returning unused area to free list.
20852078
void EmptyAllocationInfo();
@@ -2184,6 +2177,21 @@ class V8_EXPORT_PRIVATE PagedSpace : NON_EXPORTED_BASE(public Space) {
21842177
// multiple tasks hold locks on pages while trying to sweep each others pages.
21852178
void AnnounceLockedPage(Page* page) { locked_page_ = page; }
21862179

2180+
Address ComputeLimit(Address start, Address end, size_t size_in_bytes);
2181+
void SetAllocationInfo(Address top, Address limit);
2182+
2183+
private:
2184+
// Set space allocation info.
2185+
void SetTopAndLimit(Address top, Address limit) {
2186+
DCHECK(top == limit ||
2187+
Page::FromAddress(top) == Page::FromAddress(limit - 1));
2188+
MemoryChunk::UpdateHighWaterMark(allocation_info_.top());
2189+
allocation_info_.Reset(top, limit);
2190+
}
2191+
void DecreaseLimit(Address new_limit);
2192+
void StartNextInlineAllocationStep() override;
2193+
bool SupportsInlineAllocation() { return identity() == OLD_SPACE; }
2194+
21872195
protected:
21882196
// PagedSpaces that should be included in snapshots have different, i.e.,
21892197
// smaller, initial pages.
@@ -2246,6 +2254,7 @@ class V8_EXPORT_PRIVATE PagedSpace : NON_EXPORTED_BASE(public Space) {
22462254
base::Mutex space_mutex_;
22472255

22482256
Page* locked_page_;
2257+
Address top_on_previous_step_;
22492258

22502259
friend class IncrementalMarking;
22512260
friend class MarkCompactCollector;
@@ -2647,14 +2656,6 @@ class NewSpace : public Space {
26472656
UpdateInlineAllocationLimit(0);
26482657
}
26492658

2650-
// Allows observation of inline allocation. The observer->Step() method gets
2651-
// called after every step_size bytes have been allocated (approximately).
2652-
// This works by adjusting the allocation limit to a lower value and adjusting
2653-
// it after each step.
2654-
void AddAllocationObserver(AllocationObserver* observer) override;
2655-
2656-
void RemoveAllocationObserver(AllocationObserver* observer) override;
2657-
26582659
// Get the extent of the inactive semispace (for use as a marking stack,
26592660
// or to zap it). Notice: space-addresses are not necessarily on the
26602661
// same page, so FromSpaceStart() might be above FromSpaceEnd().
@@ -2762,7 +2763,7 @@ class NewSpace : public Space {
27622763
// different when we cross a page boundary or reset the space.
27632764
void InlineAllocationStep(Address top, Address new_top, Address soon_object,
27642765
size_t size);
2765-
void StartNextInlineAllocationStep();
2766+
void StartNextInlineAllocationStep() override;
27662767

27672768
friend class SemiSpaceIterator;
27682769
};

src/profiler/sampling-heap-profiler.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -172,8 +172,11 @@ class SamplingAllocationObserver : public AllocationObserver {
172172
void Step(int bytes_allocated, Address soon_object, size_t size) override {
173173
USE(heap_);
174174
DCHECK(heap_->gc_state() == Heap::NOT_IN_GC);
175-
DCHECK(soon_object);
176-
profiler_->SampleObject(soon_object, size);
175+
if (soon_object) {
176+
// TODO(ofrobots): it would be better to sample the next object rather
177+
// than skipping this sample epoch if soon_object happens to be null.
178+
profiler_->SampleObject(soon_object, size);
179+
}
177180
}
178181

179182
intptr_t GetNextStepSize() override { return GetNextSampleInterval(rate_); }

test/cctest/heap/heap-utils.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ void ForceEvacuationCandidate(Page* page) {
203203
int remaining = static_cast<int>(limit - top);
204204
space->heap()->CreateFillerObjectAt(top, remaining,
205205
ClearRecordedSlots::kNo);
206-
space->SetTopAndLimit(nullptr, nullptr);
206+
space->EmptyAllocationInfo();
207207
}
208208
}
209209

0 commit comments

Comments
 (0)