74f753f32d
Detects yield points in Debugger::IsAtAsyncJump for bytecode by seeing if the currently executing instruction is a direct call to an await or yield compiled stub. Adds a ResumptionBreakpointHandler runtime entry that is called during Interpreter::Resume() if the current isolate has resumption breakpoints. Similarly, all the places where a DebugCheck could be emitted if debugging stops are requested now include an explicit source position emission when source positions are requested but debugger stops are not, to ensure the debugger has appropriate information. Fixes CompareTopDartFrameTo returning kSelf for non-top frames when the top frame was interpreted but the stepping frame was not or vice versa. TEST=pkg/vm_service/test Change-Id: I88cdc37cf745f30e8dfb6b14c19fc9b2c4cbaf2d 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/+/446300 Commit-Queue: Tess Strickland <sstrickl@google.com> Reviewed-by: Alexander Markov <alexmarkov@google.com>
114 lines
3.4 KiB
Dart
114 lines
3.4 KiB
Dart
// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file
|
|
// for details. All rights reserved. Use of this source code is governed by a
|
|
// BSD-style license that can be found in the LICENSE file.
|
|
|
|
import 'bytecode_serialization.dart'
|
|
show
|
|
BufferedWriter,
|
|
BufferedReader,
|
|
BytecodeDeclaration,
|
|
PackedUInt30DeltaEncoder,
|
|
PackedUInt30DeltaDecoder,
|
|
SLEB128DeltaEncoder,
|
|
SLEB128DeltaDecoder;
|
|
|
|
/// Maintains mapping between bytecode instructions and source positions.
|
|
class SourcePositions extends BytecodeDeclaration {
|
|
// Special value of fileOffset which marks synthetic code without source
|
|
// position.
|
|
static const syntheticCodeMarker = -1;
|
|
|
|
final List<int> _positions = <int>[]; // Pairs (PC, fileOffset).
|
|
int _lastPc = 0;
|
|
int _lastOffset = 0;
|
|
|
|
SourcePositions();
|
|
|
|
// Maps the given PC to the given file offset.
|
|
void add(int pc, int fileOffset) {
|
|
assert((fileOffset >= 0) || (fileOffset == syntheticCodeMarker));
|
|
if (fileOffset != _lastOffset) {
|
|
if (pc <= _lastPc) {
|
|
throw ArgumentError(
|
|
'$pc <= $_lastPc for change in source position $fileOffset != $_lastOffset',
|
|
'pc');
|
|
}
|
|
_positions.add(pc);
|
|
_positions.add(fileOffset);
|
|
_lastPc = pc;
|
|
_lastOffset = fileOffset;
|
|
}
|
|
}
|
|
|
|
bool get isEmpty => _positions.isEmpty;
|
|
bool get isNotEmpty => !isEmpty;
|
|
|
|
void write(BufferedWriter writer) {
|
|
writer.writePackedUInt30(_positions.length ~/ 2);
|
|
final encodePC = new PackedUInt30DeltaEncoder();
|
|
final encodeOffset = new SLEB128DeltaEncoder();
|
|
for (int i = 0; i < _positions.length; i += 2) {
|
|
final int pc = _positions[i];
|
|
final int fileOffset = _positions[i + 1];
|
|
encodePC.write(writer, pc);
|
|
encodeOffset.write(writer, fileOffset);
|
|
}
|
|
}
|
|
|
|
SourcePositions.read(BufferedReader reader) {
|
|
final int length = reader.readPackedUInt30();
|
|
final decodePC = new PackedUInt30DeltaDecoder();
|
|
final decodeOffset = new SLEB128DeltaDecoder();
|
|
for (int i = 0; i < length; ++i) {
|
|
int pc = decodePC.read(reader);
|
|
int fileOffset = decodeOffset.read(reader);
|
|
_positions.add(pc);
|
|
_positions.add(fileOffset);
|
|
}
|
|
}
|
|
|
|
@override
|
|
String toString() => _positions.toString();
|
|
|
|
Map<int, String> getBytecodeAnnotations() {
|
|
final map = <int, String>{};
|
|
for (int i = 0; i < _positions.length; i += 2) {
|
|
final int pc = _positions[i];
|
|
final int fileOffset = _positions[i + 1];
|
|
final entry = 'source position $fileOffset';
|
|
if (map[pc] == null) {
|
|
map[pc] = entry;
|
|
} else {
|
|
map[pc] = "${map[pc]}; $entry";
|
|
}
|
|
}
|
|
return map;
|
|
}
|
|
}
|
|
|
|
/// Keeps file offsets of line starts. This information is used to
|
|
/// decode source positions to line/column.
|
|
class LineStarts extends BytecodeDeclaration {
|
|
final List<int> lineStarts;
|
|
|
|
LineStarts(this.lineStarts);
|
|
|
|
void write(BufferedWriter writer) {
|
|
writer.writePackedUInt30(lineStarts.length);
|
|
final encodeLineStarts = new PackedUInt30DeltaEncoder();
|
|
for (int lineStart in lineStarts) {
|
|
encodeLineStarts.write(writer, lineStart);
|
|
}
|
|
}
|
|
|
|
factory LineStarts.read(BufferedReader reader) {
|
|
final decodeLineStarts = new PackedUInt30DeltaDecoder();
|
|
final lineStarts = new List<int>.generate(
|
|
reader.readPackedUInt30(), (_) => decodeLineStarts.read(reader));
|
|
return new LineStarts(lineStarts);
|
|
}
|
|
|
|
@override
|
|
String toString() => 'Line starts: $lineStarts';
|
|
}
|