| Index: src/profiler/profiler-listener.h
|
| diff --git a/src/profiler/cpu-profiler.h b/src/profiler/profiler-listener.h
|
| similarity index 13%
|
| copy from src/profiler/cpu-profiler.h
|
| copy to src/profiler/profiler-listener.h
|
| index 31136d00bcd1e95f8cfd64a20bd859a63060385d..7e24ceaa8629d4e9bd34446f6237c62008ed43fe 100644
|
| --- a/src/profiler/cpu-profiler.h
|
| +++ b/src/profiler/profiler-listener.h
|
| @@ -1,227 +1,44 @@
|
| -// Copyright 2012 the V8 project authors. All rights reserved.
|
| +// Copyright 2016 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_CPU_PROFILER_H_
|
| -#define V8_PROFILER_CPU_PROFILER_H_
|
| +#ifndef V8_PROFILER_PROFILER_LISTENER_H_
|
| +#define V8_PROFILER_PROFILER_LISTENER_H_
|
|
|
| -#include <memory>
|
| +#include <vector>
|
|
|
| -#include "src/allocation.h"
|
| -#include "src/base/atomic-utils.h"
|
| -#include "src/base/atomicops.h"
|
| -#include "src/base/platform/time.h"
|
| -#include "src/compiler.h"
|
| -#include "src/isolate.h"
|
| -#include "src/libsampler/v8-sampler.h"
|
| -#include "src/locked-queue.h"
|
| -#include "src/profiler/circular-queue.h"
|
| -#include "src/profiler/tick-sample.h"
|
| +#include "src/code-events.h"
|
| +#include "src/profiler/profile-generator.h"
|
|
|
| namespace v8 {
|
| namespace internal {
|
|
|
| -// Forward declarations.
|
| -class CodeEntry;
|
| -class CodeMap;
|
| -class CpuProfile;
|
| -class CpuProfilesCollection;
|
| -class ProfileGenerator;
|
| +class CodeEventsContainer;
|
|
|
| -#define CODE_EVENTS_TYPE_LIST(V) \
|
| - V(CODE_CREATION, CodeCreateEventRecord) \
|
| - V(CODE_MOVE, CodeMoveEventRecord) \
|
| - V(CODE_DISABLE_OPT, CodeDisableOptEventRecord) \
|
| - V(CODE_DEOPT, CodeDeoptEventRecord) \
|
| - V(REPORT_BUILTIN, ReportBuiltinEventRecord)
|
| -
|
| -
|
| -class CodeEventRecord {
|
| - public:
|
| -#define DECLARE_TYPE(type, ignore) type,
|
| - enum Type {
|
| - NONE = 0,
|
| - CODE_EVENTS_TYPE_LIST(DECLARE_TYPE)
|
| - NUMBER_OF_TYPES
|
| - };
|
| -#undef DECLARE_TYPE
|
| -
|
| - Type type;
|
| - mutable unsigned order;
|
| -};
|
| -
|
| -
|
| -class CodeCreateEventRecord : public CodeEventRecord {
|
| - public:
|
| - Address start;
|
| - CodeEntry* entry;
|
| - unsigned size;
|
| -
|
| - INLINE(void UpdateCodeMap(CodeMap* code_map));
|
| -};
|
| -
|
| -
|
| -class CodeMoveEventRecord : public CodeEventRecord {
|
| +class CodeEventObserver {
|
| public:
|
| - Address from;
|
| - Address to;
|
| -
|
| - INLINE(void UpdateCodeMap(CodeMap* code_map));
|
| + virtual void CodeEventHandler(const CodeEventsContainer& evt_rec) = 0;
|
| + virtual ~CodeEventObserver() {}
|
| };
|
|
|
| -
|
| -class CodeDisableOptEventRecord : public CodeEventRecord {
|
| +class ProfilerListener : public CodeEventListener {
|
| public:
|
| - Address start;
|
| - const char* bailout_reason;
|
| -
|
| - INLINE(void UpdateCodeMap(CodeMap* code_map));
|
| -};
|
| -
|
| -
|
| -class CodeDeoptEventRecord : public CodeEventRecord {
|
| - public:
|
| - Address start;
|
| - const char* deopt_reason;
|
| - SourcePosition position;
|
| - int deopt_id;
|
| -
|
| - INLINE(void UpdateCodeMap(CodeMap* code_map));
|
| -};
|
| -
|
| -
|
| -class ReportBuiltinEventRecord : public CodeEventRecord {
|
| - public:
|
| - Address start;
|
| - Builtins::Name builtin_id;
|
| -
|
| - INLINE(void UpdateCodeMap(CodeMap* code_map));
|
| -};
|
| -
|
| -
|
| -class TickSampleEventRecord {
|
| - public:
|
| - // The parameterless constructor is used when we dequeue data from
|
| - // the ticks buffer.
|
| - TickSampleEventRecord() { }
|
| - explicit TickSampleEventRecord(unsigned order) : order(order) { }
|
| -
|
| - unsigned order;
|
| - TickSample sample;
|
| -};
|
| + explicit ProfilerListener(Isolate* isolate);
|
| + ~ProfilerListener() override;
|
|
|
| -
|
| -class CodeEventsContainer {
|
| - public:
|
| - explicit CodeEventsContainer(
|
| - CodeEventRecord::Type type = CodeEventRecord::NONE) {
|
| - generic.type = type;
|
| - }
|
| - union {
|
| - CodeEventRecord generic;
|
| -#define DECLARE_CLASS(ignore, type) type type##_;
|
| - CODE_EVENTS_TYPE_LIST(DECLARE_CLASS)
|
| -#undef DECLARE_TYPE
|
| - };
|
| -};
|
| -
|
| -
|
| -// This class implements both the profile events processor thread and
|
| -// methods called by event producers: VM and stack sampler threads.
|
| -class ProfilerEventsProcessor : public base::Thread {
|
| - public:
|
| - ProfilerEventsProcessor(ProfileGenerator* generator,
|
| - sampler::Sampler* sampler,
|
| - base::TimeDelta period);
|
| - virtual ~ProfilerEventsProcessor();
|
| -
|
| - // Thread control.
|
| - virtual void Run();
|
| - void StopSynchronously();
|
| - INLINE(bool running()) { return !!base::NoBarrier_Load(&running_); }
|
| - void Enqueue(const CodeEventsContainer& event);
|
| -
|
| - // Puts current stack into tick sample events buffer.
|
| - void AddCurrentStack(Isolate* isolate, bool update_stats = false);
|
| - void AddDeoptStack(Isolate* isolate, Address from, int fp_to_sp_delta);
|
| -
|
| - // Tick sample events are filled directly in the buffer of the circular
|
| - // queue (because the structure is of fixed width, but usually not all
|
| - // stack frame entries are filled.) This method returns a pointer to the
|
| - // next record of the buffer.
|
| - inline TickSample* StartTickSample();
|
| - inline void FinishTickSample();
|
| -
|
| - // SamplingCircularQueue has stricter alignment requirements than a normal new
|
| - // can fulfil, so we need to provide our own new/delete here.
|
| - void* operator new(size_t size);
|
| - void operator delete(void* ptr);
|
| -
|
| - private:
|
| - // Called from events processing thread (Run() method.)
|
| - bool ProcessCodeEvent();
|
| -
|
| - enum SampleProcessingResult {
|
| - OneSampleProcessed,
|
| - FoundSampleForNextCodeEvent,
|
| - NoSamplesInQueue
|
| - };
|
| - SampleProcessingResult ProcessOneSample();
|
| -
|
| - ProfileGenerator* generator_;
|
| - sampler::Sampler* sampler_;
|
| - base::Atomic32 running_;
|
| - const base::TimeDelta period_; // Samples & code events processing period.
|
| - LockedQueue<CodeEventsContainer> events_buffer_;
|
| - static const size_t kTickSampleBufferSize = 1 * MB;
|
| - static const size_t kTickSampleQueueLength =
|
| - kTickSampleBufferSize / sizeof(TickSampleEventRecord);
|
| - SamplingCircularQueue<TickSampleEventRecord,
|
| - kTickSampleQueueLength> ticks_buffer_;
|
| - LockedQueue<TickSampleEventRecord> ticks_from_vm_buffer_;
|
| - base::AtomicNumber<unsigned> last_code_event_id_;
|
| - unsigned last_processed_code_event_id_;
|
| -};
|
| -
|
| -class CpuProfiler : public CodeEventListener {
|
| - public:
|
| - explicit CpuProfiler(Isolate* isolate);
|
| -
|
| - CpuProfiler(Isolate* isolate, CpuProfilesCollection* profiles,
|
| - ProfileGenerator* test_generator,
|
| - ProfilerEventsProcessor* test_processor);
|
| -
|
| - ~CpuProfiler() override;
|
| -
|
| - void set_sampling_interval(base::TimeDelta value);
|
| - void CollectSample();
|
| - void StartProfiling(const char* title, bool record_samples = false);
|
| - void StartProfiling(String* title, bool record_samples);
|
| - CpuProfile* StopProfiling(const char* title);
|
| - CpuProfile* StopProfiling(String* title);
|
| - int GetProfilesCount();
|
| - CpuProfile* GetProfile(int index);
|
| - void DeleteAllProfiles();
|
| - void DeleteProfile(CpuProfile* profile);
|
| -
|
| - // Invoked from stack sampler (thread or signal handler.)
|
| - inline TickSample* StartTickSample();
|
| - inline void FinishTickSample();
|
| -
|
| - // Must be called via PROFILE macro, otherwise will crash when
|
| - // profiling is not enabled.
|
| void CallbackEvent(Name* name, Address entry_point) override;
|
| - void CodeCreateEvent(LogEventsAndTags tag, AbstractCode* code,
|
| - const char* comment) override;
|
| - void CodeCreateEvent(LogEventsAndTags tag, AbstractCode* code,
|
| - Name* name) override;
|
| - void CodeCreateEvent(LogEventsAndTags tag, AbstractCode* code,
|
| - SharedFunctionInfo* shared, Name* script_name) override;
|
| - void CodeCreateEvent(LogEventsAndTags tag, AbstractCode* code,
|
| - SharedFunctionInfo* shared, Name* script_name, int line,
|
| - int column) override;
|
| - void CodeCreateEvent(LogEventsAndTags tag, AbstractCode* code,
|
| - int args_count) override;
|
| + void CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
|
| + AbstractCode* code, const char* comment) override;
|
| + void CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
|
| + AbstractCode* code, Name* name) override;
|
| + void CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
|
| + AbstractCode* code, SharedFunctionInfo* shared,
|
| + Name* script_name) override;
|
| + void CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
|
| + AbstractCode* code, SharedFunctionInfo* shared,
|
| + Name* script_name, int line, int column) override;
|
| + void CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
|
| + AbstractCode* code, int args_count) override;
|
| void CodeMovingGCEvent() override {}
|
| void CodeMoveEvent(AbstractCode* from, Address to) override;
|
| void CodeDisableOptEvent(AbstractCode* code,
|
| @@ -232,35 +49,49 @@ class CpuProfiler : public CodeEventListener {
|
| void SetterCallbackEvent(Name* name, Address entry_point) override;
|
| void SharedFunctionInfoMoveEvent(Address from, Address to) override {}
|
|
|
| - bool is_profiling() const { return is_profiling_; }
|
| + CodeEntry* NewCodeEntry(
|
| + CodeEventListener::LogEventsAndTags tag, const char* name,
|
| + const char* name_prefix = CodeEntry::kEmptyNamePrefix,
|
| + const char* resource_name = CodeEntry::kEmptyResourceName,
|
| + int line_number = v8::CpuProfileNode::kNoLineNumberInfo,
|
| + int column_number = v8::CpuProfileNode::kNoColumnNumberInfo,
|
| + JITLineInfoTable* line_info = NULL, Address instruction_start = NULL);
|
|
|
| - ProfileGenerator* generator() const { return generator_.get(); }
|
| - ProfilerEventsProcessor* processor() const { return processor_.get(); }
|
| - Isolate* isolate() const { return isolate_; }
|
| + void AddObserver(CodeEventObserver* observer);
|
| + void RemoveObserver(CodeEventObserver* observer);
|
| + V8_INLINE bool HasObservers() { return !observers_.empty(); }
|
| +
|
| + const char* GetName(Name* name) {
|
| + return function_and_resource_names_.GetName(name);
|
| + }
|
| + const char* GetName(int args_count) {
|
| + return function_and_resource_names_.GetName(args_count);
|
| + }
|
| + const char* GetFunctionName(Name* name) {
|
| + return function_and_resource_names_.GetFunctionName(name);
|
| + }
|
| + const char* GetFunctionName(const char* name) {
|
| + return function_and_resource_names_.GetFunctionName(name);
|
| + }
|
|
|
| private:
|
| - void StartProcessorIfNotStarted();
|
| - void StopProcessorIfLastProfile(const char* title);
|
| - void StopProcessor();
|
| - void ResetProfiles();
|
| - void LogBuiltins();
|
| void RecordInliningInfo(CodeEntry* entry, AbstractCode* abstract_code);
|
| void RecordDeoptInlinedFrames(CodeEntry* entry, AbstractCode* abstract_code);
|
| Name* InferScriptName(Name* name, SharedFunctionInfo* info);
|
| + V8_INLINE void DispatchCodeEvent(const CodeEventsContainer& evt_rec) {
|
| + for (auto observer : observers_) {
|
| + observer->CodeEventHandler(evt_rec);
|
| + }
|
| + }
|
|
|
| - Isolate* const isolate_;
|
| - base::TimeDelta sampling_interval_;
|
| - std::unique_ptr<CpuProfilesCollection> profiles_;
|
| - std::unique_ptr<ProfileGenerator> generator_;
|
| - std::unique_ptr<ProfilerEventsProcessor> processor_;
|
| - bool saved_is_logging_;
|
| - bool is_profiling_;
|
| + StringsStorage function_and_resource_names_;
|
| + std::vector<CodeEntry*> code_entries_;
|
| + std::vector<CodeEventObserver*> observers_;
|
|
|
| - DISALLOW_COPY_AND_ASSIGN(CpuProfiler);
|
| + DISALLOW_COPY_AND_ASSIGN(ProfilerListener);
|
| };
|
|
|
| } // namespace internal
|
| } // namespace v8
|
|
|
| -
|
| -#endif // V8_PROFILER_CPU_PROFILER_H_
|
| +#endif // V8_PROFILER_PROFILER_LISTENER_H_
|
|
|