Skip to content

Commit

Permalink
[vm/bytecode] Add DebugCheck bytecode instruction
Browse files Browse the repository at this point in the history
DebugCheck bytecode instruction is generated after parameter variables
are declared and copied into their locations in the prologue.
It helps debugger to stop in the beginning of a function at the point
where parameters can be inspected. It is generated only if
'--bytecode-options=debugger-stops' is specified.

Change-Id: I0f3b1ea8dc45d762a5dcee75b5d3a4ffc0b2a1b1
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/108371
Reviewed-by: Ryan Macnak <[email protected]>
Reviewed-by: Régis Crelier <[email protected]>
Commit-Queue: Alexander Markov <[email protected]>
  • Loading branch information
alexmarkov authored and [email protected] committed Jul 9, 2019
1 parent fc542be commit 9503969
Show file tree
Hide file tree
Showing 12 changed files with 62 additions and 26 deletions.
5 changes: 3 additions & 2 deletions pkg/vm/bin/kernel_service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -146,8 +146,8 @@ abstract class Compiler {

if (options.bytecode && errors.isEmpty) {
await runWithFrontEndCompilerContext(script, options, component, () {
// TODO(alexmarkov): disable source positions, local variables info
// and source files in VM PRODUCT mode.
// TODO(alexmarkov): disable source positions, local variables info,
// debugger stops and source files in VM PRODUCT mode.
// TODO(alexmarkov): disable asserts if they are not enabled in VM.
// TODO(rmacnak): disable annotations if mirrors are not enabled.
generateBytecode(component,
Expand All @@ -156,6 +156,7 @@ abstract class Compiler {
environmentDefines: options.environmentDefines,
emitSourcePositions: true,
emitLocalVarInfo: true,
emitDebuggerStops: true,
emitSourceFiles: true,
emitAnnotations: true));
});
Expand Down
5 changes: 5 additions & 0 deletions pkg/vm/lib/bytecode/assembler.dart
Original file line number Diff line number Diff line change
Expand Up @@ -513,6 +513,11 @@ class BytecodeAssembler {
_emitInstructionA(Opcode.kCheckStack, ra);
}

void emitDebugCheck() {
emitSourcePosition();
_emitInstruction0(Opcode.kDebugCheck);
}

void emitCheckFunctionTypeArgs(int ra, int re) {
emitSourcePosition();
_emitInstructionAE(Opcode.kCheckFunctionTypeArgs, ra, re);
Expand Down
8 changes: 4 additions & 4 deletions pkg/vm/lib/bytecode/dbc.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ library vm.bytecode.dbc;
/// Before bumping current bytecode version format, make sure that
/// all users have switched to a VM which is able to consume new
/// version of bytecode.
const int currentBytecodeFormatVersion = 12;
const int currentBytecodeFormatVersion = 13;

enum Opcode {
kUnusedOpcode000,
Expand Down Expand Up @@ -99,8 +99,6 @@ enum Opcode {
kUnusedOpcode083,
kUnusedOpcode084,

// Bytecode instructions since bytecode format v7:

kTrap,

// Prologue and stack management.
Expand All @@ -117,7 +115,7 @@ enum Opcode {
kCheckFunctionTypeArgs,
kCheckFunctionTypeArgs_Wide,
kCheckStack,
kUnused01,
kDebugCheck,
kUnused02, // Reserved for CheckParameterTypes
kUnused03, // Reserved for CheckParameterTypes_Wide

Expand Down Expand Up @@ -370,6 +368,8 @@ const Map<Opcode, Format> BytecodeFormats = const {
Encoding.kAE, const [Operand.imm, Operand.reg, Operand.none]),
Opcode.kCheckStack: const Format(
Encoding.kA, const [Operand.imm, Operand.none, Operand.none]),
Opcode.kDebugCheck: const Format(
Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
Opcode.kAllocate: const Format(
Encoding.kD, const [Operand.lit, Operand.none, Operand.none]),
Opcode.kAllocateT: const Format(
Expand Down
23 changes: 17 additions & 6 deletions pkg/vm/lib/bytecode/gen_bytecode.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1534,12 +1534,6 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
} else {
asm.emitEntry(locals.frameSize);
}
// TODO(alexmarkov): Introduce a new bytecode triggering a debug check in
// the interpreter. Its token position should correspond to the declaration
// position of the last parameter, which the debugger can inspect at the
// point of the debug check.
// TODO(regis): Support the new bytecode in the interpreter and dissociate
// the debug check from the CheckStack bytecode.
asm.emitCheckStack(0);

if (isClosure) {
Expand Down Expand Up @@ -1666,6 +1660,23 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
function.positionalParameters.forEach(_copyParamIfCaptured);
locals.sortedNamedParameters.forEach(_copyParamIfCaptured);
}

if (options.emitDebuggerStops) {
// DebugCheck instruction should be emitted after parameter variables
// are declared and copied into context.
// The debugger expects the source position to correspond to the
// declaration position of the last parameter, if any, or of the function.
if (options.emitSourcePositions && function != null) {
var pos = function.fileOffset;
if (function.namedParameters.isNotEmpty) {
pos = function.namedParameters.last.fileOffset;
} else if (function.positionalParameters.isNotEmpty) {
pos = function.positionalParameters.last.fileOffset;
}
_recordSourcePosition(pos);
}
asm.emitDebugCheck();
}
}

void _copyParamIfCaptured(VariableDeclaration variable) {
Expand Down
6 changes: 6 additions & 0 deletions pkg/vm/lib/bytecode/options.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ class BytecodeOptions {
static Map<String, String> commandLineFlags = {
'annotations': 'Emit Dart annotations',
'local-var-info': 'Emit debug information about local variables',
'debugger-stops': 'Emit bytecode instructions for stopping in the debugger',
'show-bytecode-size-stat': 'Show bytecode size breakdown',
'source-positions': 'Emit source positions',
};
Expand All @@ -18,6 +19,7 @@ class BytecodeOptions {
bool emitSourcePositions;
bool emitSourceFiles;
bool emitLocalVarInfo;
bool emitDebuggerStops;
bool emitAnnotations;
bool omitAssertSourcePositions;
bool showBytecodeSizeStatistics;
Expand All @@ -29,6 +31,7 @@ class BytecodeOptions {
this.emitSourcePositions = false,
this.emitSourceFiles = false,
this.emitLocalVarInfo = false,
this.emitDebuggerStops = false,
this.emitAnnotations = false,
this.omitAssertSourcePositions = false,
this.showBytecodeSizeStatistics = false,
Expand All @@ -49,6 +52,9 @@ class BytecodeOptions {
case 'local-var-info':
emitLocalVarInfo = true;
break;
case 'debugger-stops':
emitDebuggerStops = true;
break;
case 'annotations':
emitAnnotations = true;
break;
Expand Down
9 changes: 9 additions & 0 deletions runtime/vm/compiler/frontend/base_flow_graph_builder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -873,6 +873,15 @@ Fragment BaseFlowGraphBuilder::BuildFfiAsFunctionInternalCall(
return code;
}

Fragment BaseFlowGraphBuilder::DebugStepCheck(TokenPosition position) {
#ifdef PRODUCT
return Fragment();
#else
return Fragment(new (Z) DebugStepCheckInstr(
position, RawPcDescriptors::kRuntimeCall, GetNextDeoptId()));
#endif
}

} // namespace kernel
} // namespace dart

Expand Down
2 changes: 2 additions & 0 deletions runtime/vm/compiler/frontend/base_flow_graph_builder.h
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,8 @@ class BaseFlowGraphBuilder {
const Class& klass,
intptr_t argument_count);

Fragment DebugStepCheck(TokenPosition position);

protected:
intptr_t AllocateBlockId() { return ++last_used_block_id_; }

Expand Down
7 changes: 7 additions & 0 deletions runtime/vm/compiler/frontend/bytecode_flow_graph_builder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -730,6 +730,13 @@ void BytecodeFlowGraphBuilder::BuildCheckStack() {
}
}

void BytecodeFlowGraphBuilder::BuildDebugCheck() {
if (is_generating_interpreter()) {
UNIMPLEMENTED(); // TODO(alexmarkov): interpreter
}
code_ += B->DebugStepCheck(position_);
}

void BytecodeFlowGraphBuilder::BuildPushConstant() {
PushConstant(ConstantAt(DecodeOperandD()));
}
Expand Down
9 changes: 0 additions & 9 deletions runtime/vm/compiler/frontend/kernel_to_il.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1220,15 +1220,6 @@ bool FlowGraphBuilder::NeedsDebugStepCheck(Value* value,
return definition->IsLoadLocal();
}

Fragment FlowGraphBuilder::DebugStepCheck(TokenPosition position) {
#ifdef PRODUCT
return Fragment();
#else
return Fragment(new (Z) DebugStepCheckInstr(
position, RawPcDescriptors::kRuntimeCall, GetNextDeoptId()));
#endif
}

Fragment FlowGraphBuilder::EvaluateAssertion() {
const Class& klass =
Class::ZoneHandle(Z, Library::LookupCoreClass(Symbols::AssertionError()));
Expand Down
1 change: 0 additions & 1 deletion runtime/vm/compiler/frontend/kernel_to_il.h
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,6 @@ class FlowGraphBuilder : public BaseFlowGraphBuilder {

bool NeedsDebugStepCheck(const Function& function, TokenPosition position);
bool NeedsDebugStepCheck(Value* value, TokenPosition position);
Fragment DebugStepCheck(TokenPosition position);

// Truncates (instead of deoptimizing) if the origin does not fit into the
// target representation.
Expand Down
6 changes: 3 additions & 3 deletions runtime/vm/constants_kbc.h
Original file line number Diff line number Diff line change
Expand Up @@ -570,7 +570,7 @@ namespace dart {
V(CheckFunctionTypeArgs, A_E, ORDN, num, reg, ___) \
V(CheckFunctionTypeArgs_Wide, A_E, WIDE, num, reg, ___) \
V(CheckStack, A, ORDN, num, ___, ___) \
V(Unused01, 0, RESV, ___, ___, ___) \
V(DebugCheck, 0, ORDN, ___, ___, ___) \
V(Unused02, 0, RESV, ___, ___, ___) \
V(Unused03, 0, RESV, ___, ___, ___) \
V(Allocate, D, ORDN, lit, ___, ___) \
Expand Down Expand Up @@ -749,7 +749,7 @@ class KernelBytecode {
// Maximum bytecode format version supported by VM.
// The range of supported versions should include version produced by bytecode
// generator (currentBytecodeFormatVersion in pkg/vm/lib/bytecode/dbc.dart).
static const intptr_t kMaxSupportedBytecodeFormatVersion = 12;
static const intptr_t kMaxSupportedBytecodeFormatVersion = 13;

enum Opcode {
#define DECLARE_BYTECODE(name, encoding, kind, op1, op2, op3) k##name,
Expand Down Expand Up @@ -969,7 +969,7 @@ class KernelBytecode {
case KernelBytecode::kStoreLocal_Wide:
case KernelBytecode::kStoreStaticTOS:
case KernelBytecode::kStoreStaticTOS_Wide:
case KernelBytecode::kCheckStack:
case KernelBytecode::kDebugCheck:
case KernelBytecode::kDirectCall:
case KernelBytecode::kDirectCall_Wide:
case KernelBytecode::kInterfaceCall:
Expand Down
7 changes: 6 additions & 1 deletion runtime/vm/interpreter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1750,7 +1750,6 @@ RawObject* Interpreter::Call(RawFunction* function,

{
BYTECODE(CheckStack, A);
DEBUG_CHECK;
{
// Check the interpreter's own stack limit for actual interpreter's stack
// overflows, and also the thread's stack limit for scheduled interrupts.
Expand All @@ -1775,6 +1774,12 @@ RawObject* Interpreter::Call(RawFunction* function,
DISPATCH();
}

{
BYTECODE(DebugCheck, 0);
DEBUG_CHECK;
DISPATCH();
}

{
BYTECODE(CheckFunctionTypeArgs, A_E);
const intptr_t declared_type_args_len = rA;
Expand Down

0 comments on commit 9503969

Please sign in to comment.