Skip to content

Commit 827551f

Browse files
sstricklCommit Queue
authored andcommitted
[vm,dyn_modules] Fix ActivationFrame::ContextLevel for bytecode frames.
Instead of using the computed LocalVarDescriptors when the frame is interpreted, use the LocalVariableInfo in the serialized bytecode to find which Scope is currently active. Add printing of local variable information to the bytecode disassembler. TEST=pkg/vm_service/test Change-Id: I7bd15056e4e2a947ad16ffb83a50447c2ba59994 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 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/449340 Reviewed-by: Alexander Markov <[email protected]> Commit-Queue: Tess Strickland <[email protected]>
1 parent 0a81294 commit 827551f

File tree

5 files changed

+151
-21
lines changed

5 files changed

+151
-21
lines changed

runtime/vm/bytecode_reader.cc

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2902,6 +2902,13 @@ void BytecodeReader::CollectScriptTokenPositionsFromBytecode(
29022902

29032903
#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
29042904

2905+
const char* BytecodeLocalVariablesIterator::kKindNames[] = {
2906+
"Invalid",
2907+
"Scope",
2908+
"VariableDeclaration",
2909+
"ContextVariable",
2910+
};
2911+
29052912
LocalVarDescriptorsPtr BytecodeReader::ComputeLocalVarDescriptors(
29062913
Zone* zone,
29072914
const Function& function,

runtime/vm/bytecode_reader.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -594,6 +594,7 @@ class BytecodeLocalVariablesIterator : ValueObject {
594594
kContextVariable,
595595
};
596596

597+
static const char* kKindNames[];
597598
static const intptr_t kKindMask = 0xF;
598599
static const intptr_t kIsCapturedFlag = 1 << 4;
599600

@@ -641,6 +642,7 @@ class BytecodeLocalVariablesIterator : ValueObject {
641642
bool IsDone() const { return entries_remaining_ < 0; }
642643

643644
intptr_t Kind() const { return cur_kind_and_flags_ & kKindMask; }
645+
const char* KindName() const { return kKindNames[Kind()]; }
644646
bool IsScope() const { return Kind() == kScope; }
645647
bool IsVariableDeclaration() const { return Kind() == kVariableDeclaration; }
646648
bool IsContextVariable() const { return Kind() == kContextVariable; }

runtime/vm/compiler/assembler/disassembler_kbc.cc

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,23 @@ void KernelBytecodeDisassembler::Disassemble(uword start,
354354
#endif
355355
}
356356

357+
#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
358+
static const int kLocalVariableKindMaxWidth = strlen(
359+
bytecode::BytecodeLocalVariablesIterator::kKindNames
360+
[bytecode::BytecodeLocalVariablesIterator::kVariableDeclaration]);
361+
362+
static const int kLocalVariableColumnWidths[] = {
363+
kLocalVariableKindMaxWidth, // kind
364+
14, // start pc
365+
14, // end pc
366+
7, // context level
367+
7, // index
368+
7, // start token pos
369+
7, // end token pos
370+
7, // decl token pos
371+
};
372+
#endif
373+
357374
void KernelBytecodeDisassembler::Disassemble(const Function& function) {
358375
#if !defined(PRODUCT)
359376
ASSERT(function.HasBytecode());
@@ -397,6 +414,69 @@ void KernelBytecodeDisassembler::Disassemble(const Function& function) {
397414
THR_Print("}\n");
398415
}
399416

417+
if (bytecode.HasLocalVariablesInfo()) {
418+
#if !defined(DART_PRECOMPILED_RUNTIME)
419+
auto& name = String::Handle(zone);
420+
auto& type = AbstractType::Handle(zone);
421+
THR_Print("Local variable information for function '%s' {\n",
422+
function_fullname);
423+
// "*" in a printf format specifier tells it to read the field width from
424+
// the printf argument list.
425+
THR_Print(
426+
" %*s %*s %*s %*s %*s %*s %*s %*s name\n",
427+
kLocalVariableColumnWidths[0], "kind", kLocalVariableColumnWidths[1],
428+
"start pc", kLocalVariableColumnWidths[2], "end pc",
429+
kLocalVariableColumnWidths[3], "ctx", kLocalVariableColumnWidths[4],
430+
"index", kLocalVariableColumnWidths[5], "start",
431+
kLocalVariableColumnWidths[6], "end", kLocalVariableColumnWidths[7],
432+
"decl");
433+
bytecode::BytecodeLocalVariablesIterator iter(zone, bytecode);
434+
while (iter.MoveNext()) {
435+
THR_Print(" %*s %-#*" Px "", kLocalVariableColumnWidths[0],
436+
iter.KindName(), kLocalVariableColumnWidths[1],
437+
base + iter.StartPC());
438+
if (iter.IsVariableDeclaration() || iter.IsScope()) {
439+
THR_Print(" %-#*" Px "", kLocalVariableColumnWidths[2],
440+
base + iter.EndPC());
441+
} else {
442+
THR_Print(" %*s", kLocalVariableColumnWidths[2], "");
443+
}
444+
if (iter.IsScope()) {
445+
THR_Print(" %*" Pd "", kLocalVariableColumnWidths[3],
446+
iter.ContextLevel());
447+
} else {
448+
THR_Print(" %*s", kLocalVariableColumnWidths[3], "");
449+
}
450+
if (iter.IsContextVariable() || iter.IsVariableDeclaration()) {
451+
THR_Print(" %*" Pd "", kLocalVariableColumnWidths[4], iter.Index());
452+
} else {
453+
THR_Print(" %*s", kLocalVariableColumnWidths[4], "");
454+
}
455+
if (iter.IsVariableDeclaration() || iter.IsScope()) {
456+
THR_Print(" %*s %*s", kLocalVariableColumnWidths[5],
457+
iter.StartTokenPos().ToCString(),
458+
kLocalVariableColumnWidths[6],
459+
iter.EndTokenPos().ToCString());
460+
461+
} else {
462+
THR_Print(" %*s %*s", kLocalVariableColumnWidths[5], "",
463+
kLocalVariableColumnWidths[6], "");
464+
}
465+
if (iter.IsVariableDeclaration()) {
466+
name = iter.Name();
467+
type = iter.Type();
468+
THR_Print(" %*s %s: %s%s", kLocalVariableColumnWidths[7],
469+
iter.DeclarationTokenPos().ToCString(), name.ToCString(),
470+
type.ToCString(), iter.IsCaptured() ? " (captured)" : "");
471+
}
472+
THR_Print("\n");
473+
}
474+
THR_Print("}\n");
475+
#else
476+
UNREACHABLE();
477+
#endif
478+
}
479+
400480
THR_Print("Exception Handlers for function '%s' {\n", function_fullname);
401481
const ExceptionHandlers& handlers =
402482
ExceptionHandlers::Handle(zone, bytecode.exception_handlers());

runtime/vm/debugger.cc

Lines changed: 53 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -636,7 +636,15 @@ void ActivationFrame::PrintDescriptorsError(const char* message) {
636636
OS::PrintErr("deopt_id_ %" Px "\n", deopt_id_);
637637
OS::PrintErr("context_level_ %" Px "\n", context_level_);
638638
OS::PrintErr("token_pos_ %s\n", token_pos_.ToCString());
639-
{
639+
if (IsInterpreted()) {
640+
#if defined(DART_DYNAMIC_MODULES)
641+
DisassembleToStdout formatter;
642+
bytecode().Disassemble(&formatter);
643+
OS::PrintErr("%s\n", var_descriptors_.ToCString());
644+
#else
645+
UNREACHABLE();
646+
#endif
647+
} else {
640648
DisassembleToStdout formatter;
641649
code().Disassemble(&formatter);
642650
PcDescriptors::Handle(code().pc_descriptors()).Print();
@@ -658,24 +666,51 @@ intptr_t ActivationFrame::ContextLevel() {
658666
const Context& ctx = GetSavedCurrentContext();
659667
if (context_level_ < 0 && !ctx.IsNull()) {
660668
ASSERT(IsInterpreted() || !code().is_optimized());
661-
GetVarDescriptors();
662-
intptr_t deopt_id = DeoptId();
663-
if (deopt_id == DeoptId::kNone) {
664-
PrintDescriptorsError("Missing deopt id");
665-
}
666-
intptr_t var_desc_len = var_descriptors_.Length();
667669
bool found = false;
668-
// We store the deopt ids as real token positions.
669-
const auto to_compare = TokenPosition::Deserialize(deopt_id);
670-
for (intptr_t cur_idx = 0; cur_idx < var_desc_len; cur_idx++) {
671-
UntaggedLocalVarDescriptors::VarInfo var_info;
672-
var_descriptors_.GetInfo(cur_idx, &var_info);
673-
const int8_t kind = var_info.kind();
674-
if ((kind == UntaggedLocalVarDescriptors::kContextLevel) &&
675-
to_compare.IsWithin(var_info.begin_pos, var_info.end_pos)) {
676-
context_level_ = var_info.index();
677-
found = true;
678-
break;
670+
if (IsInterpreted()) {
671+
#if defined(DART_DYNAMIC_MODULES) && !defined(PRODUCT) && \
672+
!defined(DART_PRECOMPILED_RUNTIME)
673+
const intptr_t pc_offset = pc() - PayloadStart();
674+
DEBUG_ONLY(intptr_t closest_start = 0);
675+
bytecode::BytecodeLocalVariablesIterator local_vars(
676+
Thread::Current()->zone(), bytecode());
677+
while (local_vars.MoveNext()) {
678+
if (local_vars.IsScope()) {
679+
if (local_vars.StartPC() <= pc_offset &&
680+
pc_offset < local_vars.EndPC()) {
681+
DEBUG_ASSERT(!found || local_vars.StartPC() > closest_start);
682+
found = true;
683+
context_level_ = local_vars.ContextLevel();
684+
DEBUG_ONLY(closest_start = local_vars.StartPC());
685+
} else if (local_vars.StartPC() > pc_offset) {
686+
// The scopes in the local variables info are ordered by starting
687+
// PC offset, so no need to search further.
688+
break;
689+
}
690+
}
691+
}
692+
#else
693+
UNREACHABLE();
694+
#endif
695+
} else {
696+
GetVarDescriptors();
697+
intptr_t var_desc_len = var_descriptors_.Length();
698+
// We store the deopt ids as real token positions.
699+
intptr_t deopt_id = DeoptId();
700+
if (deopt_id == DeoptId::kNone) {
701+
PrintDescriptorsError("Missing deopt id");
702+
}
703+
const TokenPosition to_compare = TokenPosition::Deserialize(deopt_id);
704+
for (intptr_t cur_idx = 0; cur_idx < var_desc_len; cur_idx++) {
705+
UntaggedLocalVarDescriptors::VarInfo var_info;
706+
var_descriptors_.GetInfo(cur_idx, &var_info);
707+
const int8_t kind = var_info.kind();
708+
if ((kind == UntaggedLocalVarDescriptors::kContextLevel) &&
709+
to_compare.IsWithin(var_info.begin_pos, var_info.end_pos)) {
710+
context_level_ = var_info.index();
711+
found = true;
712+
break;
713+
}
679714
}
680715
}
681716
if (!found) {

runtime/vm/object.h

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7601,9 +7601,6 @@ class Bytecode : public Object {
76017601
void set_local_variables_binary_offset(intptr_t value) const {
76027602
StoreNonPointer(&untag()->local_variables_binary_offset_, value);
76037603
}
7604-
bool HasLocalVariablesInfo() const {
7605-
return (local_variables_binary_offset() != 0);
7606-
}
76077604

76087605
LocalVarDescriptorsPtr var_descriptors() const {
76097606
return untag()->var_descriptors<std::memory_order_acquire>();
@@ -7616,6 +7613,15 @@ class Bytecode : public Object {
76167613
// Will compute local var descriptors if necessary.
76177614
LocalVarDescriptorsPtr GetLocalVarDescriptors() const;
76187615
#endif // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
7616+
7617+
bool HasLocalVariablesInfo() const {
7618+
#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
7619+
return (local_variables_binary_offset() != 0);
7620+
#else
7621+
return false;
7622+
#endif
7623+
}
7624+
76197625
const char* Name() const;
76207626
const char* QualifiedName() const;
76217627
const char* FullyQualifiedName() const;

0 commit comments

Comments
 (0)