LCOV - code coverage report
Current view: top level - src/profiler - heap-profiler.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 99 107 92.5 %
Date: 2017-10-20 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.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       54999 : HeapProfiler::HeapProfiler(Heap* heap)
      18       54999 :     : ids_(new HeapObjectsMap(heap)),
      19       54999 :       names_(new StringsStorage(heap)),
      20             :       is_tracking_object_moves_(false),
      21      164997 :       get_retainer_infos_callback_(nullptr) {}
      22             : 
      23         309 : static void DeleteHeapSnapshot(HeapSnapshot* snapshot_ptr) {
      24         309 :   delete snapshot_ptr;
      25         309 : }
      26             : 
      27             : 
      28      106730 : HeapProfiler::~HeapProfiler() {
      29             :   std::for_each(snapshots_.begin(), snapshots_.end(), &DeleteHeapSnapshot);
      30       53365 : }
      31             : 
      32             : 
      33          55 : void HeapProfiler::DeleteAllSnapshots() {
      34             :   std::for_each(snapshots_.begin(), snapshots_.end(), &DeleteHeapSnapshot);
      35             :   snapshots_.clear();
      36          55 :   names_.reset(new StringsStorage(heap()));
      37          55 : }
      38             : 
      39             : 
      40           5 : void HeapProfiler::RemoveSnapshot(HeapSnapshot* snapshot) {
      41           5 :   snapshots_.erase(std::find(snapshots_.begin(), snapshots_.end(), snapshot));
      42           5 : }
      43             : 
      44             : 
      45          10 : void HeapProfiler::DefineWrapperClass(
      46             :     uint16_t class_id, v8::HeapProfiler::WrapperInfoCallback callback) {
      47             :   DCHECK_NE(class_id, v8::HeapProfiler::kPersistentHandleNoClassId);
      48          30 :   if (wrapper_callbacks_.size() <= class_id) {
      49             :     wrapper_callbacks_.insert(wrapper_callbacks_.end(),
      50          10 :                               class_id - wrapper_callbacks_.size() + 1,
      51          30 :                               nullptr);
      52             :   }
      53          10 :   wrapper_callbacks_[class_id] = callback;
      54          10 : }
      55             : 
      56             : 
      57          15 : v8::RetainedObjectInfo* HeapProfiler::ExecuteWrapperClassCallback(
      58             :     uint16_t class_id, Object** wrapper) {
      59          30 :   if (wrapper_callbacks_.size() <= class_id) return nullptr;
      60             :   return wrapper_callbacks_[class_id](
      61          15 :       class_id, Utils::ToLocal(Handle<Object>(wrapper)));
      62             : }
      63             : 
      64           0 : void HeapProfiler::SetGetRetainerInfosCallback(
      65             :     v8::HeapProfiler::GetRetainerInfosCallback callback) {
      66           0 :   get_retainer_infos_callback_ = callback;
      67           0 : }
      68             : 
      69         319 : v8::HeapProfiler::RetainerInfos HeapProfiler::GetRetainerInfos(
      70             :     Isolate* isolate) {
      71             :   v8::HeapProfiler::RetainerInfos infos;
      72         319 :   if (get_retainer_infos_callback_ != nullptr)
      73           0 :     infos =
      74             :         get_retainer_infos_callback_(reinterpret_cast<v8::Isolate*>(isolate));
      75         319 :   return infos;
      76             : }
      77             : 
      78         319 : HeapSnapshot* HeapProfiler::TakeSnapshot(
      79             :     v8::ActivityControl* control,
      80             :     v8::HeapProfiler::ObjectNameResolver* resolver) {
      81         319 :   HeapSnapshot* result = new HeapSnapshot(this);
      82             :   {
      83         319 :     HeapSnapshotGenerator generator(result, control, resolver, heap());
      84         319 :     if (!generator.GenerateSnapshot()) {
      85           5 :       delete result;
      86           5 :       result = nullptr;
      87             :     } else {
      88         314 :       snapshots_.push_back(result);
      89         319 :     }
      90             :   }
      91         319 :   ids_->RemoveDeadEntries();
      92         319 :   is_tracking_object_moves_ = true;
      93             : 
      94             :   heap()->isolate()->debug()->feature_tracker()->Track(
      95         319 :       DebugFeatureTracker::kHeapSnapshot);
      96             : 
      97         319 :   return result;
      98             : }
      99             : 
     100          28 : bool HeapProfiler::StartSamplingHeapProfiler(
     101             :     uint64_t sample_interval, int stack_depth,
     102             :     v8::HeapProfiler::SamplingFlags flags) {
     103          28 :   if (sampling_heap_profiler_.get()) {
     104             :     return false;
     105             :   }
     106             :   sampling_heap_profiler_.reset(new SamplingHeapProfiler(
     107          28 :       heap(), names_.get(), sample_interval, stack_depth, flags));
     108             :   return true;
     109             : }
     110             : 
     111             : 
     112          28 : void HeapProfiler::StopSamplingHeapProfiler() {
     113             :   sampling_heap_profiler_.reset();
     114          28 : }
     115             : 
     116             : 
     117          31 : v8::AllocationProfile* HeapProfiler::GetAllocationProfile() {
     118          31 :   if (sampling_heap_profiler_.get()) {
     119          23 :     return sampling_heap_profiler_->GetAllocationProfile();
     120             :   } else {
     121             :     return nullptr;
     122             :   }
     123             : }
     124             : 
     125             : 
     126          40 : void HeapProfiler::StartHeapObjectsTracking(bool track_allocations) {
     127          40 :   ids_->UpdateHeapObjectsMap();
     128          40 :   is_tracking_object_moves_ = true;
     129             :   DCHECK(!is_tracking_allocations());
     130          40 :   if (track_allocations) {
     131          30 :     allocation_tracker_.reset(new AllocationTracker(ids_.get(), names_.get()));
     132          30 :     heap()->DisableInlineAllocation();
     133             :     heap()->isolate()->debug()->feature_tracker()->Track(
     134          30 :         DebugFeatureTracker::kAllocationTracking);
     135             :   }
     136          40 : }
     137             : 
     138          55 : SnapshotObjectId HeapProfiler::PushHeapObjectsStats(OutputStream* stream,
     139             :                                                     int64_t* timestamp_us) {
     140          55 :   return ids_->PushHeapObjectsStats(stream, timestamp_us);
     141             : }
     142             : 
     143        3446 : void HeapProfiler::StopHeapObjectsTracking() {
     144        3446 :   ids_->StopHeapObjectsTracking();
     145        3446 :   if (is_tracking_allocations()) {
     146             :     allocation_tracker_.reset();
     147          30 :     heap()->EnableInlineAllocation();
     148             :   }
     149        3446 : }
     150             : 
     151         150 : int HeapProfiler::GetSnapshotsCount() {
     152         300 :   return static_cast<int>(snapshots_.size());
     153             : }
     154             : 
     155          30 : HeapSnapshot* HeapProfiler::GetSnapshot(int index) {
     156          60 :   return snapshots_.at(index);
     157             : }
     158             : 
     159         155 : SnapshotObjectId HeapProfiler::GetSnapshotObjectId(Handle<Object> obj) {
     160         155 :   if (!obj->IsHeapObject())
     161             :     return v8::HeapProfiler::kUnknownObjectId;
     162         310 :   return ids_->FindEntry(HeapObject::cast(*obj)->address());
     163             : }
     164             : 
     165      103772 : void HeapProfiler::ObjectMoveEvent(Address from, Address to, int size) {
     166      103772 :   base::LockGuard<base::Mutex> guard(&profiler_mutex_);
     167      103772 :   bool known_object = ids_->MoveObject(from, to, size);
     168      205869 :   if (!known_object && allocation_tracker_) {
     169           0 :     allocation_tracker_->address_to_trace()->MoveObject(from, to, size);
     170             :   }
     171      103772 : }
     172             : 
     173       13279 : void HeapProfiler::AllocationEvent(Address addr, int size) {
     174             :   DisallowHeapAllocation no_allocation;
     175       13279 :   if (allocation_tracker_) {
     176       13279 :     allocation_tracker_->AllocationEvent(addr, size);
     177             :   }
     178       13279 : }
     179             : 
     180             : 
     181           0 : void HeapProfiler::UpdateObjectSizeEvent(Address addr, int size) {
     182           0 :   ids_->UpdateObjectSize(addr, size);
     183           0 : }
     184             : 
     185         140 : Handle<HeapObject> HeapProfiler::FindHeapObjectById(SnapshotObjectId id) {
     186             :   HeapObject* object = nullptr;
     187         140 :   HeapIterator iterator(heap(), HeapIterator::kFilterUnreachable);
     188             :   // Make sure that object with the given id is still reachable.
     189     1083298 :   for (HeapObject* obj = iterator.next(); obj != nullptr;
     190             :        obj = iterator.next()) {
     191     2166316 :     if (ids_->FindEntry(obj->address()) == id) {
     192             :       DCHECK_NULL(object);
     193             :       object = obj;
     194             :       // Can't break -- kFilterUnreachable requires full heap traversal.
     195             :     }
     196             :   }
     197         280 :   return object != nullptr ? Handle<HeapObject>(object) : Handle<HeapObject>();
     198             : }
     199             : 
     200             : 
     201        3411 : void HeapProfiler::ClearHeapObjectMap() {
     202        3411 :   ids_.reset(new HeapObjectsMap(heap()));
     203        3411 :   if (!is_tracking_allocations()) is_tracking_object_moves_ = false;
     204        3411 : }
     205             : 
     206             : 
     207    12022351 : Heap* HeapProfiler::heap() const { return ids_->heap(); }
     208             : 
     209          65 : void HeapProfiler::QueryObjects(Handle<Context> context,
     210             :                                 debug::QueryObjectPredicate* predicate,
     211             :                                 PersistentValueVector<v8::Object>* objects) {
     212             :   // We should return accurate information about live objects, so we need to
     213             :   // collect all garbage first.
     214             :   heap()->CollectAllAvailableGarbage(
     215          65 :       GarbageCollectionReason::kLowMemoryNotification);
     216             :   heap()->CollectAllGarbage(Heap::kMakeHeapIterableMask,
     217          65 :                             GarbageCollectionReason::kHeapProfiler);
     218          65 :   HeapIterator heap_iterator(heap());
     219             :   HeapObject* heap_obj;
     220     1000113 :   while ((heap_obj = heap_iterator.next()) != nullptr) {
     221     2221831 :     if (!heap_obj->IsJSObject() || heap_obj->IsExternal()) continue;
     222             :     v8::Local<v8::Object> v8_obj(
     223      221575 :         Utils::ToLocal(handle(JSObject::cast(heap_obj))));
     224      221575 :     if (!predicate->Filter(v8_obj)) continue;
     225          85 :     objects->Append(v8_obj);
     226          65 :   }
     227          65 : }
     228             : 
     229             : }  // namespace internal
     230             : }  // namespace v8

Generated by: LCOV version 1.10