5 #include "src/profiler/heap-profiler.h" 7 #include "src/api-inl.h" 8 #include "src/debug/debug.h" 9 #include "src/heap/heap-inl.h" 10 #include "src/profiler/allocation-tracker.h" 11 #include "src/profiler/heap-snapshot-generator-inl.h" 12 #include "src/profiler/sampling-heap-profiler.h" 17 HeapProfiler::HeapProfiler(Heap* heap)
18 : ids_(new HeapObjectsMap(heap)),
19 names_(new StringsStorage()),
20 is_tracking_object_moves_(false) {}
22 HeapProfiler::~HeapProfiler() =
default;
24 void HeapProfiler::DeleteAllSnapshots() {
26 MaybeClearStringsStorage();
29 void HeapProfiler::MaybeClearStringsStorage() {
30 if (snapshots_.empty() && !sampling_heap_profiler_ && !allocation_tracker_) {
31 names_.reset(
new StringsStorage());
35 void HeapProfiler::RemoveSnapshot(HeapSnapshot* snapshot) {
37 std::find_if(snapshots_.begin(), snapshots_.end(),
38 [&](
const std::unique_ptr<HeapSnapshot>& entry) {
39 return entry.get() == snapshot;
44 void HeapProfiler::DefineWrapperClass(
47 if (wrapper_callbacks_.size() <= class_id) {
48 wrapper_callbacks_.insert(wrapper_callbacks_.end(),
49 class_id - wrapper_callbacks_.size() + 1,
52 wrapper_callbacks_[class_id] = callback;
57 uint16_t class_id, Object** wrapper) {
58 if (wrapper_callbacks_.size() <= class_id)
return nullptr;
59 return wrapper_callbacks_[class_id](
60 class_id, Utils::ToLocal(Handle<Object>(wrapper)));
63 void HeapProfiler::SetGetRetainerInfosCallback(
65 get_retainer_infos_callback_ = callback;
71 if (get_retainer_infos_callback_ !=
nullptr)
73 get_retainer_infos_callback_(reinterpret_cast<v8::Isolate*>(isolate));
77 void HeapProfiler::AddBuildEmbedderGraphCallback(
79 build_embedder_graph_callbacks_.push_back({callback, data});
82 void HeapProfiler::RemoveBuildEmbedderGraphCallback(
84 auto it = std::find(build_embedder_graph_callbacks_.begin(),
85 build_embedder_graph_callbacks_.end(),
86 std::make_pair(callback, data));
87 if (it != build_embedder_graph_callbacks_.end())
88 build_embedder_graph_callbacks_.erase(it);
91 void HeapProfiler::BuildEmbedderGraph(Isolate* isolate,
93 for (
const auto& cb : build_embedder_graph_callbacks_) {
94 cb.first(reinterpret_cast<v8::Isolate*>(isolate), graph, cb.second);
98 HeapSnapshot* HeapProfiler::TakeSnapshot(
101 HeapSnapshot* result =
new HeapSnapshot(
this);
103 HeapSnapshotGenerator generator(result, control, resolver, heap());
104 if (!generator.GenerateSnapshot()) {
108 snapshots_.emplace_back(result);
111 ids_->RemoveDeadEntries();
112 is_tracking_object_moves_ =
true;
114 heap()->isolate()->debug()->feature_tracker()->Track(
115 DebugFeatureTracker::kHeapSnapshot);
120 bool HeapProfiler::StartSamplingHeapProfiler(
121 uint64_t sample_interval,
int stack_depth,
122 v8::HeapProfiler::SamplingFlags flags) {
123 if (sampling_heap_profiler_.get()) {
126 sampling_heap_profiler_.reset(
new SamplingHeapProfiler(
127 heap(), names_.get(), sample_interval, stack_depth, flags));
132 void HeapProfiler::StopSamplingHeapProfiler() {
133 sampling_heap_profiler_.reset();
134 MaybeClearStringsStorage();
139 if (sampling_heap_profiler_.get()) {
140 return sampling_heap_profiler_->GetAllocationProfile();
147 void HeapProfiler::StartHeapObjectsTracking(
bool track_allocations) {
148 ids_->UpdateHeapObjectsMap();
149 is_tracking_object_moves_ =
true;
150 DCHECK(!allocation_tracker_);
151 if (track_allocations) {
152 allocation_tracker_.reset(
new AllocationTracker(ids_.get(), names_.get()));
153 heap()->AddHeapObjectAllocationTracker(
this);
154 heap()->isolate()->debug()->feature_tracker()->Track(
155 DebugFeatureTracker::kAllocationTracking);
159 SnapshotObjectId HeapProfiler::PushHeapObjectsStats(OutputStream* stream,
161 return ids_->PushHeapObjectsStats(stream, timestamp_us);
164 void HeapProfiler::StopHeapObjectsTracking() {
165 ids_->StopHeapObjectsTracking();
166 if (allocation_tracker_) {
167 allocation_tracker_.reset();
168 MaybeClearStringsStorage();
169 heap()->RemoveHeapObjectAllocationTracker(
this);
173 int HeapProfiler::GetSnapshotsCount() {
174 return static_cast<int>(snapshots_.size());
177 HeapSnapshot* HeapProfiler::GetSnapshot(
int index) {
178 return snapshots_.at(index).get();
181 SnapshotObjectId HeapProfiler::GetSnapshotObjectId(Handle<Object> obj) {
182 if (!obj->IsHeapObject())
184 return ids_->FindEntry(HeapObject::cast(*obj)->address());
187 void HeapProfiler::ObjectMoveEvent(Address from, Address to,
int size) {
188 base::MutexGuard guard(&profiler_mutex_);
189 bool known_object = ids_->MoveObject(from, to, size);
190 if (!known_object && allocation_tracker_) {
191 allocation_tracker_->address_to_trace()->MoveObject(from, to, size);
195 void HeapProfiler::AllocationEvent(Address addr,
int size) {
196 DisallowHeapAllocation no_allocation;
197 if (allocation_tracker_) {
198 allocation_tracker_->AllocationEvent(addr, size);
203 void HeapProfiler::UpdateObjectSizeEvent(Address addr,
int size) {
204 ids_->UpdateObjectSize(addr, size);
207 Handle<HeapObject> HeapProfiler::FindHeapObjectById(SnapshotObjectId
id) {
208 HeapObject*
object =
nullptr;
209 HeapIterator iterator(heap(), HeapIterator::kFilterUnreachable);
211 for (HeapObject* obj = iterator.next(); obj !=
nullptr;
212 obj = iterator.next()) {
213 if (ids_->FindEntry(obj->address()) ==
id) {
219 return object !=
nullptr ? Handle<HeapObject>(object, isolate())
220 : Handle<HeapObject>();
224 void HeapProfiler::ClearHeapObjectMap() {
225 ids_.reset(
new HeapObjectsMap(heap()));
226 if (!allocation_tracker_) is_tracking_object_moves_ =
false;
230 Heap* HeapProfiler::heap()
const {
return ids_->heap(); }
232 Isolate* HeapProfiler::isolate()
const {
return heap()->isolate(); }
234 void HeapProfiler::QueryObjects(Handle<Context> context,
235 debug::QueryObjectPredicate* predicate,
236 PersistentValueVector<v8::Object>* objects) {
239 heap()->CollectAllAvailableGarbage(GarbageCollectionReason::kHeapProfiler);
240 HeapIterator heap_iterator(heap());
241 HeapObject* heap_obj;
242 while ((heap_obj = heap_iterator.next()) !=
nullptr) {
243 if (!heap_obj->IsJSObject() || heap_obj->IsExternal(isolate()))
continue;
245 Utils::ToLocal(handle(JSObject::cast(heap_obj), isolate())));
246 if (!predicate->Filter(v8_obj))
continue;
247 objects->Append(v8_obj);
RetainerInfos(* GetRetainerInfosCallback)(v8::Isolate *isolate)
static const uint16_t kPersistentHandleNoClassId
void(* BuildEmbedderGraphCallback)(v8::Isolate *isolate, v8::EmbedderGraph *graph, void *data)
RetainedObjectInfo *(* WrapperInfoCallback)(uint16_t class_id, Local< Value > wrapper)
static const SnapshotObjectId kUnknownObjectId