[vm,dyn_modules] Fix the interpreter case in GenerateResumeStub.
Previously, it would always call the ResumeInterpreter runtime entry
passing null as the value to return to the resumed code. Instead,
appropriately retrieve the to-be-returned value from the stack.
Also fixes IL printing to print constants in non-SSA flow graphs and
adds Interpreter::TraceStackFrames, which prints the top frames of the
current stack, so calls to it can be added for easier debugging in the
future.
TEST=pkg/vm_service/test/async_star_step_out_test.dart
(still fails, but the failure changes due to no longer spuriously
calling get:current after the generator finishes)
Cq-Include-Trybots: luci.dart.try:vm-dyn-linux-debug-x64-try
Change-Id: Ibb3524d32c8c4e1320f4f9dfd35947eda7d6ca68
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/488181
Reviewed-by: Alexander Markov <alexmarkov@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
This commit is contained in:
committed by
Commit Queue
parent
e9d8109258
commit
32b8c8f12f
@@ -34,7 +34,7 @@ DECLARE_FLAG(bool, trace_inlining_intervals);
|
||||
|
||||
static bool IsRedundant(Instruction* instr) {
|
||||
if (auto constant = instr->AsConstant()) {
|
||||
return !constant->HasUses();
|
||||
return constant->HasSSATemp() && !constant->HasUses();
|
||||
} else if (auto move = instr->AsParallelMove()) {
|
||||
return move->IsRedundant();
|
||||
} else {
|
||||
|
||||
@@ -2542,11 +2542,12 @@ void StubCodeCompiler::GenerateResumeStub() {
|
||||
}
|
||||
SPILLS_RETURN_ADDRESS_FROM_LR_TO_REGISTER({}); // Undo SetReturnAddress().
|
||||
#endif
|
||||
__ Comment("Resume interpreter with exception");
|
||||
__ Comment("Resume interpreter");
|
||||
__ Bind(&resume_interpreter);
|
||||
__ PushObject(NullObject()); // Make room for result.
|
||||
__ PushObject(NullObject()); // Return value.
|
||||
__ PushRegistersInOrder({kException, kStackTrace});
|
||||
// Load the value to pass to the resumed bytecode.
|
||||
__ LoadFromOffset(kTemp, FPREG, param_offset + 3 * target::kWordSize);
|
||||
__ PushRegistersInOrder({kTemp, kException, kStackTrace});
|
||||
__ CallRuntime(kResumeInterpreterRuntimeEntry, /*argument_count=*/3);
|
||||
__ Drop(3); // Drop arguments.
|
||||
__ PopRegister(CallingConventions::kReturnReg); // Get result.
|
||||
|
||||
@@ -439,6 +439,54 @@ DART_NOINLINE void Interpreter::WriteInstructionToTrace(const KBCInstr* pc) {
|
||||
}
|
||||
}
|
||||
|
||||
void Interpreter::PrintStackFrames(const ObjectPtr* FP,
|
||||
const ObjectPtr* SP,
|
||||
intptr_t depth) {
|
||||
const word *fp = reinterpret_cast<const word*>(FP),
|
||||
*sp = reinterpret_cast<const word*>(SP);
|
||||
for (intptr_t i = 0; i < depth; i++) {
|
||||
const word caller_pc = fp[kKBCSavedCallerPcSlotFromFp];
|
||||
const bool is_entry_frame = caller_pc == kEntryFramePcMarker;
|
||||
// The entry frame slots are printed separately from the rest of the frame.
|
||||
auto* const frame_end = fp + (is_entry_frame ? kKBCEntrySavedSlots : 0);
|
||||
|
||||
THR_Print("Frame %" Pd "%s:\n", i, is_entry_frame ? " (entry)" : "");
|
||||
for (auto* current = sp; current >= frame_end; --current) {
|
||||
THR_Print(" %#" Px ": %#" Px "\n", reinterpret_cast<uword>(current),
|
||||
*current);
|
||||
}
|
||||
|
||||
if (is_entry_frame) {
|
||||
THR_Print(" %#" Px ": %#" Px " (pool pointer)\n",
|
||||
reinterpret_cast<uword>(fp + kKBCSavedPpSlotFromEntryFp),
|
||||
fp[kKBCSavedPpSlotFromEntryFp]);
|
||||
THR_Print(" %#" Px ": %#" Px " (args descriptor)\n",
|
||||
reinterpret_cast<uword>(fp + kKBCSavedArgDescSlotFromEntryFp),
|
||||
fp[kKBCSavedArgDescSlotFromEntryFp]);
|
||||
THR_Print(" %#" Px ": %#" Px " (exit link)\n",
|
||||
reinterpret_cast<uword>(fp + kKBCExitLinkSlotFromEntryFp),
|
||||
fp[kKBCExitLinkSlotFromEntryFp]);
|
||||
}
|
||||
|
||||
THR_Print(" %#" Px ": %#" Px " (saved caller fp)\n",
|
||||
reinterpret_cast<uword>(fp + kKBCSavedCallerFpSlotFromFp),
|
||||
fp[kKBCSavedCallerFpSlotFromFp]);
|
||||
THR_Print(" %#" Px ": %#" Px " (saved caller pc)\n",
|
||||
reinterpret_cast<uword>(fp + kKBCSavedCallerPcSlotFromFp),
|
||||
fp[kKBCSavedCallerPcSlotFromFp]);
|
||||
if (is_entry_frame) break;
|
||||
THR_Print(" %#" Px ": %#" Px " (caller pc)\n",
|
||||
reinterpret_cast<uword>(fp + kKBCPcMarkerSlotFromFp),
|
||||
fp[kKBCPcMarkerSlotFromFp]);
|
||||
THR_Print(" %#" Px ": %#" Px " (called function)\n",
|
||||
reinterpret_cast<uword>(fp + kKBCFunctionSlotFromFp),
|
||||
fp[kKBCFunctionSlotFromFp]);
|
||||
sp = fp + kKBCCallerSpSlotFromFp;
|
||||
fp = reinterpret_cast<const word*>(fp[kKBCSavedCallerFpSlotFromFp]);
|
||||
THR_Print("\n");
|
||||
}
|
||||
}
|
||||
|
||||
#endif // defined(DEBUG)
|
||||
|
||||
// Calls into the Dart runtime are based on this interface.
|
||||
|
||||
@@ -289,6 +289,15 @@ class Interpreter {
|
||||
void FlushTraceBuffer();
|
||||
void WriteInstructionToTrace(const KBCInstr* pc);
|
||||
|
||||
// Prints at most the requested number of interpreted stack frames
|
||||
// up to the most recent entry frame.
|
||||
//
|
||||
// If [depth] is non-positive, prints all interpreted stack frames
|
||||
// up to the most recent entry frame.
|
||||
void PrintStackFrames(const ObjectPtr* FP,
|
||||
const ObjectPtr* SP,
|
||||
intptr_t depth = 0);
|
||||
|
||||
void* trace_file_;
|
||||
uint64_t trace_file_bytes_written_;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user