summaryrefslogtreecommitdiff
path: root/deps/v8/src/profiler/sampling-heap-profiler.h
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/profiler/sampling-heap-profiler.h')
-rw-r--r--deps/v8/src/profiler/sampling-heap-profiler.h166
1 files changed, 166 insertions, 0 deletions
diff --git a/deps/v8/src/profiler/sampling-heap-profiler.h b/deps/v8/src/profiler/sampling-heap-profiler.h
new file mode 100644
index 0000000000..0b538b070c
--- /dev/null
+++ b/deps/v8/src/profiler/sampling-heap-profiler.h
@@ -0,0 +1,166 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef V8_PROFILER_SAMPLING_HEAP_PROFILER_H_
+#define V8_PROFILER_SAMPLING_HEAP_PROFILER_H_
+
+#include <deque>
+#include <map>
+#include <set>
+#include "include/v8-profiler.h"
+#include "src/heap/heap.h"
+#include "src/profiler/strings-storage.h"
+
+namespace v8 {
+
+namespace base {
+class RandomNumberGenerator;
+}
+
+namespace internal {
+
+class SamplingAllocationObserver;
+
+class AllocationProfile : public v8::AllocationProfile {
+ public:
+ AllocationProfile() : nodes_() {}
+
+ v8::AllocationProfile::Node* GetRootNode() override {
+ return nodes_.size() == 0 ? nullptr : &nodes_.front();
+ }
+
+ std::deque<v8::AllocationProfile::Node>& nodes() { return nodes_; }
+
+ private:
+ std::deque<v8::AllocationProfile::Node> nodes_;
+
+ DISALLOW_COPY_AND_ASSIGN(AllocationProfile);
+};
+
+class SamplingHeapProfiler {
+ public:
+ SamplingHeapProfiler(Heap* heap, StringsStorage* names, uint64_t rate,
+ int stack_depth);
+ ~SamplingHeapProfiler();
+
+ v8::AllocationProfile* GetAllocationProfile();
+
+ StringsStorage* names() const { return names_; }
+
+ class AllocationNode;
+
+ struct Sample {
+ public:
+ Sample(size_t size_, AllocationNode* owner_, Local<Value> local_,
+ SamplingHeapProfiler* profiler_)
+ : size(size_),
+ owner(owner_),
+ global(Global<Value>(
+ reinterpret_cast<v8::Isolate*>(profiler_->isolate_), local_)),
+ profiler(profiler_) {}
+ ~Sample() { global.Reset(); }
+ const size_t size;
+ AllocationNode* const owner;
+ Global<Value> global;
+ SamplingHeapProfiler* const profiler;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(Sample);
+ };
+
+ class AllocationNode {
+ public:
+ AllocationNode(const char* const name, int script_id,
+ const int start_position)
+ : script_id_(script_id),
+ script_position_(start_position),
+ name_(name) {}
+ ~AllocationNode() {
+ for (auto child : children_) {
+ delete child;
+ }
+ }
+
+ private:
+ std::map<size_t, unsigned int> allocations_;
+ std::vector<AllocationNode*> children_;
+ const int script_id_;
+ const int script_position_;
+ const char* const name_;
+
+ friend class SamplingHeapProfiler;
+
+ DISALLOW_COPY_AND_ASSIGN(AllocationNode);
+ };
+
+ private:
+ Heap* heap() const { return heap_; }
+
+ void SampleObject(Address soon_object, size_t size);
+
+ static void OnWeakCallback(const WeakCallbackInfo<Sample>& data);
+
+ // Methods that construct v8::AllocationProfile.
+
+ // Translates the provided AllocationNode *node* returning an equivalent
+ // AllocationProfile::Node. The newly created AllocationProfile::Node is added
+ // to the provided AllocationProfile *profile*. Line numbers, column numbers,
+ // and script names are resolved using *scripts* which maps all currently
+ // loaded scripts keyed by their script id.
+ v8::AllocationProfile::Node* TranslateAllocationNode(
+ AllocationProfile* profile, SamplingHeapProfiler::AllocationNode* node,
+ const std::map<int, Script*>& scripts);
+ v8::AllocationProfile::Allocation ScaleSample(size_t size,
+ unsigned int count);
+ AllocationNode* AddStack();
+ AllocationNode* FindOrAddChildNode(AllocationNode* parent, const char* name,
+ int script_id, int start_position);
+
+ Isolate* const isolate_;
+ Heap* const heap_;
+ base::SmartPointer<SamplingAllocationObserver> new_space_observer_;
+ base::SmartPointer<SamplingAllocationObserver> other_spaces_observer_;
+ StringsStorage* const names_;
+ AllocationNode profile_root_;
+ std::set<Sample*> samples_;
+ const int stack_depth_;
+ const uint64_t rate_;
+
+ friend class SamplingAllocationObserver;
+};
+
+class SamplingAllocationObserver : public AllocationObserver {
+ public:
+ SamplingAllocationObserver(Heap* heap, intptr_t step_size, uint64_t rate,
+ SamplingHeapProfiler* profiler,
+ base::RandomNumberGenerator* random)
+ : AllocationObserver(step_size),
+ profiler_(profiler),
+ heap_(heap),
+ random_(random),
+ rate_(rate) {}
+ virtual ~SamplingAllocationObserver() {}
+
+ protected:
+ void Step(int bytes_allocated, Address soon_object, size_t size) override {
+ USE(heap_);
+ DCHECK(heap_->gc_state() == Heap::NOT_IN_GC);
+ DCHECK(soon_object);
+ profiler_->SampleObject(soon_object, size);
+ }
+
+ intptr_t GetNextStepSize() override { return GetNextSampleInterval(rate_); }
+
+ private:
+ intptr_t GetNextSampleInterval(uint64_t rate);
+ SamplingHeapProfiler* const profiler_;
+ Heap* const heap_;
+ base::RandomNumberGenerator* const random_;
+ uint64_t const rate_;
+};
+
+} // namespace internal
+} // namespace v8
+
+#endif // V8_PROFILER_SAMPLING_HEAP_PROFILER_H_