13#if !defined(DART_PRECOMPILED_RUNTIME)
37DEFINE_FLAG(
bool, trace_profiled_isolates,
false,
"Trace profiled isolates.");
42 "Time between profiler samples in microseconds. Minimum 50.");
46 "Maximum number stack frames walked. Minimum 1. Maximum 255.");
47#if defined(USING_SIMULATOR)
48DEFINE_FLAG(
bool, profile_vm,
true,
"Always collect native stack traces.");
50DEFINE_FLAG(
bool, profile_vm,
false,
"Always collect native stack traces.");
53 profile_vm_allocation,
55 "Collect native stack traces when tracing Dart allocations.");
59 sample_buffer_duration,
61 "Defines the size of the profiler sample buffer to contain at least "
62 "N seconds of samples at a given sample rate. If not provided, the "
63 "default is ~4 seconds. Large values will greatly increase memory "
69#if !defined(PRODUCT) || defined(DART_PRECOMPILER)
82 uword lookup_pc = frame_index == 0 ? pc : pc - 1;
98#if !defined(DART_PRECOMPILED_RUNTIME)
104 bool symbolize_jit_code =
105 (thread !=
nullptr) &&
108 if (symbolize_jit_code) {
115 pc -
result.PayloadStart());
129 intptr_t skip_count = 0)
164 if (new_sample ==
nullptr) {
190#if defined(HOST_ARCH_IA32) || defined(HOST_ARCH_X64) || \
191 defined(HOST_ARCH_ARM) || defined(HOST_ARCH_ARM64)
197static constexpr intptr_t kHostSavedCallerPcSlotFromFp = 1;
198static constexpr intptr_t kHostSavedCallerFpSlotFromFp = 0;
199#elif defined(HOST_ARCH_RISCV32) || defined(HOST_ARCH_RISCV64)
207static constexpr intptr_t kHostSavedCallerPcSlotFromFp = -1;
208static constexpr intptr_t kHostSavedCallerFpSlotFromFp = -2;
210#error What architecture?
228 intptr_t skip_count = 0)
231 stack_upper_(stack_upper),
235 lower_bound_(stack_lower) {}
238 Append(original_pc_, original_fp_);
240 uword* pc =
reinterpret_cast<uword*
>(original_pc_);
244 if (!ValidFramePointer(
fp)) {
245 counters_->incomplete_sample_fp_bounds.fetch_add(1);
258 if (
fp <= previous_fp) {
260 counters_->incomplete_sample_fp_step.fetch_add(1);
264 if (!ValidFramePointer(
fp)) {
266 counters_->incomplete_sample_fp_bounds.fetch_add(1);
270 const uword pc_value =
reinterpret_cast<uword>(pc);
271 if ((pc_value + 1) < pc_value) {
277 counters_->incomplete_sample_bad_pc.fetch_add(1);
282 lower_bound_ =
reinterpret_cast<uword>(
fp);
293 uword* caller_pc_ptr =
fp + kHostSavedCallerPcSlotFromFp;
297 return reinterpret_cast<uword*
>(*caller_pc_ptr);
302 uword* caller_fp_ptr =
fp + kHostSavedCallerFpSlotFromFp;
306 return reinterpret_cast<uword*
>(*caller_fp_ptr);
309 bool ValidFramePointer(
uword*
fp)
const {
314 cursor +=
sizeof(
fp);
315 bool r = (cursor >= lower_bound_) && (cursor < stack_upper_);
319 ProfilerCounters*
const counters_;
320 const uword stack_upper_;
321 const uword original_pc_;
322 const uword original_fp_;
323 const uword original_sp_;
331 if (stack_lower >= stack_upper) {
336 if ((sp < stack_lower) || (sp >= stack_upper)) {
341 if ((
fp < stack_lower) || (
fp >= stack_upper)) {
357 uword* stack_upper) {
358 ASSERT(os_thread !=
nullptr);
359 ASSERT(stack_lower !=
nullptr);
360 ASSERT(stack_upper !=
nullptr);
362#if defined(USING_SIMULATOR)
363 const bool use_simulator_stack_bounds =
365 if (use_simulator_stack_bounds) {
367 ASSERT(isolate !=
nullptr);
373 const bool use_simulator_stack_bounds =
false;
376 if (!use_simulator_stack_bounds) {
381 if ((*stack_lower == 0) || (*stack_upper == 0)) {
385 if (!use_simulator_stack_bounds && (sp > *stack_lower)) {
397 uword* stack_upper) {
398 ASSERT(stack_lower !=
nullptr);
399 ASSERT(stack_upper !=
nullptr);
405 if ((*stack_lower == 0) || (*stack_upper == 0)) {
409 if (sp > *stack_lower) {
418 if (context ==
nullptr) {
422#if defined(DART_HOST_OS_LINUX) || defined(DART_HOST_OS_MACOS) || \
423 defined(DART_HOST_OS_ANDROID)
424 ucontext_t* ucontext =
reinterpret_cast<ucontext_t*
>(context);
425 mcontext_t mcontext = ucontext->uc_mcontext;
430#elif defined(DART_HOST_OS_WINDOWS)
431 CONTEXT* ctx =
reinterpret_cast<CONTEXT*
>(context);
432#if defined(HOST_ARCH_IA32)
436#elif defined(HOST_ARCH_X64)
440#elif defined(HOST_ARCH_ARM)
444#elif defined(HOST_ARCH_ARM64)
449#error Unsupported architecture.
469#if !defined(DART_PRECOMPILED_RUNTIME)
481 static RelaxedAtomic<uintptr_t> started_dump = 0;
482 if (started_dump.fetch_add(1u) != 0) {
483 OS::PrintErr(
"Aborting reentrant request for stack trace.\n");
489 auto isolate = thread ==
nullptr ? nullptr : thread->isolate();
490 auto isolate_group = thread ==
nullptr ? nullptr : thread->isolate_group();
491 auto source = isolate_group ==
nullptr ? nullptr : isolate_group->source();
494 const char* isolate_group_name =
495 isolate_group ==
nullptr ?
"(nil)" : isolate_group->source()->
name;
496 const char* isolate_name = isolate ==
nullptr ?
"(nil)" : isolate->name();
497#ifdef SUPPORT_TIMELINE
498 const intptr_t thread_id =
501 const intptr_t thread_id = -1;
505 ", isolate_group=%s(%p), isolate=%s(%p)\n",
507 isolate_group_name, isolate_group, isolate_name, isolate);
508#if defined(DART_COMPRESSED_POINTERS)
509 const char kCompressedPointers[] =
"yes";
511 const char kCompressedPointers[] =
"no";
513#if defined(USING_SIMULATOR)
514 const char kUsingSimulator[] =
"yes";
516 const char kUsingSimulator[] =
"no";
518 OS::PrintErr(
"os=%s, arch=%s, comp=%s, sim=%s\n", kHostOperatingSystemName,
519 kTargetArchitectureName, kCompressedPointers, kUsingSimulator);
523 :
reinterpret_cast<uword>(
source->snapshot_instructions),
526 :
reinterpret_cast<uword>(vm_source->snapshot_instructions));
529 uword stack_lower = 0;
530 uword stack_upper = 0;
534 "Stack dump aborted because GetAndValidateThreadStackBounds failed.\n");
542 ProfilerNativeStackWalker native_stack_walker(
543 &counters_,
ILLEGAL_PORT,
nullptr,
nullptr, stack_lower, stack_upper, pc,
545 native_stack_walker.walk();
548 if (thread !=
nullptr) {
550 TransitionNativeToVM transition(thread);
563RelaxedAtomic<bool> Profiler::initialized_ =
false;
564SampleBlockBuffer* Profiler::sample_block_buffer_ =
nullptr;
566bool SampleBlockProcessor::initialized_ =
false;
567bool SampleBlockProcessor::shutdown_ =
false;
568bool SampleBlockProcessor::thread_running_ =
false;
569ThreadJoinId SampleBlockProcessor::processor_thread_id_ =
571Monitor* SampleBlockProcessor::monitor_ =
nullptr;
576 if (!FLAG_profiler) {
583 if (sample_block_buffer_ ==
nullptr) {
584 intptr_t num_blocks = CalculateSampleBufferCapacity();
606 if (!FLAG_profiler) {
614 initialized_ =
false;
618 if (!FLAG_profiler && initialized_) {
620 }
else if (FLAG_profiler && !initialized_) {
626 const int kMinimumDepth = 2;
627 const int kMaximumDepth = 255;
628 if (depth < kMinimumDepth) {
629 FLAG_max_profile_depth = kMinimumDepth;
630 }
else if (depth > kMaximumDepth) {
631 FLAG_max_profile_depth = kMaximumDepth;
633 FLAG_max_profile_depth = depth;
638 const intptr_t kMicrosPerSec = 1000000;
639 return kMicrosPerSec / FLAG_profile_period;
642intptr_t Profiler::CalculateSampleBufferCapacity() {
643 if (FLAG_sample_buffer_duration <= 0) {
649 const intptr_t max_sample_chain_length =
651 const intptr_t sample_count = FLAG_sample_buffer_duration *
657 const int kMinimumProfilePeriod = 50;
658 if (period < kMinimumProfilePeriod) {
659 FLAG_profile_period = kMinimumProfilePeriod;
661 FLAG_profile_period = period;
671 intptr_t samples_per_block) {
674 const bool executable =
false;
675 const bool compressed =
false;
678 if (memory_ ==
nullptr) {
681 sample_buffer_ =
reinterpret_cast<Sample*
>(memory_->
address());
683 for (intptr_t
i = 0;
i < blocks; ++
i) {
684 blocks_[
i].
Init(&sample_buffer_[
i * samples_per_block], samples_per_block);
699SampleBlock* SampleBlockBuffer::ReserveSampleBlock() {
700 intptr_t capacity = capacity_;
708 i = (
i + 1) % capacity;
709 }
while (
i != start);
714 SampleBlock* block = &blocks_[
i];
715 if (block->TryAllocateCompleted()) {
718 i = (
i + 1) % capacity;
719 }
while (
i != start);
725 for (intptr_t
i = 0;
i < capacity_;
i++) {
735 for (intptr_t j = 0; j < tag_table.
Length(); ++j) {
736 *tag ^= tag_table.
At(j);
746 ASSERT(isolate !=
nullptr);
749 if (block !=
nullptr) {
755 if (block !=
nullptr) {
765 ASSERT(isolate !=
nullptr);
776 for (intptr_t
i = 0;
i < capacity_; ++
i) {
800 ASSERT(previous !=
nullptr);
803 ASSERT(isolate !=
nullptr);
805 ?
buffer->ReserveAllocationSample(isolate)
806 :
buffer->ReserveCPUSample(isolate);
807 if (
next ==
nullptr) {
811 next->set_head_sample(
false);
818 return ReserveSampleImpl(isolate,
false);
822 return ReserveSampleImpl(isolate,
true);
825Sample* SampleBlockBuffer::ReserveSampleImpl(
Isolate* isolate,
826 bool allocation_sample) {
831 if (block !=
nullptr) {
834 if (sample !=
nullptr) {
838 SampleBlock*
next = ReserveSampleBlock();
839 if (
next ==
nullptr) {
844 next->set_owner(isolate);
845 if (allocation_sample) {
850 if (block !=
nullptr) {
861 return next->ReserveSample();
870 : stack_buffer_(sample->GetStackBuffer()),
872 code_(
Code::ZoneHandle(
code.ptr())) {
878 : stack_buffer_(stack_buffer),
880 code_(
Code::ZoneHandle(
code.ptr())) {
899 uint8_t* code_pointer =
reinterpret_cast<uint8_t*
>(code_.
PayloadStart());
907 return stack_buffer_[
i];
911 uword* stack_buffer_;
916#if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64)
918 ASSERT(return_address !=
nullptr);
924 if (
offset < prologue_offset) {
935 ProloguePattern pp(
pc());
946 SetFramePointerPattern sfpp(
pc());
947 if (sfpp.IsValid()) {
956 ReturnPattern rp(
pc());
965#elif defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_ARM64) || \
966 defined(TARGET_ARCH_RISCV32) || defined(TARGET_ARCH_RISCV64)
968 ASSERT(return_address !=
nullptr);
972#error ReturnAddressLocator implementation missing for this architecture.
976 if ((time_origin_micros_ == -1) || (time_extent_micros_ == -1)) {
980 const int64_t timestamp = sample->
timestamp();
981 int64_t
delta = timestamp - time_origin_micros_;
982 return (
delta >= 0) && (
delta <= time_extent_micros_);
986 const intptr_t task =
static_cast<intptr_t
>(sample->
thread_task());
990 return (task & thread_task_mask_) != 0;
1010 bool allocation_sample,
1011 intptr_t skip_count = 0)
1013 ? thread->isolate()->main_port()
1019 pc_(reinterpret_cast<
uword*>(pc)),
1020 fp_(reinterpret_cast<
uword*>(
fp)),
1021 sp_(reinterpret_cast<
uword*>(sp)),
1022 lr_(reinterpret_cast<
uword*>(lr)) {}
1032 bool has_exit_frame = exit_fp !=
nullptr;
1033 if (has_exit_frame) {
1042 if (thread_->
vm_tag() == VMTag::kDartTagId) {
1051 const bool is_entry_frame =
1052#if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64)
1058 if (is_entry_frame) {
1077 if (fp_ ==
nullptr) {
1100 uword* CallerPC()
const {
1106 return reinterpret_cast<uword*
>(*caller_pc_ptr);
1109 uword* CallerFP()
const {
1115 return reinterpret_cast<uword*
>(*caller_fp_ptr);
1118 uword* ExitLink()
const {
1124 return reinterpret_cast<uword*
>(*exit_link_ptr);
1127 uword Stack(intptr_t index)
const {
1129 uword* stack_ptr = sp_ + index;
1136 Thread*
const thread_;
1144 ASSERT(sample !=
nullptr);
1145 uword* sp =
reinterpret_cast<uword*
>(sp_addr);
1147 if (sp !=
nullptr) {
1157#if defined(DART_HOST_OS_WINDOWS)
1160static uword fault_address = 0;
1161static LONG GuardPageExceptionFilter(EXCEPTION_POINTERS* ep) {
1163 if (ep->ExceptionRecord->ExceptionCode != STATUS_GUARD_PAGE_VIOLATION) {
1164 return EXCEPTION_CONTINUE_SEARCH;
1167 fault_address = ep->ExceptionRecord->ExceptionInformation[1];
1169 ASSERT(ep->ExceptionRecord->ExceptionInformation[0] == 0);
1170 return EXCEPTION_EXECUTE_HANDLER;
1176 bool exited_dart_code,
1185 ASSERT(counters !=
nullptr);
1186#if defined(DART_HOST_OS_WINDOWS)
1197 if (FLAG_profile_vm) {
1199 counters->stack_walker_native.fetch_add(1);
1200 native_stack_walker->
walk();
1202 counters->stack_walker_dart_exit.fetch_add(1);
1204 dart_stack_walker->
walk();
1206 counters->stack_walker_dart.fetch_add(1);
1208 dart_stack_walker->
walk();
1210 counters->stack_walker_none.fetch_add(1);
1211 sample->
SetAt(0, pc);
1214#if defined(DART_HOST_OS_WINDOWS)
1216 } __except (GuardPageExceptionFilter(GetExceptionInformation())) {
1223 DWORD new_protect = PAGE_READWRITE | PAGE_GUARD;
1224 DWORD old_protect = 0;
1226 VirtualProtect(
reinterpret_cast<void*
>(fault_address),
1227 sizeof(fault_address), new_protect, &old_protect);
1230 ASSERT(old_protect == PAGE_READWRITE);
1236 bool allocation_sample,
1238 ASSERT(thread !=
nullptr);
1241 Sample* sample = allocation_sample ?
buffer->ReserveAllocationSample(isolate)
1242 :
buffer->ReserveCPUSample(isolate);
1243 if (sample ==
nullptr) {
1248#if defined(USING_SIMULATOR)
1253 if (redirect_vm_tag != 0) {
1254 vm_tag = redirect_vm_tag;
1273 uint32_t identity_hash) {
1274 ASSERT(thread !=
nullptr);
1276 ASSERT(os_thread !=
nullptr);
1296 uword stack_lower = 0;
1297 uword stack_upper = 0;
1307 if (sample ==
nullptr) {
1309 counters_.sample_allocation_failure++;
1315 if (FLAG_profile_vm_allocation) {
1319 stack_upper, pc,
fp, sp);
1320 native_stack_walker.
walk();
1321 }
else if (exited_dart_code) {
1325 dart_exit_stack_walker.
walk();
1329 sample->
SetAt(0, pc);
1333void Profiler::SampleThreadSingleFrame(
Thread* thread,
1336 ASSERT(thread !=
nullptr);
1338 ASSERT(os_thread !=
nullptr);
1351 sample->
SetAt(0, pc);
1356 ASSERT(thread !=
nullptr);
1358 ASSERT(os_thread !=
nullptr);
1363 counters_.bail_out_unknown_task.fetch_add(1);
1371 counters_.bail_out_jump_to_exception_handler.fetch_add(1);
1379 uintptr_t pc =
state.pc;
1380 uintptr_t lr =
state.lr;
1381#if defined(USING_SIMULATOR)
1387#if defined(USING_SIMULATOR)
1391 pc = simulator->
get_pc();
1392 lr = simulator->
get_lr();
1402 counters_.bail_out_check_isolate.fetch_add(1);
1414 SetupSample(thread,
false, os_thread->trace_id());
1415 if (sample ==
nullptr) {
1417 counters_.sample_allocation_failure++;
1423 counters_.single_frame_sample_deoptimizing.fetch_add(1);
1424 SampleThreadSingleFrame(thread, sample, pc);
1429 uword stack_lower = 0;
1430 uword stack_upper = 0;
1433 counters_.single_frame_sample_get_and_validate_stack_bounds.fetch_add(1);
1435 SampleThreadSingleFrame(thread, sample, pc);
1459 CollectSample(isolate, exited_dart_code, in_dart_code, sample,
1460 &native_stack_walker, &dart_stack_walker, pc,
fp, sp,
1471 return code_.
Size();
1485 ASSERT(table_ !=
nullptr);
1500void CodeLookupTable::Build(Thread* thread) {
1501 ASSERT(thread !=
nullptr);
1503 ASSERT(vm_isolate !=
nullptr);
1506 code_objects_.Clear();
1508 thread->CheckForSafepoint();
1511 TimelineBeginEndScope tl(Timeline::GetIsolateStream(),
1512 "CodeLookupTable::Build HeapIterationScope");
1513 HeapIterationScope iteration(thread);
1515 iteration.IterateVMIsolateObjects(&cltb);
1516 iteration.IterateOldObjects(&cltb);
1518 thread->CheckForSafepoint();
1531 for (intptr_t
i = 0;
i <
length() - 1;
i++) {
1532 const CodeDescriptor*
a =
At(
i);
1533 const CodeDescriptor*
b =
At(
i + 1);
1543void CodeLookupTable::Add(
const Object&
code) {
1546 CodeDescriptor* cd =
new CodeDescriptor(AbstractCode(
code.ptr()));
1547 code_objects_.Add(cd);
1554 intptr_t current = first;
1558 if (pc >= cd->
Start()) {
1606 if (sample->
At(0) == 0) {
1610 if (filter !=
nullptr) {
1613 if (sample->
port() != filter->
port()) {
1656 bool truncated =
false;
1657 Sample* current = sample;
1658 while (current !=
nullptr) {
1660 if (current->
At(
i) == 0) {
1663 processed_sample->
Add(current->
At(
i));
1667 current =
Next(current);
1671 processed_sample->FixupCaller(clt, 0,
1676 return processed_sample;
1683 ASSERT(sample != next_sample);
1685 if (sample->
port() != next_sample->
port()) {
1691 if (sample->
tid() != next_sample->
tid()) {
1698 : pcs_(
Sample::kPCArraySizeInWords),
1702 allocation_cid_(-1),
1703 allocation_identity_hash_(0),
1704 truncated_(
false) {}
1708 uword* stack_buffer) {
1710 if (cd ==
nullptr) {
1718 CheckForMissingDartFrame(clt, cd, pc_marker, stack_buffer);
1721void ProcessedSample::CheckForMissingDartFrame(
const CodeLookupTable& clt,
1722 const CodeDescriptor* cd,
1724 uword* stack_buffer) {
1746 uword return_address = pc_marker;
1749 ReturnAddressLocator ral(
At(0), stack_buffer,
code);
1751 if (!ral.LocateReturnAddress(&return_address)) {
1752 ASSERT(return_address == pc_marker);
1753 if (
code.GetPrologueOffset() == 0) {
1759 if (
code.ContainsInstructionAt(return_address)) {
1765 if (clt.FindCode(return_address) ==
nullptr) {
1770 if (return_address != 0) {
1777 ASSERT(code_lookup_table_ !=
nullptr);
1782 if (monitor_ ==
nullptr) {
1785 ASSERT(monitor_ !=
nullptr);
1786 initialized_ =
true;
1795 while (!thread_running_) {
1818 initialized_ =
false;
1819 ASSERT(!thread_running_);
1850 event.set_cpu_profile(&
profile);
1859void SampleBlockProcessor::ThreadMain(
uword parameters) {
1865 ASSERT(os_thread !=
nullptr);
1867 thread_running_ =
true;
1868 startup_ml.Notify();
1871 MonitorLocker wait_ml(monitor_);
1873 const int64_t wakeup_interval = 1000 * 100;
1875 wait_ml.WaitMicros(wakeup_interval);
1883 const bool kBypassSafepoint =
false;
1886 group->ForEachIsolate([&](Isolate* isolate) {
1887 if (isolate->TakeHasCompletedBlocks()) {
1888 Profiler::ProcessCompletedBlocks(isolate);
1895 thread_running_ =
false;
static int step(int x, SkScalar min, SkScalar max)
static float next(float f)
#define ASAN_UNPOISON(ptr, len)
#define RELEASE_ASSERT(cond)
uword PayloadStart() const
int64_t compile_timestamp() const
ClearProfileVisitor(Isolate *isolate)
virtual void VisitSample(Sample *sample)
int64_t CompileTimestamp() const
CodeDescriptor(const AbstractCode code)
bool Contains(uword pc) const
static int Compare(CodeDescriptor *const *a, CodeDescriptor *const *b)
CodeLookupTableBuilder(CodeLookupTable *table)
void VisitObject(ObjectPtr raw_obj) override
~CodeLookupTableBuilder()
CodeLookupTable(Thread *thread)
const CodeDescriptor * At(intptr_t index) const
friend class CodeLookupTableBuilder
const CodeDescriptor * FindCode(uword pc) const
intptr_t GetPrologueOffset() const
static CodePtr FindCodeUnsafe(uword pc)
bool ContainsInstructionAt(uword addr) const
bool IsUnknownDartCode() const
uword PayloadStart() const
static IsolateGroup * vm_isolate_group()
static Isolate * vm_isolate()
ObjectPtr At(intptr_t index) const
static void ForEach(std::function< void(IsolateGroup *)> action)
IsolateGroupSource * source() const
bool TrySetHasCompletedBlocks()
Simulator * simulator() const
static bool IsSystemIsolate(const Isolate *isolate)
VMTagCounters * vm_tag_counters()
static void VisitIsolates(IsolateVisitor *visitor)
void set_current_sample_block(SampleBlock *block)
SampleBlock * current_sample_block() const
bool IsDeoptimizing() const
void set_current_allocation_sample_block(SampleBlock *block)
Thread * mutator_thread() const
SampleBlock * current_allocation_sample_block() const
Dart_Port main_port() const
Monitor::WaitResult Wait(int64_t millis=Monitor::kNoTimeout)
static bool LookupSharedObject(uword pc, uword *dso_base=nullptr, const char **dso_name=nullptr)
static const char * LookupSymbolName(uword pc, uword *start)
static void FreeSymbolName(const char *name)
static int Start(const char *name, ThreadStartFunction function, uword parameter)
static bool GetCurrentStackBounds(uword *lower, uword *upper)
static uword GetCurrentStackPointer()
static void Join(ThreadJoinId id)
static OSThread * Current()
uword stack_limit() const
static ThreadJoinId GetCurrentThreadJoinId(OSThread *thread)
static intptr_t ThreadIdToIntPtr(ThreadId id)
static const ThreadJoinId kInvalidThreadJoinId
static int64_t GetCurrentMonotonicMicros()
static void static void PrintErr(const char *format,...) PRINTF_ATTRIBUTE(1
static uintptr_t GetProgramCounter()
static intptr_t ProcessId()
static ObjectPtr RawCast(ObjectPtr obj)
void set_tid(ThreadId tid)
void set_allocation_cid(intptr_t cid)
uword At(intptr_t index) const
void set_truncated(bool truncated)
void set_first_frame_executing(bool first_frame_executing)
void set_timestamp(int64_t timestamp)
int64_t timestamp() 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)
ProfilerDartStackWalker(Thread *thread, Sample *sample, SampleBuffer *sample_buffer, uword pc, uword fp, uword sp, uword lr, bool allocation_sample, intptr_t skip_count=0)
ProfilerNativeStackWalker(ProfilerCounters *counters, Dart_Port port_id, Sample *sample, SampleBuffer *sample_buffer, uword stack_lower, uword stack_upper, uword pc, uword fp, uword sp, intptr_t skip_count=0)
bool Append(uword pc, uword fp)
ProfilerStackWalker(Dart_Port port_id, Sample *head_sample, SampleBuffer *sample_buffer, intptr_t skip_count=0)
SampleBuffer * sample_buffer_
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 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)
T fetch_add(T arg, std::memory_order order=std::memory_order_relaxed)
ReturnAddressLocator(Sample *sample, const Code &code)
uword StackAt(intptr_t i)
ReturnAddressLocator(uword pc, uword *stack_buffer, const Code &code)
uint8_t * CodePointer(intptr_t offset)
bool LocateReturnAddress(uword *return_address)
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
Sample * ReserveAllocationSample(Isolate *isolate)
Sample * ReserveCPUSample(Isolate *isolate)
void FreeCompletedBlocks()
void VisitIsolate(Isolate *isolate)
virtual ~SampleBlockCleanupVisitor()=default
SampleBlockCleanupVisitor()=default
bool HasStreamableSamples(const GrowableObjectArray &tag_table, UserTag *tag)
RelaxedAtomic< uint32_t > cursor_
static constexpr intptr_t kSamplesPerBlock
virtual Sample * ReserveSampleAndLink(Sample *previous)
void StreamingToCompleted()
virtual Sample * ReserveSample()
bool TryAcquireStreaming(Isolate *isolate)
ProcessedSample * BuildProcessedSample(Sample *sample, const CodeLookupTable &clt)
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
static constexpr intptr_t kNoTaskFilter
virtual bool FilterSample(Sample *sample)
bool TimeFilterSample(Sample *sample)
bool take_samples() const
bool TaskFilterSample(Sample *sample)
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_truncated_trace(bool truncated_trace)
void Init(Dart_Port port, int64_t timestamp, ThreadId tid)
void set_vm_tag(uword tag)
bool is_allocation_sample() const
intptr_t allocation_cid() const
void SetContinuation(Sample *next)
void SetAllocationCid(intptr_t cid)
int64_t timestamp() const
static constexpr int kStackBufferSizeInWords
void set_user_tag(uword tag)
bool ignore_sample() 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)
uint32_t allocation_identity_hash() const
bool truncated_trace() const
static void HandleEvent(ServiceEvent *event, bool enter_safepoint=true)
static StreamInfo profiler_stream
static uintptr_t GetCStackPointer(const mcontext_t &mcontext)
static uintptr_t GetFramePointer(const mcontext_t &mcontext)
static uintptr_t GetProgramCounter(const mcontext_t &mcontext)
DART_FORCE_INLINE int32_t get_pc() const
uword stack_limit() const
DART_FORCE_INLINE int32_t get_register(Register reg) const
static uword FunctionForRedirect(uword redirect)
static void DumpCurrentTrace()
StreamableSampleFilter(Dart_Port port, const Isolate *isolate)
bool FilterSample(Sample *sample) override
static bool HasBeenInitialized()
static bool InInvocationStub(uword pc)
static bool InJumpToFrameStub(uword pc)
static void SetInterruptPeriod(intptr_t period)
OSThread * os_thread() const
bool HasCompilerState() const
void ScheduleInterrupts(uword interrupt_bits)
static Thread * Current()
CompilerState & compiler_state()
bool HasExitedDartCode() const
bool IsExecutingDartCode() const
static void ExitIsolateGroupAsHelper(bool bypass_safepoint)
uword top_exit_frame_info() const
bool IsDartMutatorThread() const
ExecutionState execution_state() const
Isolate * isolate() const
TaskKind task_kind() const
static bool EnterIsolateGroupAsHelper(IsolateGroup *isolate_group, TaskKind kind, bool bypass_safepoint)
static UserTagPtr FindTagById(const Isolate *isolate, uword tag_id)
static constexpr T RoundUp(T x, uintptr_t alignment, uintptr_t offset=0)
static const char * String()
static intptr_t PageSize()
static VirtualMemory * Allocate(intptr_t size, bool is_executable, bool is_compressed, const char *name)
#define MSAN_UNPOISON(ptr, len)
static constexpr int kExitLinkSlotFromEntryFp
static Sample * SetupSample(Thread *thread, bool allocation_sample, ThreadId tid)
static void DumpCompilerState(Thread *thread)
static bool CheckIsolate(Isolate *isolate)
static constexpr int kSavedCallerPcSlotFromFp
static intptr_t SamplesPerSecond()
static void CollectSample(Isolate *isolate, bool exited_dart_code, bool in_dart_code, Sample *sample, ProfilerNativeStackWalker *native_stack_walker, ProfilerDartStackWalker *dart_stack_walker, uword pc, uword fp, uword sp, ProfilerCounters *counters)
static void CopyStackBuffer(Sample *sample, uword sp_addr)
static constexpr int kSavedCallerFpSlotFromFp
static void FlushSampleBlocks(Isolate *isolate)
static bool ValidateThreadStackBounds(uintptr_t fp, uintptr_t sp, uword stack_lower, uword stack_upper)
static bool GetAndValidateCurrentThreadStackBounds(uintptr_t fp, uintptr_t sp, uword *stack_lower, uword *stack_upper)
static constexpr intptr_t kMaxSamplesPerTick
DEFINE_FLAG(bool, print_cluster_information, false, "Print information about clusters written to snapshot")
static void DumpStackFrame(uword pc, uword fp, const char *name, uword offset)
static bool GetAndValidateThreadStackBounds(OSThread *os_thread, Thread *thread, uintptr_t fp, uintptr_t sp, uword *stack_lower, uword *stack_upper)
constexpr intptr_t kWordSize
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 TIMELINE_DURATION(thread, stream, name)
#define COPY_FP_REGISTER(fp)