21#if !defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER)
23#if !defined(DART_PRECOMPILED_RUNTIME)
27DEFINE_FLAG(
bool, trace_source_positions,
false,
"Source position diagnostics");
29 include_inlining_info_in_disassembly,
31 "Include inlining information when printing disassembly")
39 const int kHexColumnWidth = 23;
40#if defined(TARGET_ARCH_IS_32_BIT)
41 THR_Print(
"0x%" Px32 " %s",
static_cast<uint32_t
>(pc), hex_buffer);
43 THR_Print(
"0x%" Px64 " %s",
static_cast<uint64_t
>(pc), hex_buffer);
45 int hex_length = strlen(hex_buffer);
46 if (hex_length < kHexColumnWidth) {
47 for (
int i = kHexColumnWidth - hex_length;
i > 0;
i--) {
52 if (
object !=
nullptr) {
78#if defined(TARGET_ARCH_RISCV32) || defined(TARGET_ARCH_RISCV64) || \
79 defined(TARGET_ARCH_ARM)
80 len = strlen(hex_buffer);
81 if (remaining_ <
len + 100) {
90 memmove(buffer_, hex_buffer,
len);
98 len = strlen(human_buffer);
99 if (remaining_ <
len + 100) {
108 memmove(buffer_, human_buffer,
len);
120 va_list measure_args;
124 if (remaining_ <
len + 100) {
149 const CodeComments* comments) {
150 if (comments ==
nullptr) {
151 comments =
code.IsNull() ? &Code::Comments::New(0) : &
code.comments();
153 ASSERT(formatter !=
nullptr);
154 char hex_buffer[kHexadecimalBufferSize];
155 char human_buffer[kUserReadableBufferSize];
157 intptr_t comment_finger = 0;
162 const intptr_t old_comment_finger = comment_finger;
163 while (comment_finger < comments->Length() &&
164 comments->PCOffsetAt(comment_finger) <=
offset) {
165 formatter->
Print(
" ;; %s\n", comments->CommentAt(comment_finger));
168 if (FLAG_include_inlining_info_in_disassembly &&
169 old_comment_finger != comment_finger && !
code.IsNull()) {
173 code.GetInlinedFunctionsAtInstruction(
offset, &inlined_functions,
177 for (intptr_t
i = 1;
i < inlined_functions.
length();
i++) {
178 const char*
name = inlined_functions[
i]->ToQualifiedCString();
180 f.Printf(
" ;; Inlined [%s",
name);
183 f.Printf(
" -> %s",
name);
188 formatter->
Print(
"%s", str);
191 int instruction_length;
194 sizeof(human_buffer), &instruction_length,
code, &
object,
197 sizeof(human_buffer),
object,
198 FLAG_disassemble_relative ?
offset : pc);
199 pc += instruction_length;
203void Disassembler::DisassembleCodeHelper(
const char* function_fullname,
204 const char* function_info,
209 THR_Print(
"Code for %sfunction '%s' (%s) {\n", optimized ?
"optimized " :
"",
210 function_fullname, function_info);
214#if defined(TARGET_ARCH_IA32)
215 if (
code.pointer_offsets_length() > 0) {
216 THR_Print(
"Pointer offsets for function: {\n");
219 for (intptr_t
i =
code.pointer_offsets_length() - 1;
i >= 0;
i--) {
231 if (FLAG_precompiled_mode) {
234 const ObjectPool& object_pool =
236 if (!object_pool.IsNull() && object_pool.Length() > 0) {
237 object_pool.DebugPrint();
241 code.DumpSourcePositions(FLAG_disassemble_relative);
246 const PcDescriptors& descriptors =
248 if (descriptors.Length() > 0) {
250 buffer.Printf(
"PC Descriptors for function '%s' {\n", function_fullname);
256#if !defined(DART_PRECOMPILED_RUNTIME)
258 if (!deopt_table.IsNull()) {
260 if (deopt_table_length > 0) {
265 for (intptr_t
i = 0;
i < deopt_table_length; ++
i) {
267 const intptr_t reason =
269 ASSERT((0 <= reason) && (reason < ICData::kDeoptNumReasons));
280 const auto& stackmaps =
282 if (!stackmaps.IsNull() && stackmaps.payload_size() > 0) {
284 buffer.Printf(
"StackMaps for function '%s' {\n", function_fullname);
286 buffer.AddString(
"\n}\n");
291 if (FLAG_print_variable_descriptors) {
292 var_descriptors =
code.GetLocalVarDescriptors();
294 const intptr_t var_desc_length =
295 var_descriptors.IsNull() ? 0 : var_descriptors.Length();
296 if (var_desc_length > 0) {
297 THR_Print(
"Variable Descriptors for function '%s' {\n", function_fullname);
299 for (intptr_t
i = 0;
i < var_desc_length;
i++) {
300 var_name = var_descriptors.GetName(
i);
301 UntaggedLocalVarDescriptors::VarInfo var_info;
302 var_descriptors.GetInfo(
i, &var_info);
303 const int8_t kind = var_info.kind();
305 THR_Print(
" saved current CTX reg offset %d\n", var_info.index());
308 THR_Print(
" context level %d scope %d", var_info.index(),
311 THR_Print(
" stack var '%s' offset %d", var_name.ToCString(),
315 THR_Print(
" context var '%s' level %d offset %d",
316 var_name.ToCString(), var_info.scope_id, var_info.index());
318 THR_Print(
" (valid %s-%s)\n", var_info.begin_pos.ToCString(),
319 var_info.end_pos.ToCString());
325 const ExceptionHandlers& handlers =
327 if (handlers.num_entries() > 0 || handlers.has_async_handler()) {
329 buffer.Printf(
"Exception Handlers for function '%s' {\n",
336#if defined(DART_PRECOMPILED_RUNTIME) || defined(DART_PRECOMPILER)
337 if (FLAG_precompiled_mode &&
339 THR_Print(
"Catch entry moves for function '%s' {\n", function_fullname);
340 CatchEntryMovesMapReader reader(
342 reader.PrintEntries();
348 THR_Print(
"Entry points for function '%s' {\n", function_fullname);
353 " [code+0x%02" Px "] %" Px " kMonomorphic\n",
355 code.MonomorphicEntryPoint() - start +
base);
357 " [code+0x%02" Px "] %" Px " kUnchecked\n",
359 code.UncheckedEntryPoint() - start +
base);
360 THR_Print(
" [code+0x%02" Px "] %" Px " kMonomorphicUnchecked\n",
363 code.MonomorphicUncheckedEntryPoint() - start +
base);
367#if defined(DART_PRECOMPILED_RUNTIME)
368 THR_Print(
"(Cannot show static call target functions in AOT runtime.)\n");
371 if (!
table.IsNull()) {
373 if (static_calls.Length() > 0) {
374 THR_Print(
"Static call target functions {\n");
381 for (
auto&
call : static_calls) {
387 if (
object.IsAbstractType()) {
388 dst_type = AbstractType::Cast(
object).ptr();
389 }
else if (
object.IsCode()) {
390 code = Code::Cast(
object).ptr();
398 const char* s_entry_point =
400 const char* skind =
nullptr;
403 skind =
"pc-relative-call";
406 skind =
"pc-relative-tts-call";
409 skind =
"pc-relative-tail-call";
412 skind =
"call-via-code";
417 if (!dst_type.IsNull()) {
418 THR_Print(
" 0x%" Px ": type testing stub %s, (%s)%s\n",
419 base +
offset, dst_type.ToCString(), skind, s_entry_point);
425 code.QualifiedName(NameFormattingParams(
427 skind, s_entry_point);
429 THR_Print(
" 0x%" Px ": allocation stub for %s, (%s)%s\n",
430 base +
offset, cls.ToCString(), skind, s_entry_point);
434 function.ToFullyQualifiedCString(), skind, s_entry_point);
442#if !defined(DART_PRECOMPILED_RUNTIME)
443 if (optimized && FLAG_trace_inlining_intervals) {
444 code.DumpInlineIntervals();
448 if (FLAG_trace_source_positions) {
449 code.DumpSourcePositions();
456 if (
code.IsUnknownDartCode()) {
464 const char* function_fullname =
function.ToFullyQualifiedCString();
466 if (
function.HasSavedArgumentsDescriptor()) {
473 DisassembleCodeHelper(function_fullname,
buffer.buffer(),
code, optimized);
484 code.Disassemble(&formatter);
487 if (FLAG_precompiled_mode) {
488 THR_Print(
"(No object pool for bare instructions.)\n");
489 }
else if (!object_pool.
IsNull() && object_pool.
Length() > 0) {
516 if (
object !=
nullptr) {
524 va_list measure_args;
529 char*
p =
reinterpret_cast<char*
>(
malloc(
len + 1));
535 for (intptr_t
i = 0;
i <
len;
i++) {
536 if (
p[
i] ==
'\n' ||
p[
i] ==
'\r') {
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
void PrintTo(BaseTextBuffer *buffer, bool show_named_positions=false) const
static constexpr ICData::DeoptReasonId decode(intptr_t value)
static intptr_t entry_point_offset(EntryKind kind=EntryKind::kNormal)
@ kSCallTableFunctionTarget
@ kSCallTableCodeOrTypeTarget
@ kSCallTableKindAndOffset
static const char * ToCString(const Array &table, const TypedData &packed)
static void GetEntry(const Array &table, intptr_t index, Smi *offset, TypedData *info, Smi *reason_and_flags)
static intptr_t GetLength(const Array &table)
virtual void ConsumeInstruction(char *hex_buffer, intptr_t hex_size, char *human_buffer, intptr_t human_size, Object *object, uword pc)
virtual void Print(const char *format,...) PRINTF_ATTRIBUTE(2
virtual void ConsumeInstruction(char *hex_buffer, intptr_t hex_size, char *human_buffer, intptr_t human_size, Object *object, uword pc)
virtual void Print(const char *format,...) PRINTF_ATTRIBUTE(2
virtual void Print(const char *format,...) PRINTF_ATTRIBUTE(2
static void Disassemble(uword start, uword end, DisassemblyFormatter *formatter, const Code &code, const CodeComments *comments=nullptr)
static void DisassembleStub(const char *name, const Code &code)
static void DisassembleCode(const Function &function, const Code &code, bool optimized)
static void DecodeInstruction(char *hex_buffer, intptr_t hex_size, char *human_buffer, intptr_t human_size, int *out_instr_len, const Code &code, Object **object, uword pc)
static const char * KindToCString(UntaggedFunction::Kind kind)
void AddValueNull() const
void AddValue(bool b) const
void AddValueF(const char *format,...) const PRINTF_ATTRIBUTE(2
virtual const char * ToCString() const
static Thread * Current()
static int static int VSNPrint(char *str, size_t size, const char *format, va_list args)
#define THR_Print(format,...)
#define THR_VPrint(format, args)
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
uint32_t uint32_t * format
Dart_NativeFunction function
void * malloc(size_t size)
DEFINE_FLAG(bool, print_cluster_information, false, "Print information about clusters written to snapshot")
static T LoadUnaligned(const T *ptr)
ArrayOfTuplesView< Code::SCallTableEntry, std::tuple< Smi, Object, Function > > StaticCallsTable
const char * DeoptReasonToCString(ICData::DeoptReasonId deopt_reason)
DECLARE_FLAG(bool, show_invisible_frames)
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