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) {}
240 Append(original_pc_, original_fp_);
242 uword* pc =
reinterpret_cast<uword*
>(original_pc_);
246 uword gap = original_fp_ - original_sp_;
247 if (gap >= kMaxStep) {
250 counters_->incomplete_sample_fp_step.fetch_add(1);
254 if (!ValidFramePointer(
fp)) {
255 counters_->incomplete_sample_fp_bounds.fetch_add(1);
268 if (
fp <= previous_fp) {
270 counters_->incomplete_sample_fp_step.fetch_add(1);
274 gap =
fp - previous_fp;
275 if (gap >= kMaxStep) {
277 counters_->incomplete_sample_fp_step.fetch_add(1);
281 if (!ValidFramePointer(
fp)) {
283 counters_->incomplete_sample_fp_bounds.fetch_add(1);
287 const uword pc_value =
reinterpret_cast<uword>(pc);
288 if ((pc_value + 1) < pc_value) {
294 counters_->incomplete_sample_bad_pc.fetch_add(1);
299 lower_bound_ =
reinterpret_cast<uword>(
fp);
310 uword* caller_pc_ptr =
fp + kHostSavedCallerPcSlotFromFp;
314 return reinterpret_cast<uword*
>(*caller_pc_ptr);
319 uword* caller_fp_ptr =
fp + kHostSavedCallerFpSlotFromFp;
323 return reinterpret_cast<uword*
>(*caller_fp_ptr);
326 bool ValidFramePointer(
uword*
fp)
const {
331 cursor +=
sizeof(
fp);
332 bool r = (cursor >= lower_bound_) && (cursor < stack_upper_);
336 ProfilerCounters*
const counters_;
337 const uword stack_upper_;
338 const uword original_pc_;
339 const uword original_fp_;
340 const uword original_sp_;
348 if (stack_lower >= stack_upper) {
353 if ((sp < stack_lower) || (sp >= stack_upper)) {
358 if ((
fp < stack_lower) || (
fp >= stack_upper)) {
373 uword* stack_upper) {
374 ASSERT(os_thread !=
nullptr);
375 ASSERT(stack_lower !=
nullptr);
376 ASSERT(stack_upper !=
nullptr);
378#if defined(USING_SIMULATOR)
379 const bool use_simulator_stack_bounds =
381 if (use_simulator_stack_bounds) {
383 ASSERT(isolate !=
nullptr);
389 const bool use_simulator_stack_bounds =
false;
392 if (!use_simulator_stack_bounds) {
397 if ((*stack_lower == 0) || (*stack_upper == 0)) {
401 if (!use_simulator_stack_bounds && (sp > *stack_lower)) {
410 if (context ==
nullptr) {
414#if defined(DART_HOST_OS_LINUX) || defined(DART_HOST_OS_MACOS) || \
415 defined(DART_HOST_OS_ANDROID)
416 ucontext_t* ucontext =
reinterpret_cast<ucontext_t*
>(context);
417 mcontext_t mcontext = ucontext->uc_mcontext;
422#elif defined(DART_HOST_OS_WINDOWS)
423 CONTEXT* ctx =
reinterpret_cast<CONTEXT*
>(context);
424#if defined(HOST_ARCH_IA32)
428#elif defined(HOST_ARCH_X64)
432#elif defined(HOST_ARCH_ARM)
436#elif defined(HOST_ARCH_ARM64)
441#error Unsupported architecture.
461#if !defined(DART_PRECOMPILED_RUNTIME)
473 static RelaxedAtomic<uintptr_t> started_dump = 0;
474 if (started_dump.fetch_add(1u) != 0) {
475 OS::PrintErr(
"Aborting reentrant request for stack trace.\n");
481 ASSERT(os_thread !=
nullptr);
483 auto isolate = thread ==
nullptr ? nullptr : thread->isolate();
484 auto isolate_group = thread ==
nullptr ? nullptr : thread->isolate_group();
485 auto source = isolate_group ==
nullptr ? nullptr : isolate_group->source();
488 const char* isolate_group_name =
489 isolate_group ==
nullptr ?
"(nil)" : isolate_group->source()->
name;
490 const char* isolate_name = isolate ==
nullptr ?
"(nil)" : isolate->name();
492 const intptr_t thread_id = -1;
499 ", isolate_group=%s(%p), isolate=%s(%p)\n",
501 isolate_group_name, isolate_group, isolate_name, isolate);
502#if defined(DART_COMPRESSED_POINTERS)
503 const char kCompressedPointers[] =
"yes";
505 const char kCompressedPointers[] =
"no";
507#if defined(USING_SIMULATOR)
508 const char kUsingSimulator[] =
"yes";
510 const char kUsingSimulator[] =
"no";
512 OS::PrintErr(
"os=%s, arch=%s, comp=%s, sim=%s\n", kHostOperatingSystemName,
513 kTargetArchitectureName, kCompressedPointers, kUsingSimulator);
517 : reinterpret_cast<
uword>(
source->snapshot_instructions),
520 : reinterpret_cast<
uword>(vm_source->snapshot_instructions));
523 uword stack_lower = 0;
524 uword stack_upper = 0;
528 "Stack dump aborted because GetAndValidateThreadStackBounds failed.\n");
536 ProfilerNativeStackWalker native_stack_walker(
537 &counters_,
ILLEGAL_PORT,
nullptr,
nullptr, stack_lower, stack_upper, pc,
539 native_stack_walker.walk();
542 if (thread !=
nullptr) {
544 TransitionNativeToVM transition(thread);
557RelaxedAtomic<bool> Profiler::initialized_ =
false;
558SampleBlockBuffer* Profiler::sample_block_buffer_ =
nullptr;
560bool SampleBlockProcessor::initialized_ =
false;
561bool SampleBlockProcessor::shutdown_ =
false;
562bool SampleBlockProcessor::thread_running_ =
false;
563ThreadJoinId SampleBlockProcessor::processor_thread_id_ =
565Monitor* SampleBlockProcessor::monitor_ =
nullptr;
570 if (!FLAG_profiler) {
577 if (sample_block_buffer_ ==
nullptr) {
578 intptr_t num_blocks = CalculateSampleBufferCapacity();
600 if (!FLAG_profiler) {
608 initialized_ =
false;
612 if (!FLAG_profiler && initialized_) {
614 }
else if (FLAG_profiler && !initialized_) {
620 const int kMinimumDepth = 2;
621 const int kMaximumDepth = 255;
622 if (depth < kMinimumDepth) {
623 FLAG_max_profile_depth = kMinimumDepth;
624 }
else if (depth > kMaximumDepth) {
625 FLAG_max_profile_depth = kMaximumDepth;
627 FLAG_max_profile_depth = depth;
632 const intptr_t kMicrosPerSec = 1000000;
633 return kMicrosPerSec / FLAG_profile_period;
636intptr_t Profiler::CalculateSampleBufferCapacity() {
637 if (FLAG_sample_buffer_duration <= 0) {
643 const intptr_t max_sample_chain_length =
645 const intptr_t sample_count = FLAG_sample_buffer_duration *
651 const int kMinimumProfilePeriod = 50;
652 if (period < kMinimumProfilePeriod) {
653 FLAG_profile_period = kMinimumProfilePeriod;
655 FLAG_profile_period = period;
665 intptr_t samples_per_block) {
668 const bool executable =
false;
669 const bool compressed =
false;
672 if (memory_ ==
nullptr) {
675 sample_buffer_ =
reinterpret_cast<Sample*
>(memory_->
address());
677 for (intptr_t i = 0; i < blocks; ++i) {
678 blocks_[i].
Init(&sample_buffer_[i * samples_per_block], samples_per_block);
693SampleBlock* SampleBlockBuffer::ReserveSampleBlock() {
694 intptr_t capacity = capacity_;
702 i = (i + 1) % capacity;
703 }
while (i !=
start);
708 SampleBlock* block = &blocks_[i];
709 if (block->TryAllocateCompleted()) {
712 i = (i + 1) % capacity;
713 }
while (i !=
start);
719 for (intptr_t i = 0; i < capacity_; i++) {
726 for (intptr_t i = 0; i <
capacity_; ++i) {
729 for (intptr_t j = 0; j < tag_table.
Length(); ++j) {
730 *tag ^= tag_table.
At(j);
740 ASSERT(isolate !=
nullptr);
743 if (block !=
nullptr) {
749 if (block !=
nullptr) {
759 ASSERT(isolate !=
nullptr);
770 for (intptr_t i = 0; i < capacity_; ++i) {
794 ASSERT(previous !=
nullptr);
797 ASSERT(isolate !=
nullptr);
799 ?
buffer->ReserveAllocationSample(isolate)
800 :
buffer->ReserveCPUSample(isolate);
801 if (
next ==
nullptr) {
805 next->set_head_sample(
false);
812 return ReserveSampleImpl(isolate,
false);
816 return ReserveSampleImpl(isolate,
true);
819Sample* SampleBlockBuffer::ReserveSampleImpl(
Isolate* isolate,
820 bool allocation_sample) {
825 if (block !=
nullptr) {
828 if (sample !=
nullptr) {
832 SampleBlock*
next = ReserveSampleBlock();
833 if (
next ==
nullptr) {
838 next->set_owner(isolate);
839 if (allocation_sample) {
844 if (block !=
nullptr) {
855 return next->ReserveSample();
864 : stack_buffer_(sample->GetStackBuffer()),
866 code_(
Code::ZoneHandle(code.ptr())) {
872 : stack_buffer_(stack_buffer),
874 code_(
Code::ZoneHandle(code.ptr())) {
891 const intptr_t size = code_.
Size();
893 uint8_t* code_pointer =
reinterpret_cast<uint8_t*
>(code_.
PayloadStart());
901 return stack_buffer_[i];
905 uword* stack_buffer_;
910#if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64)
912 ASSERT(return_address !=
nullptr);
915 const intptr_t size = code_.
Size();
918 if (
offset < prologue_offset) {
929 ProloguePattern pp(
pc());
940 SetFramePointerPattern sfpp(
pc());
941 if (sfpp.IsValid()) {
950 ReturnPattern rp(
pc());
959#elif defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_ARM64) || \
960 defined(TARGET_ARCH_RISCV32) || defined(TARGET_ARCH_RISCV64)
962 ASSERT(return_address !=
nullptr);
966#error ReturnAddressLocator implementation missing for this architecture.
970 if ((time_origin_micros_ == -1) || (time_extent_micros_ == -1)) {
974 const int64_t timestamp = sample->
timestamp();
975 int64_t delta = timestamp - time_origin_micros_;
976 return (delta >= 0) && (delta <= time_extent_micros_);
980 const intptr_t task =
static_cast<intptr_t
>(sample->
thread_task());
984 return (task & thread_task_mask_) != 0;
1004 bool allocation_sample,
1005 intptr_t skip_count = 0)
1007 ? thread->isolate()->main_port()
1013 pc_(reinterpret_cast<
uword*>(pc)),
1014 fp_(reinterpret_cast<
uword*>(
fp)),
1015 sp_(reinterpret_cast<
uword*>(sp)),
1016 lr_(reinterpret_cast<
uword*>(lr)) {}
1026 bool has_exit_frame = exit_fp !=
nullptr;
1027 if (has_exit_frame) {
1036 if (thread_->
vm_tag() == VMTag::kDartTagId) {
1045 const bool is_entry_frame =
1046#if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64)
1052 if (is_entry_frame) {
1071 if (fp_ ==
nullptr) {
1094 uword* CallerPC()
const {
1100 return reinterpret_cast<uword*
>(*caller_pc_ptr);
1103 uword* CallerFP()
const {
1109 return reinterpret_cast<uword*
>(*caller_fp_ptr);
1112 uword* ExitLink()
const {
1118 return reinterpret_cast<uword*
>(*exit_link_ptr);
1121 uword Stack(intptr_t index)
const {
1123 uword* stack_ptr = sp_ + index;
1130 Thread*
const thread_;
1138 ASSERT(sample !=
nullptr);
1139 uword* sp =
reinterpret_cast<uword*
>(sp_addr);
1141 if (sp !=
nullptr) {
1151#if defined(DART_HOST_OS_WINDOWS)
1154static uword fault_address = 0;
1155static LONG GuardPageExceptionFilter(EXCEPTION_POINTERS* ep) {
1157 if (ep->ExceptionRecord->ExceptionCode != STATUS_GUARD_PAGE_VIOLATION) {
1158 return EXCEPTION_CONTINUE_SEARCH;
1161 fault_address = ep->ExceptionRecord->ExceptionInformation[1];
1163 ASSERT(ep->ExceptionRecord->ExceptionInformation[0] == 0);
1164 return EXCEPTION_EXECUTE_HANDLER;
1170 bool exited_dart_code,
1179 ASSERT(counters !=
nullptr);
1180#if defined(DART_HOST_OS_WINDOWS)
1191 if (FLAG_profile_vm) {
1193 counters->stack_walker_native.fetch_add(1);
1194 native_stack_walker->
walk();
1196 counters->stack_walker_dart_exit.fetch_add(1);
1198 dart_stack_walker->
walk();
1200 counters->stack_walker_dart.fetch_add(1);
1202 dart_stack_walker->
walk();
1204 counters->stack_walker_none.fetch_add(1);
1205 sample->
SetAt(0, pc);
1208#if defined(DART_HOST_OS_WINDOWS)
1210 } __except (GuardPageExceptionFilter(GetExceptionInformation())) {
1217 DWORD new_protect = PAGE_READWRITE | PAGE_GUARD;
1218 DWORD old_protect = 0;
1220 VirtualProtect(
reinterpret_cast<void*
>(fault_address),
1221 sizeof(fault_address), new_protect, &old_protect);
1224 ASSERT(old_protect == PAGE_READWRITE);
1230 bool allocation_sample,
1232 ASSERT(thread !=
nullptr);
1235 Sample* sample = allocation_sample ?
buffer->ReserveAllocationSample(isolate)
1236 :
buffer->ReserveCPUSample(isolate);
1237 if (sample ==
nullptr) {
1242#if defined(USING_SIMULATOR)
1247 if (redirect_vm_tag != 0) {
1248 vm_tag = redirect_vm_tag;
1267 uint32_t identity_hash) {
1268 ASSERT(thread !=
nullptr);
1270 ASSERT(os_thread !=
nullptr);
1290 uword stack_lower = 0;
1291 uword stack_upper = 0;
1301 if (sample ==
nullptr) {
1303 counters_.sample_allocation_failure++;
1309 if (FLAG_profile_vm_allocation) {
1313 stack_upper, pc,
fp, sp);
1314 native_stack_walker.
walk();
1315 }
else if (exited_dart_code) {
1319 dart_exit_stack_walker.
walk();
1323 sample->
SetAt(0, pc);
1327void Profiler::SampleThreadSingleFrame(
Thread* thread,
1330 ASSERT(thread !=
nullptr);
1332 ASSERT(os_thread !=
nullptr);
1345 sample->
SetAt(0, pc);
1350 ASSERT(thread !=
nullptr);
1352 ASSERT(os_thread !=
nullptr);
1357 counters_.bail_out_unknown_task.fetch_add(1);
1365 counters_.bail_out_jump_to_exception_handler.fetch_add(1);
1373 uintptr_t pc =
state.pc;
1374 uintptr_t lr =
state.lr;
1375#if defined(USING_SIMULATOR)
1381#if defined(USING_SIMULATOR)
1385 pc = simulator->
get_pc();
1386 lr = simulator->
get_lr();
1396 counters_.bail_out_check_isolate.fetch_add(1);
1408 SetupSample(thread,
false, os_thread->trace_id());
1409 if (sample ==
nullptr) {
1411 counters_.sample_allocation_failure++;
1417 counters_.single_frame_sample_deoptimizing.fetch_add(1);
1418 SampleThreadSingleFrame(thread, sample, pc);
1423 uword stack_lower = 0;
1424 uword stack_upper = 0;
1427 counters_.single_frame_sample_get_and_validate_stack_bounds.fetch_add(1);
1429 SampleThreadSingleFrame(thread, sample, pc);
1453 CollectSample(isolate, exited_dart_code, in_dart_code, sample,
1454 &native_stack_walker, &dart_stack_walker, pc,
fp, sp,
1465 return code_.
Size();
1479 ASSERT(table_ !=
nullptr);
1494void CodeLookupTable::Build(Thread* thread) {
1495 ASSERT(thread !=
nullptr);
1497 ASSERT(vm_isolate !=
nullptr);
1500 code_objects_.Clear();
1502 thread->CheckForSafepoint();
1505 TimelineBeginEndScope tl(Timeline::GetIsolateStream(),
1506 "CodeLookupTable::Build HeapIterationScope");
1507 HeapIterationScope iteration(thread);
1509 iteration.IterateVMIsolateObjects(&cltb);
1510 iteration.IterateOldObjects(&cltb);
1512 thread->CheckForSafepoint();
1525 for (intptr_t i = 0; i <
length() - 1; i++) {
1526 const CodeDescriptor*
a =
At(i);
1527 const CodeDescriptor*
b =
At(i + 1);
1537void CodeLookupTable::Add(
const Object& code) {
1540 CodeDescriptor* cd =
new CodeDescriptor(AbstractCode(
code.ptr()));
1541 code_objects_.Add(cd);
1548 intptr_t current = first;
1552 if (pc >= cd->
Start()) {
1585 for (intptr_t i = 0; i <
length; i++) {
1600 if (sample->
At(0) == 0) {
1604 if (filter !=
nullptr) {
1607 if (sample->
port() != filter->
port()) {
1650 bool truncated =
false;
1651 Sample* current = sample;
1652 while (current !=
nullptr) {
1654 if (current->
At(i) == 0) {
1657 processed_sample->
Add(current->
At(i));
1661 current =
Next(current);
1665 processed_sample->FixupCaller(clt, 0,
1670 return processed_sample;
1677 ASSERT(sample != next_sample);
1679 if (sample->
port() != next_sample->
port()) {
1685 if (sample->
tid() != next_sample->
tid()) {
1692 : pcs_(
Sample::kPCArraySizeInWords),
1696 allocation_cid_(-1),
1697 allocation_identity_hash_(0),
1698 truncated_(
false) {}
1702 uword* stack_buffer) {
1704 if (cd ==
nullptr) {
1712 CheckForMissingDartFrame(clt, cd, pc_marker, stack_buffer);
1715void ProcessedSample::CheckForMissingDartFrame(
const CodeLookupTable& clt,
1716 const CodeDescriptor* cd,
1718 uword* stack_buffer) {
1740 uword return_address = pc_marker;
1743 ReturnAddressLocator ral(
At(0), stack_buffer, code);
1745 if (!ral.LocateReturnAddress(&return_address)) {
1746 ASSERT(return_address == pc_marker);
1747 if (
code.GetPrologueOffset() == 0) {
1753 if (
code.ContainsInstructionAt(return_address)) {
1759 if (clt.FindCode(return_address) ==
nullptr) {
1764 if (return_address != 0) {
1771 ASSERT(code_lookup_table_ !=
nullptr);
1776 if (monitor_ ==
nullptr) {
1779 ASSERT(monitor_ !=
nullptr);
1780 initialized_ =
true;
1789 while (!thread_running_) {
1812 initialized_ =
false;
1813 ASSERT(!thread_running_);
1844 event.set_cpu_profile(&profile);
1853void SampleBlockProcessor::ThreadMain(
uword parameters) {
1859 ASSERT(os_thread !=
nullptr);
1861 thread_running_ =
true;
1862 startup_ml.Notify();
1865 MonitorLocker wait_ml(monitor_);
1867 const int64_t wakeup_interval = 1000 * 100;
1869 wait_ml.WaitMicros(wakeup_interval);
1877 const bool kBypassSafepoint =
false;
1880 group->ForEachIsolate([&](Isolate* isolate) {
1881 if (isolate->TakeHasCompletedBlocks()) {
1882 Profiler::ProcessCompletedBlocks(isolate);
1889 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 void FreeSymbolName(char *name)
static bool LookupSharedObject(uword pc, uword *dso_base=nullptr, char **dso_name=nullptr)
static char * LookupSymbolName(uword pc, uword *start)
static int Start(const char *name, ThreadStartFunction function, uword parameter)
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)
static const uint8_t buffer[]
#define DEFINE_FLAG(type, name, default_value, comment)
#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 constexpr intptr_t kMaxSamplesPerTick
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
#define TIMELINE_DURATION(thread, stream, name)
#define COPY_FP_REGISTER(fp)