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 const char* native_symbol_name =
256 if (native_symbol_name ==
nullptr) {
315 return allocation_identity_hash_;
319 allocation_identity_hash_ =
hash;
378 uint32_t allocation_identity_hash_;
380 using HeadSampleBit =
BitField<
decltype(state_),
bool, 0, 1>;
381 using LeafFrameIsDart =
386 using MissingFrameInsertedBit =
388 using TruncatedTraceBit =
390 using ClassAllocationSampleBit =
392 using ContinuationSampleBit =
394 using ThreadTaskBit =
BitField<
decltype(state_),
398 using MetadataBits =
BitField<
decltype(state_),
403 DISALLOW_COPY_AND_ASSIGN(
Sample);
417 return Code::Cast(code_).PayloadStart();
422 return Code::Cast(code_).Size();
426 if (code_.IsCode()) {
427 return Code::Cast(code_).compile_timestamp();
434 if (code_.IsCode()) {
435 return Code::Cast(code_).Name();
442 if (code_.IsCode()) {
443 return Code::Cast(code_).QualifiedName(
451 if (code_.IsCode()) {
452 return Code::Cast(code_).IsStubCode();
459 if (code_.IsCode()) {
460 return Code::Cast(code_).IsAllocationStubCode();
467 if (code_.IsCode()) {
468 return Code::Cast(code_).IsTypeTestStubCode();
475 if (code_.IsCode()) {
476 return Code::Cast(code_).owner();
483 bool IsCode()
const {
return code_.IsCode(); }
486 if (code_.IsCode()) {
487 return Code::Cast(code_).is_optimized();
514 return (pc >=
Start()) && (pc <
end);
521 uword a_start = (*a)->Start();
522 uword b_start = (*b)->Start();
524 if (a_start < b_start) {
526 }
else if (a_start > b_start) {
544 intptr_t
length()
const {
return code_objects_.length(); }
547 return code_objects_.At(index);
553 void Build(
Thread* thread);
571 ASSERT(samples !=
nullptr);
578 ASSERT(visitor !=
nullptr);
590 if (sample->
port() != visitor->
port()) {
598 if (sample->
At(0) == 0) {
654 std::memory_order success_order = std::memory_order_acquire;
655 std::memory_order failure_order = std::memory_order_relaxed;
656 return state_.compare_exchange_strong(expected, desired, success_order,
662 std::memory_order success_order = std::memory_order_acquire;
663 std::memory_order failure_order = std::memory_order_relaxed;
664 if (
state_.compare_exchange_strong(expected, desired, success_order,
678 if (
owner_ != isolate)
return false;
682 std::memory_order success_order = std::memory_order_acquire;
683 std::memory_order failure_order = std::memory_order_relaxed;
684 return state_.compare_exchange_strong(expected, desired, success_order,
700 std::memory_order success_order = std::memory_order_acquire;
701 std::memory_order failure_order = std::memory_order_relaxed;
702 if (
state_.compare_exchange_strong(expected, desired, success_order,
743 ASSERT(visitor !=
nullptr);
744 for (intptr_t
i = 0;
i < capacity_; ++
i) {
769 Sample* ReserveSampleImpl(
Isolate* isolate,
bool allocation_sample);
789 if (sample_block_buffer_ !=
nullptr) {
790 size += sample_block_buffer_->
Size();
840 return allocation_identity_hash_;
843 allocation_identity_hash_ =
hash;
861 uword* stack_buffer);
866 uword* stack_buffer);
873 intptr_t allocation_cid_;
874 uint32_t allocation_identity_hash_;
876 bool first_frame_executing_;
889 intptr_t
length()
const {
return samples_.length(); }
894 return *code_lookup_table_;
912 static constexpr intptr_t kMaxThreads = 4096;
913 static bool initialized_;
914 static bool shutdown_;
915 static bool thread_running_;
919 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 intptr_t kNextBit
static constexpr T decode(S value)
static constexpr S update(T value, S original)
ClearProfileVisitor(Isolate *isolate)
virtual void VisitSample(Sample *sample)
int64_t CompileTimestamp() const
CodeDescriptor(const AbstractCode code)
bool Contains(uword pc) const
const AbstractCode code() const
static int Compare(CodeDescriptor *const *a, CodeDescriptor *const *b)
const char * Name() const
CodeLookupTable(Thread *thread)
const CodeDescriptor * At(intptr_t index) const
const CodeDescriptor * FindCode(uword pc) const
static const char * LookupSymbolName(uword pc, uword *start)
static void FreeSymbolName(const char *name)
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)
virtual ~SampleBlockBuffer()
SampleBlockBuffer(intptr_t blocks=kDefaultBlockCount, intptr_t samples_per_block=SampleBlock::kSamplesPerBlock)
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
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace buffer
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
#define DECLARE_PROFILER_COUNTER(name)
#define PROFILER_COUNTERS(V)