5#ifndef RUNTIME_VM_PROFILER_H_
6#define RUNTIME_VM_PROFILER_H_
27class ProcessedSampleBuffer;
32#define PROFILER_COUNTERS(V) \
33 V(bail_out_unknown_task) \
34 V(bail_out_jump_to_exception_handler) \
35 V(bail_out_check_isolate) \
36 V(single_frame_sample_deoptimizing) \
37 V(single_frame_sample_get_and_validate_stack_bounds) \
38 V(stack_walker_native) \
39 V(stack_walker_dart_exit) \
40 V(stack_walker_dart) \
41 V(stack_walker_none) \
42 V(incomplete_sample_fp_bounds) \
43 V(incomplete_sample_fp_step) \
44 V(incomplete_sample_bad_pc) \
45 V(sample_allocation_failure)
48#define DECLARE_PROFILER_COUNTER(name) RelaxedAtomic<int64_t> name;
50#undef DECLARE_PROFILER_COUNTER
68 return sample_block_buffer_;
71 sample_block_buffer_ =
buffer;
79 uint32_t identity_hash);
95 inline static intptr_t
Size();
108 static intptr_t CalculateSampleBufferCapacity();
111 static void SampleThreadSingleFrame(
Thread* thread,
130 virtual void Reset() { visited_ = 0; }
148 intptr_t thread_task_mask,
149 int64_t time_origin_micros,
150 int64_t time_extent_micros,
153 thread_task_mask_(thread_task_mask),
154 time_origin_micros_(time_origin_micros),
155 time_extent_micros_(time_extent_micros),
157 ASSERT(thread_task_mask != 0);
158 ASSERT(time_origin_micros_ >= -1);
159 ASSERT(time_extent_micros_ >= -1);
181 intptr_t thread_task_mask_;
182 int64_t time_origin_micros_;
183 int64_t time_extent_micros_;
217 stack_buffer_[i] = 0;
226 allocation_identity_hash_ = 0;
254 char* native_symbol_name =
256 if (native_symbol_name ==
nullptr) {
315 return allocation_identity_hash_;
319 allocation_identity_hash_ =
hash;
371 kLeafFrameIsDartBit = 1,
374 kMissingFrameInsertedBit = 4,
375 kTruncatedTraceBit = 5,
376 kClassAllocationSampleBit = 6,
377 kContinuationSampleBit = 7,
382 class HeadSampleBit :
public BitField<uint32_t, bool, kHeadSampleBit, 1> {};
383 class LeafFrameIsDart
384 :
public BitField<uint32_t, bool, kLeafFrameIsDartBit, 1> {};
385 class IgnoreBit :
public BitField<uint32_t, bool, kIgnoreBit, 1> {};
386 class ExitFrameBit :
public BitField<uint32_t, bool, kExitFrameBit, 1> {};
387 class MissingFrameInsertedBit
388 :
public BitField<uint32_t, bool, kMissingFrameInsertedBit, 1> {};
389 class TruncatedTraceBit
390 :
public BitField<uint32_t, bool, kTruncatedTraceBit, 1> {};
391 class ClassAllocationSampleBit
392 :
public BitField<uint32_t, bool, kClassAllocationSampleBit, 1> {};
393 class ContinuationSampleBit
394 :
public BitField<uint32_t, bool, kContinuationSampleBit, 1> {};
396 :
public BitField<uint32_t, Thread::TaskKind, kThreadTaskBit, 7> {};
397 class MetadataBits :
public BitField<uint32_t, intptr_t, kMetadataBit, 16> {};
408 uint32_t allocation_identity_hash_;
424 return Code::Cast(code_).PayloadStart();
429 return Code::Cast(code_).Size();
433 if (code_.IsCode()) {
434 return Code::Cast(code_).compile_timestamp();
441 if (code_.IsCode()) {
442 return Code::Cast(code_).Name();
449 if (code_.IsCode()) {
450 return Code::Cast(code_).QualifiedName(
458 if (code_.IsCode()) {
459 return Code::Cast(code_).IsStubCode();
466 if (code_.IsCode()) {
467 return Code::Cast(code_).IsAllocationStubCode();
474 if (code_.IsCode()) {
475 return Code::Cast(code_).IsTypeTestStubCode();
482 if (code_.IsCode()) {
483 return Code::Cast(code_).owner();
490 bool IsCode()
const {
return code_.IsCode(); }
493 if (code_.IsCode()) {
494 return Code::Cast(code_).is_optimized();
521 return (pc >=
Start()) && (pc <
end);
528 uword a_start = (*a)->Start();
529 uword b_start = (*b)->Start();
531 if (a_start < b_start) {
533 }
else if (a_start > b_start) {
551 intptr_t
length()
const {
return code_objects_.length(); }
554 return code_objects_.At(index);
560 void Build(
Thread* thread);
562 void Add(
const Object& code);
578 ASSERT(samples !=
nullptr);
585 ASSERT(visitor !=
nullptr);
587 for (intptr_t i = 0; i <
length; i++) {
597 if (sample->
port() != visitor->
port()) {
605 if (sample->
At(0) == 0) {
661 std::memory_order success_order = std::memory_order_acquire;
662 std::memory_order failure_order = std::memory_order_relaxed;
663 return state_.compare_exchange_strong(expected, desired, success_order,
669 std::memory_order success_order = std::memory_order_acquire;
670 std::memory_order failure_order = std::memory_order_relaxed;
671 if (
state_.compare_exchange_strong(expected, desired, success_order,
685 if (
owner_ != isolate)
return false;
689 std::memory_order success_order = std::memory_order_acquire;
690 std::memory_order failure_order = std::memory_order_relaxed;
691 return state_.compare_exchange_strong(expected, desired, success_order,
707 std::memory_order success_order = std::memory_order_acquire;
708 std::memory_order failure_order = std::memory_order_relaxed;
709 if (
state_.compare_exchange_strong(expected, desired, success_order,
750 ASSERT(visitor !=
nullptr);
751 for (intptr_t i = 0; i < capacity_; ++i) {
776 Sample* ReserveSampleImpl(
Isolate* isolate,
bool allocation_sample);
796 if (sample_block_buffer_ !=
nullptr) {
797 size += sample_block_buffer_->
Size();
847 return allocation_identity_hash_;
850 allocation_identity_hash_ =
hash;
868 uword* stack_buffer);
873 uword* stack_buffer);
880 intptr_t allocation_cid_;
881 uint32_t allocation_identity_hash_;
883 bool first_frame_executing_;
896 intptr_t
length()
const {
return samples_.length(); }
901 return *code_lookup_table_;
919 static constexpr intptr_t kMaxThreads = 4096;
920 static bool initialized_;
921 static bool shutdown_;
922 static bool thread_running_;
926 static void ThreadMain(
uword parameters);
static float next(float f)
static uint32_t hash(const SkShaderBase::GradientInfo &v)
bool IsAllocationStubCode() const
AbstractCode(ObjectPtr code)
const char * QualifiedName() const
const Object * handle() const
const char * Name() const
bool IsTypeTestStubCode() const
bool is_optimized() const
uword PayloadStart() const
int64_t compile_timestamp() const
void InsertAt(intptr_t idx, const T &value)
static constexpr bool decode(uint32_t value)
static constexpr uint32_t update(bool value, uint32_t original)
virtual void VisitSample(Sample *sample)
int64_t CompileTimestamp() const
bool Contains(uword pc) const
const AbstractCode code() const
static int Compare(CodeDescriptor *const *a, CodeDescriptor *const *b)
const char * Name() const
const CodeDescriptor * At(intptr_t index) const
const CodeDescriptor * FindCode(uword pc) const
static void FreeSymbolName(char *name)
static char * LookupSymbolName(uword pc, uword *start)
static const ThreadId kInvalidThreadId
static void static void PrintErr(const char *format,...) PRINTF_ATTRIBUTE(1
ProcessedSample * At(intptr_t index)
const CodeLookupTable & code_lookup_table() const
void Add(ProcessedSample *sample)
void set_tid(ThreadId tid)
void set_allocation_cid(intptr_t cid)
uword At(intptr_t index) const
void set_truncated(bool truncated)
bool first_frame_executing() const
void set_first_frame_executing(bool first_frame_executing)
void set_timestamp(int64_t timestamp)
int64_t timestamp() const
bool IsAllocationSample() const
uint32_t allocation_identity_hash() const
void set_vm_tag(uword tag)
void InsertAt(intptr_t index, uword pc)
void set_allocation_identity_hash(uint32_t hash)
void set_user_tag(uword tag)
intptr_t allocation_cid() const
static void DumpStackTrace(void *context)
static void IsolateShutdown(Thread *thread)
static void SampleAllocation(Thread *thread, intptr_t cid, uint32_t identity_hash)
static void SetSampleDepth(intptr_t depth)
static ProfilerCounters counters()
static void UpdateRunningState()
static void set_sample_block_buffer(SampleBlockBuffer *buffer)
static void SampleThread(Thread *thread, const InterruptedThreadState &state)
static void ProcessCompletedBlocks(Isolate *isolate)
static SampleBlockBuffer * sample_block_buffer()
static void UpdateSamplePeriod()
static void SetSamplePeriod(intptr_t period)
void store(T arg, std::memory_order order=std::memory_order_relaxed)
virtual ~SampleBlockBuffer()
ProcessedSampleBuffer * BuildProcessedSampleBuffer(Isolate *isolate, SampleFilter *filter, ProcessedSampleBuffer *buffer=nullptr)
static constexpr intptr_t kDefaultBlockCount
void VisitSamples(SampleVisitor *visitor)
Sample * ReserveAllocationSample(Isolate *isolate)
Sample * ReserveCPUSample(Isolate *isolate)
void FreeCompletedBlocks()
bool HasStreamableSamples(const GrowableObjectArray &tag_table, UserTag *tag)
RelaxedAtomic< uint32_t > cursor_
virtual ~SampleBlock()=default
intptr_t capacity() const
friend class SampleBlockListProcessor
std::atomic< State > state_
static constexpr intptr_t kSamplesPerBlock
virtual Sample * ReserveSampleAndLink(Sample *previous)
bool TryAllocateCompleted()
void StreamingToCompleted()
virtual Sample * ReserveSample()
bool TryAcquireStreaming(Isolate *isolate)
void set_owner(Isolate *isolate)
ProcessedSample * BuildProcessedSample(Sample *sample, const CodeLookupTable &clt)
virtual ~SampleBuffer()=default
void VisitSamples(SampleVisitor *visitor)
Sample * Next(Sample *sample)
ProcessedSampleBuffer * BuildProcessedSampleBuffer(SampleFilter *filter, ProcessedSampleBuffer *buffer=nullptr)
intptr_t capacity() const
virtual void Init(Sample *samples, intptr_t capacity)
virtual Sample * ReserveSampleAndLink(Sample *previous)=0
Sample * At(intptr_t idx) const
DISALLOW_COPY_AND_ASSIGN(SampleBuffer)
virtual Sample * ReserveSample()=0
SampleFilter(Dart_Port port, intptr_t thread_task_mask, int64_t time_origin_micros, int64_t time_extent_micros, bool take_samples=false)
static constexpr intptr_t kNoTaskFilter
virtual bool FilterSample(Sample *sample)
bool TimeFilterSample(Sample *sample)
bool take_samples() const
bool TaskFilterSample(Sample *sample)
virtual void VisitSample(Sample *sample)=0
SampleVisitor(Dart_Port port)
void set_thread_task(Thread::TaskKind task)
Thread::TaskKind thread_task() const
static constexpr int kPCArraySizeInWords
Sample * continuation_sample() const
uword At(intptr_t i) const
bool is_continuation_sample() const
void set_allocation_identity_hash(uint32_t hash)
void set_is_allocation_sample(bool allocation_sample)
void set_truncated_trace(bool truncated_trace)
void Init(Dart_Port port, int64_t timestamp, ThreadId tid)
void set_vm_tag(uword tag)
void set_missing_frame_inserted(bool missing_frame_inserted)
bool is_allocation_sample() const
intptr_t allocation_cid() const
void SetContinuation(Sample *next)
void SetAllocationCid(intptr_t cid)
int64_t timestamp() const
bool missing_frame_inserted() const
static constexpr int kStackBufferSizeInWords
void set_head_sample(bool head_sample)
void set_user_tag(uword tag)
bool ignore_sample() const
void set_leaf_frame_is_dart(bool leaf_frame_is_dart)
bool leaf_frame_is_dart() const
bool exit_frame_sample() const
void set_ignore_sample(bool ignore_sample)
void set_exit_frame_sample(bool exit_frame_sample)
void SetAt(intptr_t i, uword pc)
intptr_t metadata() const
uint32_t allocation_identity_hash() const
void set_metadata(intptr_t metadata)
bool truncated_trace() const
static const uint8_t buffer[]
#define DECLARE_PROFILER_COUNTER(name)
#define PROFILER_COUNTERS(V)