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;
121 va_start(measure_args,
format);
123 va_end(measure_args);
124 if (remaining_ < len + 100) {
134 va_start(print_args,
format);
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--) {
220 const uword addr = code.GetPointerOffsetAt(i) + code.PayloadStart();
222 THR_Print(
" %d : %#" Px " '%s'\n", code.GetPointerOffsetAt(i), addr,
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",
357 " [code+0x%02" Px "] %" Px " kUnchecked\n",
360 THR_Print(
" [code+0x%02" Px "] %" Px " kMonomorphicUnchecked\n",
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;
525 va_start(measure_args,
format);
527 va_end(measure_args);
529 char* p =
reinterpret_cast<char*
>(
malloc(len + 1));
531 va_start(print_args,
format);
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
static const uint8_t buffer[]
uint32_t uint32_t * format
#define DECLARE_FLAG(type, name)
#define DEFINE_FLAG(type, name, default_value, comment)
Dart_NativeFunction function
void * malloc(size_t size)
static T LoadUnaligned(const T *ptr)
ArrayOfTuplesView< Code::SCallTableEntry, std::tuple< Smi, Object, Function > > StaticCallsTable
const char * DeoptReasonToCString(ICData::DeoptReasonId deopt_reason)