[vm,dyn_modules] Fix Scope check in ActivationFrame::ContextLevel.
The end PC offset for the scope is inclusive, not exclusive.
Also rename PrintDescriptorsError -> PrintContextLevelError and
print the Bytecode local variable information since that is what
is searched for the context level for interpreted frames.
TEST=pkg/vm_service/test/step_through_closure
pkg/vm_service/test/step_through_function_expression
Cq-Include-Trybots: luci.dart.try:vm-dyn-linux-debug-x64-try,vm-aot-dyn-linux-debug-x64-try,vm-aot-dyn-linux-product-x64-try,vm-dyn-mac-debug-arm64-try
Change-Id: Ib53d0a7cff81de16c957b73ce9ec7dcb0e4aaa34
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/449740
Reviewed-by: Alexander Markov <alexmarkov@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
This commit is contained in:
committed by
Commit Queue
parent
20428509df
commit
e01fad78df
@@ -10,6 +10,7 @@
|
||||
#include "platform/assert.h"
|
||||
#include "vm/bytecode_reader.h"
|
||||
#include "vm/constants_kbc.h"
|
||||
#include "vm/zone_text_buffer.h"
|
||||
|
||||
namespace dart {
|
||||
|
||||
@@ -354,23 +355,6 @@ void KernelBytecodeDisassembler::Disassemble(uword start,
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
|
||||
static const int kLocalVariableKindMaxWidth = strlen(
|
||||
bytecode::BytecodeLocalVariablesIterator::kKindNames
|
||||
[bytecode::BytecodeLocalVariablesIterator::kVariableDeclaration]);
|
||||
|
||||
static const int kLocalVariableColumnWidths[] = {
|
||||
kLocalVariableKindMaxWidth, // kind
|
||||
14, // start pc
|
||||
14, // end pc
|
||||
7, // context level
|
||||
7, // index
|
||||
7, // start token pos
|
||||
7, // end token pos
|
||||
7, // decl token pos
|
||||
};
|
||||
#endif
|
||||
|
||||
void KernelBytecodeDisassembler::Disassemble(const Function& function) {
|
||||
#if !defined(PRODUCT)
|
||||
ASSERT(function.HasBytecode());
|
||||
@@ -416,61 +400,11 @@ void KernelBytecodeDisassembler::Disassemble(const Function& function) {
|
||||
|
||||
if (bytecode.HasLocalVariablesInfo()) {
|
||||
#if !defined(DART_PRECOMPILED_RUNTIME)
|
||||
auto& name = String::Handle(zone);
|
||||
auto& type = AbstractType::Handle(zone);
|
||||
THR_Print("Local variable information for function '%s' {\n",
|
||||
function_fullname);
|
||||
// "*" in a printf format specifier tells it to read the field width from
|
||||
// the printf argument list.
|
||||
THR_Print(
|
||||
" %*s %*s %*s %*s %*s %*s %*s %*s name\n",
|
||||
kLocalVariableColumnWidths[0], "kind", kLocalVariableColumnWidths[1],
|
||||
"start pc", kLocalVariableColumnWidths[2], "end pc",
|
||||
kLocalVariableColumnWidths[3], "ctx", kLocalVariableColumnWidths[4],
|
||||
"index", kLocalVariableColumnWidths[5], "start",
|
||||
kLocalVariableColumnWidths[6], "end", kLocalVariableColumnWidths[7],
|
||||
"decl");
|
||||
bytecode::BytecodeLocalVariablesIterator iter(zone, bytecode);
|
||||
while (iter.MoveNext()) {
|
||||
THR_Print(" %*s %-#*" Px "", kLocalVariableColumnWidths[0],
|
||||
iter.KindName(), kLocalVariableColumnWidths[1],
|
||||
base + iter.StartPC());
|
||||
if (iter.IsVariableDeclaration() || iter.IsScope()) {
|
||||
THR_Print(" %-#*" Px "", kLocalVariableColumnWidths[2],
|
||||
base + iter.EndPC());
|
||||
} else {
|
||||
THR_Print(" %*s", kLocalVariableColumnWidths[2], "");
|
||||
}
|
||||
if (iter.IsScope()) {
|
||||
THR_Print(" %*" Pd "", kLocalVariableColumnWidths[3],
|
||||
iter.ContextLevel());
|
||||
} else {
|
||||
THR_Print(" %*s", kLocalVariableColumnWidths[3], "");
|
||||
}
|
||||
if (iter.IsContextVariable() || iter.IsVariableDeclaration()) {
|
||||
THR_Print(" %*" Pd "", kLocalVariableColumnWidths[4], iter.Index());
|
||||
} else {
|
||||
THR_Print(" %*s", kLocalVariableColumnWidths[4], "");
|
||||
}
|
||||
if (iter.IsVariableDeclaration() || iter.IsScope()) {
|
||||
THR_Print(" %*s %*s", kLocalVariableColumnWidths[5],
|
||||
iter.StartTokenPos().ToCString(),
|
||||
kLocalVariableColumnWidths[6],
|
||||
iter.EndTokenPos().ToCString());
|
||||
|
||||
} else {
|
||||
THR_Print(" %*s %*s", kLocalVariableColumnWidths[5], "",
|
||||
kLocalVariableColumnWidths[6], "");
|
||||
}
|
||||
if (iter.IsVariableDeclaration()) {
|
||||
name = iter.Name();
|
||||
type = iter.Type();
|
||||
THR_Print(" %*s %s: %s%s", kLocalVariableColumnWidths[7],
|
||||
iter.DeclarationTokenPos().ToCString(), name.ToCString(),
|
||||
type.ToCString(), iter.IsCaptured() ? " (captured)" : "");
|
||||
}
|
||||
THR_Print("\n");
|
||||
}
|
||||
ZoneTextBuffer buffer(zone);
|
||||
bytecode.WriteLocalVariablesInfo(zone, &buffer);
|
||||
THR_Print("%s", buffer.buffer());
|
||||
THR_Print("}\n");
|
||||
#else
|
||||
UNREACHABLE();
|
||||
|
||||
+19
-10
@@ -40,6 +40,7 @@
|
||||
#include "vm/timeline.h"
|
||||
#include "vm/token_position.h"
|
||||
#include "vm/visitor.h"
|
||||
#include "vm/zone_text_buffer.h"
|
||||
|
||||
#if !defined(DART_PRECOMPILED_RUNTIME)
|
||||
#include "vm/deopt_instructions.h"
|
||||
@@ -629,8 +630,8 @@ bool ActivationFrame::IsDebuggable() const {
|
||||
return Debugger::IsDebuggable(function());
|
||||
}
|
||||
|
||||
void ActivationFrame::PrintDescriptorsError(const char* message) {
|
||||
OS::PrintErr("Bad descriptors: %s\n", message);
|
||||
void ActivationFrame::PrintContextLevelError(const char* message) {
|
||||
OS::PrintErr("Cannot locate context level: %s\n", message);
|
||||
OS::PrintErr("function %s\n", function().ToQualifiedCString());
|
||||
OS::PrintErr("pc_ %" Px "\n", pc_);
|
||||
OS::PrintErr("deopt_id_ %" Px "\n", deopt_id_);
|
||||
@@ -638,9 +639,12 @@ void ActivationFrame::PrintDescriptorsError(const char* message) {
|
||||
OS::PrintErr("token_pos_ %s\n", token_pos_.ToCString());
|
||||
if (IsInterpreted()) {
|
||||
#if defined(DART_DYNAMIC_MODULES)
|
||||
DisassembleToStdout formatter;
|
||||
bytecode().Disassemble(&formatter);
|
||||
OS::PrintErr("%s\n", var_descriptors_.ToCString());
|
||||
#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
|
||||
Zone* const zone = Thread::Current()->zone();
|
||||
ZoneTextBuffer buffer(zone);
|
||||
bytecode().WriteLocalVariablesInfo(zone, &buffer);
|
||||
OS::PrintErr("%s\n", buffer.buffer());
|
||||
#endif
|
||||
#else
|
||||
UNREACHABLE();
|
||||
#endif
|
||||
@@ -677,7 +681,7 @@ intptr_t ActivationFrame::ContextLevel() {
|
||||
while (local_vars.MoveNext()) {
|
||||
if (local_vars.IsScope()) {
|
||||
if (local_vars.StartPC() <= pc_offset &&
|
||||
pc_offset < local_vars.EndPC()) {
|
||||
pc_offset <= local_vars.EndPC()) {
|
||||
DEBUG_ASSERT(!found || local_vars.StartPC() > closest_start);
|
||||
found = true;
|
||||
context_level_ = local_vars.ContextLevel();
|
||||
@@ -689,6 +693,10 @@ intptr_t ActivationFrame::ContextLevel() {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
PrintContextLevelError(
|
||||
"No Scope local variable info for the current PC");
|
||||
}
|
||||
#else
|
||||
UNREACHABLE();
|
||||
#endif
|
||||
@@ -698,7 +706,7 @@ intptr_t ActivationFrame::ContextLevel() {
|
||||
// We store the deopt ids as real token positions.
|
||||
intptr_t deopt_id = DeoptId();
|
||||
if (deopt_id == DeoptId::kNone) {
|
||||
PrintDescriptorsError("Missing deopt id");
|
||||
PrintContextLevelError("Missing deopt id");
|
||||
}
|
||||
const TokenPosition to_compare = TokenPosition::Deserialize(deopt_id);
|
||||
for (intptr_t cur_idx = 0; cur_idx < var_desc_len; cur_idx++) {
|
||||
@@ -712,9 +720,10 @@ intptr_t ActivationFrame::ContextLevel() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
PrintDescriptorsError("Missing context level in var descriptors");
|
||||
if (!found) {
|
||||
PrintContextLevelError(
|
||||
"No ContextLevel var descriptor that contains the deopt id");
|
||||
}
|
||||
}
|
||||
ASSERT(context_level_ >= 0);
|
||||
}
|
||||
|
||||
@@ -423,7 +423,7 @@ class ActivationFrame : public ZoneAllocated {
|
||||
void PrintContextMismatchError(intptr_t ctx_slot,
|
||||
intptr_t frame_ctx_level,
|
||||
intptr_t var_ctx_level);
|
||||
void PrintDescriptorsError(const char* message);
|
||||
void PrintContextLevelError(const char* message);
|
||||
|
||||
intptr_t TryIndex();
|
||||
intptr_t DeoptId();
|
||||
|
||||
@@ -19389,6 +19389,86 @@ LocalVarDescriptorsPtr Bytecode::GetLocalVarDescriptors() const {
|
||||
UNREACHABLE();
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(DART_DYNAMIC_MODULES)
|
||||
static const int kLocalVariableKindMaxWidth = strlen(
|
||||
bytecode::BytecodeLocalVariablesIterator::kKindNames
|
||||
[bytecode::BytecodeLocalVariablesIterator::kVariableDeclaration]);
|
||||
|
||||
static const int kLocalVariableColumnWidths[] = {
|
||||
kLocalVariableKindMaxWidth, // kind
|
||||
14, // start pc
|
||||
14, // end pc
|
||||
7, // context level
|
||||
7, // index
|
||||
7, // start token pos
|
||||
7, // end token pos
|
||||
7, // decl token pos
|
||||
};
|
||||
#endif
|
||||
|
||||
void Bytecode::WriteLocalVariablesInfo(Zone* zone,
|
||||
BaseTextBuffer* buffer) const {
|
||||
#if defined(DART_DYNAMIC_MODULES)
|
||||
if (!HasLocalVariablesInfo()) return;
|
||||
|
||||
// "*" in a printf format specifier tells it to read the field width from
|
||||
// the printf argument list.
|
||||
buffer->Printf(
|
||||
" %*s %*s %*s %*s %*s %*s %*s %*s name\n", kLocalVariableColumnWidths[0],
|
||||
"kind", kLocalVariableColumnWidths[1], "start pc",
|
||||
kLocalVariableColumnWidths[2], "end pc", kLocalVariableColumnWidths[3],
|
||||
"ctx", kLocalVariableColumnWidths[4], "index",
|
||||
kLocalVariableColumnWidths[5], "start", kLocalVariableColumnWidths[6],
|
||||
"end", kLocalVariableColumnWidths[7], "decl");
|
||||
auto& name = String::Handle(zone);
|
||||
auto& type = AbstractType::Handle(zone);
|
||||
const uword base = PayloadStart();
|
||||
bytecode::BytecodeLocalVariablesIterator iter(zone, *this);
|
||||
while (iter.MoveNext()) {
|
||||
buffer->Printf(" %*s %-#*" Px "", kLocalVariableColumnWidths[0],
|
||||
iter.KindName(), kLocalVariableColumnWidths[1],
|
||||
base + iter.StartPC());
|
||||
if (iter.IsVariableDeclaration() || iter.IsScope()) {
|
||||
buffer->Printf(" %-#*" Px "", kLocalVariableColumnWidths[2],
|
||||
base + iter.EndPC());
|
||||
} else {
|
||||
buffer->Printf(" %*s", kLocalVariableColumnWidths[2], "");
|
||||
}
|
||||
if (iter.IsScope()) {
|
||||
buffer->Printf(" %*" Pd "", kLocalVariableColumnWidths[3],
|
||||
iter.ContextLevel());
|
||||
} else {
|
||||
buffer->Printf(" %*s", kLocalVariableColumnWidths[3], "");
|
||||
}
|
||||
if (iter.IsContextVariable() || iter.IsVariableDeclaration()) {
|
||||
buffer->Printf(" %*" Pd "", kLocalVariableColumnWidths[4], iter.Index());
|
||||
} else {
|
||||
buffer->Printf(" %*s", kLocalVariableColumnWidths[4], "");
|
||||
}
|
||||
if (iter.IsVariableDeclaration() || iter.IsScope()) {
|
||||
buffer->Printf(" %*s %*s", kLocalVariableColumnWidths[5],
|
||||
iter.StartTokenPos().ToCString(),
|
||||
kLocalVariableColumnWidths[6],
|
||||
iter.EndTokenPos().ToCString());
|
||||
|
||||
} else {
|
||||
buffer->Printf(" %*s %*s", kLocalVariableColumnWidths[5], "",
|
||||
kLocalVariableColumnWidths[6], "");
|
||||
}
|
||||
if (iter.IsVariableDeclaration()) {
|
||||
name = iter.Name();
|
||||
type = iter.Type();
|
||||
buffer->Printf(" %*s %s: %s%s", kLocalVariableColumnWidths[7],
|
||||
iter.DeclarationTokenPos().ToCString(), name.ToCString(),
|
||||
type.ToCString(), iter.IsCaptured() ? " (captured)" : "");
|
||||
}
|
||||
buffer->AddString("\n");
|
||||
}
|
||||
#else
|
||||
UNREACHABLE();
|
||||
#endif
|
||||
}
|
||||
#endif // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
|
||||
|
||||
const char* Bytecode::ToCString() const {
|
||||
|
||||
@@ -7610,6 +7610,8 @@ class Bytecode : public Object {
|
||||
untag()->set_var_descriptors<std::memory_order_release>(value.ptr());
|
||||
}
|
||||
|
||||
void WriteLocalVariablesInfo(Zone* zone, BaseTextBuffer* buffer) const;
|
||||
|
||||
// Will compute local var descriptors if necessary.
|
||||
LocalVarDescriptorsPtr GetLocalVarDescriptors() const;
|
||||
#endif // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
|
||||
|
||||
Reference in New Issue
Block a user