LCOV - code coverage report
Current view: top level - src/profiler - heap-profiler.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 102 106 96.2 %
Date: 2019-04-18 Functions: 24 26 92.3 %

          Line data    Source code
       1             : // Copyright 2009-2010 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             : 
       5             : #include "src/profiler/heap-profiler.h"
       6             : 
       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"
      13             : 
      14             : namespace v8 {
      15             : namespace internal {
      16             : 
      17       62442 : HeapProfiler::HeapProfiler(Heap* heap)
      18       62442 :     : ids_(new HeapObjectsMap(heap)),
      19             :       names_(new StringsStorage()),
      20      249768 :       is_tracking_object_moves_(false) {}
      21             : 
      22             : HeapProfiler::~HeapProfiler() = default;
      23             : 
      24          70 : void HeapProfiler::DeleteAllSnapshots() {
      25             :   snapshots_.clear();
      26          70 :   MaybeClearStringsStorage();
      27          70 : }
      28             : 
      29         164 : void HeapProfiler::MaybeClearStringsStorage() {
      30         487 :   if (snapshots_.empty() && !sampling_heap_profiler_ && !allocation_tracker_) {
      31         154 :     names_.reset(new StringsStorage());
      32             :   }
      33         164 : }
      34             : 
      35           5 : void HeapProfiler::RemoveSnapshot(HeapSnapshot* snapshot) {
      36             :   snapshots_.erase(
      37             :       std::find_if(snapshots_.begin(), snapshots_.end(),
      38             :                    [&](const std::unique_ptr<HeapSnapshot>& entry) {
      39           5 :                      return entry.get() == snapshot;
      40           5 :                    }));
      41           5 : }
      42             : 
      43          35 : void HeapProfiler::AddBuildEmbedderGraphCallback(
      44             :     v8::HeapProfiler::BuildEmbedderGraphCallback callback, void* data) {
      45          70 :   build_embedder_graph_callbacks_.push_back({callback, data});
      46          35 : }
      47             : 
      48           5 : void HeapProfiler::RemoveBuildEmbedderGraphCallback(
      49             :     v8::HeapProfiler::BuildEmbedderGraphCallback callback, void* data) {
      50             :   auto it = std::find(build_embedder_graph_callbacks_.begin(),
      51             :                       build_embedder_graph_callbacks_.end(),
      52          10 :                       std::make_pair(callback, data));
      53           5 :   if (it != build_embedder_graph_callbacks_.end())
      54             :     build_embedder_graph_callbacks_.erase(it);
      55           5 : }
      56             : 
      57          35 : void HeapProfiler::BuildEmbedderGraph(Isolate* isolate,
      58             :                                       v8::EmbedderGraph* graph) {
      59          75 :   for (const auto& cb : build_embedder_graph_callbacks_) {
      60          40 :     cb.first(reinterpret_cast<v8::Isolate*>(isolate), graph, cb.second);
      61             :   }
      62          35 : }
      63             : 
      64         398 : HeapSnapshot* HeapProfiler::TakeSnapshot(
      65             :     v8::ActivityControl* control,
      66             :     v8::HeapProfiler::ObjectNameResolver* resolver) {
      67         398 :   HeapSnapshot* result = new HeapSnapshot(this);
      68             :   {
      69         796 :     HeapSnapshotGenerator generator(result, control, resolver, heap());
      70         398 :     if (!generator.GenerateSnapshot()) {
      71           5 :       delete result;
      72           5 :       result = nullptr;
      73             :     } else {
      74         393 :       snapshots_.emplace_back(result);
      75             :     }
      76             :   }
      77         398 :   ids_->RemoveDeadEntries();
      78         398 :   is_tracking_object_moves_ = true;
      79             : 
      80             :   heap()->isolate()->debug()->feature_tracker()->Track(
      81         398 :       DebugFeatureTracker::kHeapSnapshot);
      82             : 
      83         398 :   return result;
      84             : }
      85             : 
      86          59 : bool HeapProfiler::StartSamplingHeapProfiler(
      87             :     uint64_t sample_interval, int stack_depth,
      88             :     v8::HeapProfiler::SamplingFlags flags) {
      89          59 :   if (sampling_heap_profiler_.get()) {
      90             :     return false;
      91             :   }
      92         118 :   sampling_heap_profiler_.reset(new SamplingHeapProfiler(
      93         118 :       heap(), names_.get(), sample_interval, stack_depth, flags));
      94          59 :   return true;
      95             : }
      96             : 
      97             : 
      98          59 : void HeapProfiler::StopSamplingHeapProfiler() {
      99          59 :   sampling_heap_profiler_.reset();
     100          59 :   MaybeClearStringsStorage();
     101          59 : }
     102             : 
     103             : 
     104          77 : v8::AllocationProfile* HeapProfiler::GetAllocationProfile() {
     105          77 :   if (sampling_heap_profiler_.get()) {
     106          64 :     return sampling_heap_profiler_->GetAllocationProfile();
     107             :   } else {
     108             :     return nullptr;
     109             :   }
     110             : }
     111             : 
     112             : 
     113          45 : void HeapProfiler::StartHeapObjectsTracking(bool track_allocations) {
     114          45 :   ids_->UpdateHeapObjectsMap();
     115          45 :   is_tracking_object_moves_ = true;
     116             :   DCHECK(!allocation_tracker_);
     117          45 :   if (track_allocations) {
     118          35 :     allocation_tracker_.reset(new AllocationTracker(ids_.get(), names_.get()));
     119          70 :     heap()->AddHeapObjectAllocationTracker(this);
     120             :     heap()->isolate()->debug()->feature_tracker()->Track(
     121          35 :         DebugFeatureTracker::kAllocationTracking);
     122             :   }
     123          45 : }
     124             : 
     125          55 : SnapshotObjectId HeapProfiler::PushHeapObjectsStats(OutputStream* stream,
     126             :                                                     int64_t* timestamp_us) {
     127          55 :   return ids_->PushHeapObjectsStats(stream, timestamp_us);
     128             : }
     129             : 
     130        3924 : void HeapProfiler::StopHeapObjectsTracking() {
     131        3924 :   ids_->StopHeapObjectsTracking();
     132        3924 :   if (allocation_tracker_) {
     133          35 :     allocation_tracker_.reset();
     134          35 :     MaybeClearStringsStorage();
     135          70 :     heap()->RemoveHeapObjectAllocationTracker(this);
     136             :   }
     137        3924 : }
     138             : 
     139         155 : int HeapProfiler::GetSnapshotsCount() {
     140         155 :   return static_cast<int>(snapshots_.size());
     141             : }
     142             : 
     143          30 : HeapSnapshot* HeapProfiler::GetSnapshot(int index) {
     144          60 :   return snapshots_.at(index).get();
     145             : }
     146             : 
     147         155 : SnapshotObjectId HeapProfiler::GetSnapshotObjectId(Handle<Object> obj) {
     148         155 :   if (!obj->IsHeapObject())
     149             :     return v8::HeapProfiler::kUnknownObjectId;
     150         155 :   return ids_->FindEntry(HeapObject::cast(*obj)->address());
     151             : }
     152             : 
     153      128379 : void HeapProfiler::ObjectMoveEvent(Address from, Address to, int size) {
     154      128379 :   base::MutexGuard guard(&profiler_mutex_);
     155      128397 :   bool known_object = ids_->MoveObject(from, to, size);
     156      255029 :   if (!known_object && allocation_tracker_) {
     157       35222 :     allocation_tracker_->address_to_trace()->MoveObject(from, to, size);
     158             :   }
     159      128395 : }
     160             : 
     161      115590 : void HeapProfiler::AllocationEvent(Address addr, int size) {
     162             :   DisallowHeapAllocation no_allocation;
     163      115590 :   if (allocation_tracker_) {
     164      115590 :     allocation_tracker_->AllocationEvent(addr, size);
     165             :   }
     166      115590 : }
     167             : 
     168             : 
     169           0 : void HeapProfiler::UpdateObjectSizeEvent(Address addr, int size) {
     170           0 :   ids_->UpdateObjectSize(addr, size);
     171           0 : }
     172             : 
     173         140 : Handle<HeapObject> HeapProfiler::FindHeapObjectById(SnapshotObjectId id) {
     174             :   HeapObject object;
     175         280 :   HeapIterator iterator(heap(), HeapIterator::kFilterUnreachable);
     176             :   // Make sure that object with the given id is still reachable.
     177      919868 :   for (HeapObject obj = iterator.next(); !obj.is_null();
     178             :        obj = iterator.next()) {
     179      919728 :     if (ids_->FindEntry(obj->address()) == id) {
     180             :       DCHECK(object.is_null());
     181             :       object = obj;
     182             :       // Can't break -- kFilterUnreachable requires full heap traversal.
     183             :     }
     184             :   }
     185             :   return !object.is_null() ? Handle<HeapObject>(object, isolate())
     186         280 :                            : Handle<HeapObject>();
     187             : }
     188             : 
     189             : 
     190        3884 : void HeapProfiler::ClearHeapObjectMap() {
     191        3884 :   ids_.reset(new HeapObjectsMap(heap()));
     192        3884 :   if (!allocation_tracker_) is_tracking_object_moves_ = false;
     193        3884 : }
     194             : 
     195             : 
     196           0 : Heap* HeapProfiler::heap() const { return ids_->heap(); }
     197             : 
     198    12011002 : Isolate* HeapProfiler::isolate() const { return heap()->isolate(); }
     199             : 
     200          85 : void HeapProfiler::QueryObjects(Handle<Context> context,
     201             :                                 debug::QueryObjectPredicate* predicate,
     202             :                                 PersistentValueVector<v8::Object>* objects) {
     203             :   // We should return accurate information about live objects, so we need to
     204             :   // collect all garbage first.
     205          85 :   heap()->CollectAllAvailableGarbage(GarbageCollectionReason::kHeapProfiler);
     206         170 :   HeapIterator heap_iterator(heap());
     207     2362626 :   for (HeapObject heap_obj = heap_iterator.next(); !heap_obj.is_null();
     208             :        heap_obj = heap_iterator.next()) {
     209     2667458 :     if (!heap_obj->IsJSObject() || heap_obj->IsExternal(isolate())) continue;
     210             :     v8::Local<v8::Object> v8_obj(
     211      304717 :         Utils::ToLocal(handle(JSObject::cast(heap_obj), isolate())));
     212      304717 :     if (!predicate->Filter(v8_obj)) continue;
     213         100 :     objects->Append(v8_obj);
     214             :   }
     215          85 : }
     216             : 
     217             : }  // namespace internal
     218      122036 : }  // namespace v8

Generated by: LCOV version 1.10