Skip to content

Commit f0fe238

Browse files
Clement Skaucommit-bot@chromium.org
Clement Skau
authored andcommitted
[VM] Stack trace: skip consecutive gaps.
TEST=tools/test.py -n dartk-linux-release-x64 vm/dart_2/causal_stacks Bug: #44169 Change-Id: I27dbe298ea30ef562984788223080fcb65f43da4 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/172961 Reviewed-by: Tess Strickland <[email protected]> Commit-Queue: Clement Skau <[email protected]>
1 parent dcafee7 commit f0fe238

File tree

1 file changed

+77
-60
lines changed

1 file changed

+77
-60
lines changed

runtime/vm/object.cc

Lines changed: 77 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -24247,6 +24247,8 @@ const char* StackTrace::ToCString() const {
2424724247
// for each frame.
2424824248
intptr_t frame_index = 0;
2424924249
uint32_t frame_skip = 0;
24250+
// If we're already in a gap, don't print multiple gap markers.
24251+
bool in_gap = false;
2425024252
do {
2425124253
for (intptr_t i = frame_skip; i < stack_trace.Length(); i++) {
2425224254
code_object = stack_trace.CodeAtFrame(i);
@@ -24260,72 +24262,87 @@ const char* StackTrace::ToCString() const {
2426024262
// To account for gap frames.
2426124263
frame_index += Smi::Value(stack_trace.PcOffsetAtFrame(i));
2426224264
}
24263-
} else if (code_object.raw() == StubCode::AsynchronousGapMarker().raw()) {
24264-
buffer.AddString("<asynchronous suspension>\n");
24265-
} else {
24266-
intptr_t pc_offset = Smi::Value(stack_trace.PcOffsetAtFrame(i));
24267-
ASSERT(code_object.IsCode());
24268-
code ^= code_object.raw();
24269-
ASSERT(code.IsFunctionCode());
24270-
function = code.function();
24271-
const uword pc = code.PayloadStart() + pc_offset;
24272-
#if defined(DART_PRECOMPILED_RUNTIME)
24273-
// When printing non-symbolic frames, we normally print call
24274-
// addresses, not return addresses, by subtracting one from the PC to
24275-
// get an address within the preceding instruction.
24276-
//
24277-
// The one exception is a normal closure registered as a listener on a
24278-
// future. In this case, the returned pc_offset is 0, as the closure
24279-
// is invoked with the value of the resolved future. Thus, we must
24280-
// report the return address, as returning a value before the closure
24281-
// payload will cause failures to decode the frame using DWARF info.
24282-
const bool is_future_listener = pc_offset == 0;
24283-
const uword call_addr = is_future_listener ? pc : pc - 1;
24284-
if (FLAG_dwarf_stack_traces_mode) {
24285-
// If we have access to the owning function and it would be
24286-
// invisible in a symbolic stack trace, don't show this frame.
24287-
// (We can't do the same for inlined functions, though.)
24288-
if (!FLAG_show_invisible_frames && !function.IsNull() &&
24289-
!function.is_visible()) {
24290-
continue;
24291-
}
24292-
// This output is formatted like Android's debuggerd. Note debuggerd
24293-
// prints call addresses instead of return addresses.
24294-
buffer.Printf(" #%02" Pd " abs %" Pp "", frame_index, call_addr);
24295-
PrintNonSymbolicStackFrameBody(&buffer, call_addr,
24296-
isolate_instructions, vm_instructions);
24297-
frame_index++;
24298-
continue;
24299-
} else if (function.IsNull()) {
24300-
// We can't print the symbolic information since the owner was not
24301-
// retained, so instead print the static symbol + offset like the
24302-
// non-symbolic stack traces.
24303-
PrintSymbolicStackFrameIndex(&buffer, frame_index);
24304-
PrintNonSymbolicStackFrameBody(&buffer, call_addr,
24305-
isolate_instructions, vm_instructions);
24306-
frame_index++;
24307-
continue;
24265+
continue;
24266+
}
24267+
24268+
if (code_object.raw() == StubCode::AsynchronousGapMarker().raw()) {
24269+
if (!in_gap) {
24270+
buffer.AddString("<asynchronous suspension>\n");
2430824271
}
24272+
in_gap = true;
24273+
continue;
24274+
}
24275+
24276+
intptr_t pc_offset = Smi::Value(stack_trace.PcOffsetAtFrame(i));
24277+
ASSERT(code_object.IsCode());
24278+
code ^= code_object.raw();
24279+
ASSERT(code.IsFunctionCode());
24280+
function = code.function();
24281+
const uword pc = code.PayloadStart() + pc_offset;
24282+
24283+
// If the function is not to be shown, skip.
24284+
if (!FLAG_show_invisible_frames && !function.IsNull() &&
24285+
!function.is_visible()) {
24286+
continue;
24287+
}
24288+
24289+
// A visible frame ends any gap we might be in.
24290+
in_gap = false;
24291+
24292+
#if defined(DART_PRECOMPILED_RUNTIME)
24293+
// When printing non-symbolic frames, we normally print call
24294+
// addresses, not return addresses, by subtracting one from the PC to
24295+
// get an address within the preceding instruction.
24296+
//
24297+
// The one exception is a normal closure registered as a listener on a
24298+
// future. In this case, the returned pc_offset is 0, as the closure
24299+
// is invoked with the value of the resolved future. Thus, we must
24300+
// report the return address, as returning a value before the closure
24301+
// payload will cause failures to decode the frame using DWARF info.
24302+
const bool is_future_listener = pc_offset == 0;
24303+
const uword call_addr = is_future_listener ? pc : pc - 1;
24304+
24305+
if (FLAG_dwarf_stack_traces_mode) {
24306+
// This output is formatted like Android's debuggerd. Note debuggerd
24307+
// prints call addresses instead of return addresses.
24308+
buffer.Printf(" #%02" Pd " abs %" Pp "", frame_index, call_addr);
24309+
PrintNonSymbolicStackFrameBody(&buffer, call_addr, isolate_instructions,
24310+
vm_instructions);
24311+
frame_index++;
24312+
continue;
24313+
}
24314+
24315+
if (function.IsNull()) {
24316+
in_gap = false;
24317+
// We can't print the symbolic information since the owner was not
24318+
// retained, so instead print the static symbol + offset like the
24319+
// non-symbolic stack traces.
24320+
PrintSymbolicStackFrameIndex(&buffer, frame_index);
24321+
PrintNonSymbolicStackFrameBody(&buffer, call_addr, isolate_instructions,
24322+
vm_instructions);
24323+
frame_index++;
24324+
continue;
24325+
}
2430924326
#endif
24310-
if (code.is_optimized() && stack_trace.expand_inlined()) {
24311-
code.GetInlinedFunctionsAtReturnAddress(pc_offset, &inlined_functions,
24312-
&inlined_token_positions);
24313-
ASSERT(inlined_functions.length() >= 1);
24314-
for (intptr_t j = inlined_functions.length() - 1; j >= 0; j--) {
24315-
const auto& inlined = *inlined_functions[j];
24316-
auto const pos = inlined_token_positions[j];
24317-
if (FLAG_show_invisible_frames || function.is_visible()) {
24318-
PrintSymbolicStackFrame(zone, &buffer, inlined, pos, frame_index);
24319-
frame_index++;
24320-
}
24321-
}
24322-
} else if (FLAG_show_invisible_frames || function.is_visible()) {
24323-
auto const pos = code.GetTokenIndexOfPC(pc);
24324-
PrintSymbolicStackFrame(zone, &buffer, function, pos, frame_index);
24327+
24328+
if (code.is_optimized() && stack_trace.expand_inlined()) {
24329+
code.GetInlinedFunctionsAtReturnAddress(pc_offset, &inlined_functions,
24330+
&inlined_token_positions);
24331+
ASSERT(inlined_functions.length() >= 1);
24332+
for (intptr_t j = inlined_functions.length() - 1; j >= 0; j--) {
24333+
const auto& inlined = *inlined_functions[j];
24334+
auto const pos = inlined_token_positions[j];
24335+
PrintSymbolicStackFrame(zone, &buffer, inlined, pos, frame_index);
2432524336
frame_index++;
2432624337
}
24338+
continue;
2432724339
}
24340+
24341+
auto const pos = code.GetTokenIndexOfPC(pc);
24342+
PrintSymbolicStackFrame(zone, &buffer, function, pos, frame_index);
24343+
frame_index++;
2432824344
}
24345+
2432924346
// Follow the link.
2433024347
frame_skip = stack_trace.skip_sync_start_in_parent_stack()
2433124348
? StackTrace::kSyncAsyncCroppedFrames

0 commit comments

Comments
 (0)