LCOV - code coverage report
Current view: top level - src/profiler - heap-profiler.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 90 101 89.1 %
Date: 2017-04-26 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       60782 : HeapProfiler::HeapProfiler(Heap* heap)
      18       60782 :     : ids_(new HeapObjectsMap(heap)),
      19       60782 :       names_(new StringsStorage(heap)),
      20             :       is_tracking_object_moves_(false),
      21      182346 :       get_retainer_infos_callback_(nullptr) {}
      22             : 
      23         353 : static void DeleteHeapSnapshot(HeapSnapshot** snapshot_ptr) {
      24         353 :   delete *snapshot_ptr;
      25         353 : }
      26             : 
      27             : 
      28      118570 : HeapProfiler::~HeapProfiler() {
      29             :   snapshots_.Iterate(DeleteHeapSnapshot);
      30             :   snapshots_.Clear();
      31       59285 : }
      32             : 
      33             : 
      34          54 : void HeapProfiler::DeleteAllSnapshots() {
      35             :   snapshots_.Iterate(DeleteHeapSnapshot);
      36             :   snapshots_.Clear();
      37          54 :   names_.reset(new StringsStorage(heap()));
      38          54 : }
      39             : 
      40             : 
      41           6 : void HeapProfiler::RemoveSnapshot(HeapSnapshot* snapshot) {
      42           6 :   snapshots_.RemoveElement(snapshot);
      43           6 : }
      44             : 
      45             : 
      46          12 : void HeapProfiler::DefineWrapperClass(
      47             :     uint16_t class_id, v8::HeapProfiler::WrapperInfoCallback callback) {
      48             :   DCHECK(class_id != v8::HeapProfiler::kPersistentHandleNoClassId);
      49          24 :   if (wrapper_callbacks_.length() <= class_id) {
      50             :     wrapper_callbacks_.AddBlock(
      51          12 :         NULL, class_id - wrapper_callbacks_.length() + 1);
      52             :   }
      53          12 :   wrapper_callbacks_[class_id] = callback;
      54          12 : }
      55             : 
      56             : 
      57          18 : v8::RetainedObjectInfo* HeapProfiler::ExecuteWrapperClassCallback(
      58             :     uint16_t class_id, Object** wrapper) {
      59          18 :   if (wrapper_callbacks_.length() <= class_id) return NULL;
      60             :   return wrapper_callbacks_[class_id](
      61          18 :       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         365 : v8::HeapProfiler::RetainerInfos HeapProfiler::GetRetainerInfos(
      70             :     Isolate* isolate) {
      71             :   v8::HeapProfiler::RetainerInfos infos;
      72         365 :   if (get_retainer_infos_callback_ != nullptr)
      73           0 :     infos =
      74             :         get_retainer_infos_callback_(reinterpret_cast<v8::Isolate*>(isolate));
      75         365 :   return infos;
      76             : }
      77             : 
      78         365 : HeapSnapshot* HeapProfiler::TakeSnapshot(
      79             :     v8::ActivityControl* control,
      80             :     v8::HeapProfiler::ObjectNameResolver* resolver) {
      81         365 :   HeapSnapshot* result = new HeapSnapshot(this);
      82             :   {
      83         365 :     HeapSnapshotGenerator generator(result, control, resolver, heap());
      84         365 :     if (!generator.GenerateSnapshot()) {
      85           6 :       delete result;
      86             :       result = NULL;
      87             :     } else {
      88         359 :       snapshots_.Add(result);
      89         365 :     }
      90             :   }
      91         365 :   ids_->RemoveDeadEntries();
      92         365 :   is_tracking_object_moves_ = true;
      93             : 
      94             :   heap()->isolate()->debug()->feature_tracker()->Track(
      95         365 :       DebugFeatureTracker::kHeapSnapshot);
      96             : 
      97         365 :   return result;
      98             : }
      99             : 
     100          36 : bool HeapProfiler::StartSamplingHeapProfiler(
     101             :     uint64_t sample_interval, int stack_depth,
     102             :     v8::HeapProfiler::SamplingFlags flags) {
     103          36 :   if (sampling_heap_profiler_.get()) {
     104             :     return false;
     105             :   }
     106             :   sampling_heap_profiler_.reset(new SamplingHeapProfiler(
     107          36 :       heap(), names_.get(), sample_interval, stack_depth, flags));
     108             :   return true;
     109             : }
     110             : 
     111             : 
     112          36 : void HeapProfiler::StopSamplingHeapProfiler() {
     113             :   sampling_heap_profiler_.reset();
     114          36 : }
     115             : 
     116             : 
     117          42 : v8::AllocationProfile* HeapProfiler::GetAllocationProfile() {
     118          42 :   if (sampling_heap_profiler_.get()) {
     119          30 :     return sampling_heap_profiler_->GetAllocationProfile();
     120             :   } else {
     121             :     return nullptr;
     122             :   }
     123             : }
     124             : 
     125             : 
     126          48 : void HeapProfiler::StartHeapObjectsTracking(bool track_allocations) {
     127          48 :   ids_->UpdateHeapObjectsMap();
     128          48 :   is_tracking_object_moves_ = true;
     129             :   DCHECK(!is_tracking_allocations());
     130          48 :   if (track_allocations) {
     131          36 :     allocation_tracker_.reset(new AllocationTracker(ids_.get(), names_.get()));
     132          36 :     heap()->DisableInlineAllocation();
     133             :     heap()->isolate()->debug()->feature_tracker()->Track(
     134          36 :         DebugFeatureTracker::kAllocationTracking);
     135             :   }
     136          48 : }
     137             : 
     138             : 
     139          66 : SnapshotObjectId HeapProfiler::PushHeapObjectsStats(OutputStream* stream,
     140             :                                                     int64_t* timestamp_us) {
     141          66 :   return ids_->PushHeapObjectsStats(stream, timestamp_us);
     142             : }
     143             : 
     144             : 
     145        4747 : void HeapProfiler::StopHeapObjectsTracking() {
     146        4747 :   ids_->StopHeapObjectsTracking();
     147        4747 :   if (is_tracking_allocations()) {
     148             :     allocation_tracker_.reset();
     149          36 :     heap()->EnableInlineAllocation();
     150             :   }
     151        4747 : }
     152             : 
     153             : 
     154           0 : size_t HeapProfiler::GetMemorySizeUsedByProfiler() {
     155             :   size_t size = sizeof(*this);
     156           0 :   size += names_->GetUsedMemorySize();
     157           0 :   size += ids_->GetUsedMemorySize();
     158           0 :   size += GetMemoryUsedByList(snapshots_);
     159           0 :   for (int i = 0; i < snapshots_.length(); ++i) {
     160           0 :     size += snapshots_[i]->RawSnapshotSize();
     161             :   }
     162           0 :   return size;
     163             : }
     164             : 
     165             : 
     166         168 : int HeapProfiler::GetSnapshotsCount() {
     167         168 :   return snapshots_.length();
     168             : }
     169             : 
     170             : 
     171          36 : HeapSnapshot* HeapProfiler::GetSnapshot(int index) {
     172          36 :   return snapshots_.at(index);
     173             : }
     174             : 
     175             : 
     176         186 : SnapshotObjectId HeapProfiler::GetSnapshotObjectId(Handle<Object> obj) {
     177         186 :   if (!obj->IsHeapObject())
     178             :     return v8::HeapProfiler::kUnknownObjectId;
     179         372 :   return ids_->FindEntry(HeapObject::cast(*obj)->address());
     180             : }
     181             : 
     182             : 
     183      123131 : void HeapProfiler::ObjectMoveEvent(Address from, Address to, int size) {
     184      123131 :   base::LockGuard<base::Mutex> guard(&profiler_mutex_);
     185      123131 :   bool known_object = ids_->MoveObject(from, to, size);
     186      244043 :   if (!known_object && allocation_tracker_) {
     187           6 :     allocation_tracker_->address_to_trace()->MoveObject(from, to, size);
     188             :   }
     189      123131 : }
     190             : 
     191             : 
     192       17228 : void HeapProfiler::AllocationEvent(Address addr, int size) {
     193             :   DisallowHeapAllocation no_allocation;
     194       17228 :   if (allocation_tracker_) {
     195       17228 :     allocation_tracker_->AllocationEvent(addr, size);
     196             :   }
     197       17228 : }
     198             : 
     199             : 
     200           6 : void HeapProfiler::UpdateObjectSizeEvent(Address addr, int size) {
     201           6 :   ids_->UpdateObjectSize(addr, size);
     202           6 : }
     203             : 
     204         168 : Handle<HeapObject> HeapProfiler::FindHeapObjectById(SnapshotObjectId id) {
     205             :   HeapObject* object = NULL;
     206         168 :   HeapIterator iterator(heap(), HeapIterator::kFilterUnreachable);
     207             :   // Make sure that object with the given id is still reachable.
     208     1525188 :   for (HeapObject* obj = iterator.next();
     209             :        obj != NULL;
     210             :        obj = iterator.next()) {
     211     3050040 :     if (ids_->FindEntry(obj->address()) == id) {
     212             :       DCHECK(object == NULL);
     213             :       object = obj;
     214             :       // Can't break -- kFilterUnreachable requires full heap traversal.
     215             :     }
     216             :   }
     217         336 :   return object != NULL ? Handle<HeapObject>(object) : Handle<HeapObject>();
     218             : }
     219             : 
     220             : 
     221        4705 : void HeapProfiler::ClearHeapObjectMap() {
     222        4705 :   ids_.reset(new HeapObjectsMap(heap()));
     223        4705 :   if (!is_tracking_allocations()) is_tracking_object_moves_ = false;
     224        4705 : }
     225             : 
     226             : 
     227    14416371 : Heap* HeapProfiler::heap() const { return ids_->heap(); }
     228             : 
     229             : 
     230             : }  // namespace internal
     231             : }  // namespace v8

Generated by: LCOV version 1.10