diff options
Diffstat (limited to 'deps/v8/src/profiler/sampling-heap-profiler.h')
-rw-r--r-- | deps/v8/src/profiler/sampling-heap-profiler.h | 166 |
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_ |