v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
allocation-observer.cc
Go to the documentation of this file.
1// Copyright 2020 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
6
7#include <algorithm>
8
9#include "src/heap/heap.h"
10#include "src/heap/spaces.h"
11
12namespace v8 {
13namespace internal {
14
16#if DEBUG
17 auto it = std::find_if(observers_.begin(), observers_.end(),
18 [observer](const AllocationObserverCounter& aoc) {
19 return aoc.observer_ == observer;
20 });
21 DCHECK_EQ(observers_.end(), it);
22#endif
23
25 pending_added_.push_back(AllocationObserverCounter(observer, 0, 0));
26 return;
27 }
28
29 intptr_t step_size = observer->GetNextStepSize();
30 size_t observer_next_counter = current_counter_ + step_size;
31
33 observer_next_counter));
34
35 if (observers_.size() == 1) {
37 next_counter_ = observer_next_counter;
38 } else {
39 size_t missing_bytes = next_counter_ - current_counter_;
41 std::min(static_cast<intptr_t>(missing_bytes), step_size);
42 }
43}
44
46 auto it = std::find_if(observers_.begin(), observers_.end(),
47 [observer](const AllocationObserverCounter& aoc) {
48 return aoc.observer_ == observer;
49 });
50 DCHECK_NE(observers_.end(), it);
51
53 DCHECK_EQ(pending_removed_.count(observer), 0);
54 pending_removed_.insert(observer);
55 return;
56 }
57
58 observers_.erase(it);
59
60 if (observers_.empty()) {
62 } else {
63 size_t step_size = 0;
64
65 for (AllocationObserverCounter& observer_counter : observers_) {
66 size_t left_in_step = observer_counter.next_counter_ - current_counter_;
67 DCHECK_GT(left_in_step, 0);
68 step_size = step_size ? std::min(step_size, left_in_step) : left_in_step;
69 }
70
71 next_counter_ = current_counter_ + step_size;
72 }
73}
74
76 if (observers_.empty()) return;
79 current_counter_ += allocated;
80}
81
83 size_t object_size,
84 size_t aligned_object_size) {
85 if (observers_.empty()) return;
87 DCHECK_GE(aligned_object_size, next_counter_ - current_counter_);
88 DCHECK(soon_object);
89 bool step_run = false;
90 step_in_progress_ = true;
91 size_t step_size = 0;
92
93 DCHECK(pending_added_.empty());
94 DCHECK(pending_removed_.empty());
95
97 if (aoc.next_counter_ - current_counter_ <= aligned_object_size) {
98 {
100 aoc.observer_->Step(
101 static_cast<int>(current_counter_ - aoc.prev_counter_), soon_object,
102 object_size);
103 }
104 size_t observer_step_size = aoc.observer_->GetNextStepSize();
105
106 aoc.prev_counter_ = current_counter_;
107 aoc.next_counter_ =
108 current_counter_ + aligned_object_size + observer_step_size;
109 step_run = true;
110 }
111
112 size_t left_in_step = aoc.next_counter_ - current_counter_;
113 step_size = step_size ? std::min(step_size, left_in_step) : left_in_step;
114 }
115
116 CHECK(step_run);
117
118 // Now process newly added allocation observers.
120 DCHECK_EQ(0, aoc.next_counter_);
121 size_t observer_step_size = aoc.observer_->GetNextStepSize();
122 aoc.prev_counter_ = current_counter_;
123 aoc.next_counter_ =
124 current_counter_ + aligned_object_size + observer_step_size;
125
126 DCHECK_NE(step_size, 0);
127 step_size = std::min(step_size, aligned_object_size + observer_step_size);
128
129 observers_.push_back(aoc);
130 }
131
132 pending_added_.clear();
133
134 if (!pending_removed_.empty()) {
135 observers_.erase(
136 std::remove_if(observers_.begin(), observers_.end(),
137 [this](const AllocationObserverCounter& aoc) {
138 return pending_removed_.count(aoc.observer_) != 0;
139 }),
140 observers_.end());
141 pending_removed_.clear();
142
143 // Some observers were removed, recalculate step size.
144 step_size = 0;
146 size_t left_in_step = aoc.next_counter_ - current_counter_;
147 step_size = step_size ? std::min(step_size, left_in_step) : left_in_step;
148 }
149
150 if (observers_.empty()) {
152 step_in_progress_ = false;
153 return;
154 }
155 }
156
157 next_counter_ = current_counter_ + step_size;
158 step_in_progress_ = false;
159}
160
162 : heap_(heap) {
163 DCHECK_EQ(heap->gc_state(), Heap::NOT_IN_GC);
164 heap->allocator()->PauseAllocationObservers();
166}
167
172
173} // namespace internal
174} // namespace v8
std::unordered_set< AllocationObserver * > pending_removed_
V8_EXPORT_PRIVATE void AdvanceAllocationObservers(size_t allocated)
V8_EXPORT_PRIVATE void RemoveAllocationObserver(AllocationObserver *observer)
std::vector< AllocationObserverCounter > pending_added_
std::vector< AllocationObserverCounter > observers_
V8_EXPORT_PRIVATE void AddAllocationObserver(AllocationObserver *observer)
V8_EXPORT_PRIVATE void InvokeAllocationObservers(Address soon_object, size_t object_size, size_t aligned_object_size)
int pause_allocation_observers_depth_
Definition heap.h:2380
HeapAllocator * allocator()
Definition heap.h:1640
#define CHECK(condition)
Definition logging.h:124
#define DCHECK_NE(v1, v2)
Definition logging.h:486
#define DCHECK_GE(v1, v2)
Definition logging.h:488
#define DCHECK(condition)
Definition logging.h:482
#define DCHECK_LT(v1, v2)
Definition logging.h:489
#define DCHECK_EQ(v1, v2)
Definition logging.h:485
#define DCHECK_GT(v1, v2)
Definition logging.h:487
Heap * heap_