[vm/bytecode] Add starting and ending source positions for closures
Issue: https://github.com/dart-lang/sdk/issues/36427
Change-Id: Ib2f55504f9238036a9700f1e2672b4641536ab7c
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/103480
Reviewed-by: RĂ©gis Crelier <regis@google.com>
Commit-Queue: Alexander Markov <alexmarkov@google.com>
diff --git a/pkg/vm/lib/bytecode/dbc.dart b/pkg/vm/lib/bytecode/dbc.dart
index 2ee6f20..974c842 100644
--- a/pkg/vm/lib/bytecode/dbc.dart
+++ b/pkg/vm/lib/bytecode/dbc.dart
@@ -10,7 +10,7 @@
/// 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 = 7;
+const int currentBytecodeFormatVersion = 8;
/// Version of experimental / bleeding edge bytecode format.
/// Produced by bytecode generator when --use-future-bytecode-format
diff --git a/pkg/vm/lib/bytecode/declarations.dart b/pkg/vm/lib/bytecode/declarations.dart
index 5fde12c..5baf7d6 100644
--- a/pkg/vm/lib/bytecode/declarations.dart
+++ b/pkg/vm/lib/bytecode/declarations.dart
@@ -140,10 +140,10 @@
((flags & hasCustomScriptFlag) != 0) ? reader.readPackedObject() : null;
final position = ((flags & hasSourcePositionsFlag) != 0)
? reader.readPackedUInt30() - 1
- : 0;
+ : TreeNode.noOffset;
final endPosition = ((flags & hasSourcePositionsFlag) != 0)
? reader.readPackedUInt30() - 1
- : 0;
+ : TreeNode.noOffset;
final initializerCode =
((flags & hasInitializerFlag) != 0 && (flags & isStaticFlag) != 0)
? reader.readLinkOffset<Code>()
@@ -298,10 +298,10 @@
((flags & hasCustomScriptFlag) != 0) ? reader.readPackedObject() : null;
final position = ((flags & hasSourcePositionsFlag) != 0)
? reader.readPackedUInt30() - 1
- : 0;
+ : TreeNode.noOffset;
final endPosition = ((flags & hasSourcePositionsFlag) != 0)
? reader.readPackedUInt30() - 1
- : 0;
+ : TreeNode.noOffset;
final typeParameters = ((flags & hasTypeParamsFlag) != 0)
? new TypeParametersDeclaration.read(reader)
: null;
@@ -628,12 +628,15 @@
}
class ClosureDeclaration {
- static const int flagHasOptionalPositionalParams = 1 << 0;
- static const int flagHasOptionalNamedParams = 1 << 1;
- static const int flagHasTypeParams = 1 << 2;
+ static const int hasOptionalPositionalParamsFlag = 1 << 0;
+ static const int hasOptionalNamedParamsFlag = 1 << 1;
+ static const int hasTypeParamsFlag = 1 << 2;
+ static const int hasSourcePositionsFlag = 1 << 3;
final ObjectHandle parent;
final ObjectHandle name;
+ final int position;
+ final int endPosition;
final List<NameAndType> typeParams;
final int numRequiredParams;
final int numNamedParams;
@@ -644,6 +647,8 @@
ClosureDeclaration(
this.parent,
this.name,
+ this.position,
+ this.endPosition,
this.typeParams,
this.numRequiredParams,
this.numNamedParams,
@@ -654,19 +659,27 @@
int flags = 0;
if (numRequiredParams != parameters.length) {
if (numNamedParams > 0) {
- flags |= flagHasOptionalNamedParams;
+ flags |= hasOptionalNamedParamsFlag;
} else {
- flags |= flagHasOptionalPositionalParams;
+ flags |= hasOptionalPositionalParamsFlag;
}
}
if (typeParams.isNotEmpty) {
- flags |= flagHasTypeParams;
+ flags |= hasTypeParamsFlag;
+ }
+ if (position != TreeNode.noOffset) {
+ flags |= hasSourcePositionsFlag;
}
writer.writePackedUInt30(flags);
writer.writePackedObject(parent);
writer.writePackedObject(name);
- if (flags & flagHasTypeParams != 0) {
+ if (flags & hasSourcePositionsFlag != 0) {
+ writer.writePackedUInt30(position + 1);
+ writer.writePackedUInt30(endPosition + 1);
+ }
+
+ if (flags & hasTypeParamsFlag != 0) {
writer.writePackedUInt30(typeParams.length);
for (var tp in typeParams) {
writer.writePackedObject(tp.name);
@@ -677,7 +690,7 @@
}
writer.writePackedUInt30(parameters.length);
if (flags &
- (flagHasOptionalPositionalParams | flagHasOptionalNamedParams) !=
+ (hasOptionalPositionalParamsFlag | hasOptionalNamedParamsFlag) !=
0) {
writer.writePackedUInt30(numRequiredParams);
}
@@ -692,8 +705,14 @@
final int flags = reader.readPackedUInt30();
final parent = reader.readPackedObject();
final name = reader.readPackedObject();
+ final position = ((flags & hasSourcePositionsFlag) != 0)
+ ? reader.readPackedUInt30() - 1
+ : TreeNode.noOffset;
+ final endPosition = ((flags & hasSourcePositionsFlag) != 0)
+ ? reader.readPackedUInt30() - 1
+ : TreeNode.noOffset;
List<NameAndType> typeParams;
- if ((flags & flagHasTypeParams) != 0) {
+ if ((flags & hasTypeParamsFlag) != 0) {
final int numTypeParams = reader.readPackedUInt30();
List<ObjectHandle> names = new List<ObjectHandle>.generate(
numTypeParams, (_) => reader.readPackedObject());
@@ -706,12 +725,12 @@
}
final numParams = reader.readPackedUInt30();
final numRequiredParams = (flags &
- (flagHasOptionalPositionalParams |
- flagHasOptionalNamedParams) !=
+ (hasOptionalPositionalParamsFlag |
+ hasOptionalNamedParamsFlag) !=
0)
? reader.readPackedUInt30()
: numParams;
- final numNamedParams = (flags & flagHasOptionalNamedParams != 0)
+ final numNamedParams = (flags & hasOptionalNamedParamsFlag != 0)
? (numParams - numRequiredParams)
: 0;
final List<NameAndType> parameters = new List<NameAndType>.generate(
@@ -719,14 +738,17 @@
(_) => new NameAndType(
reader.readPackedObject(), reader.readPackedObject()));
final returnType = reader.readPackedObject();
- return new ClosureDeclaration(parent, name, typeParams, numRequiredParams,
- numNamedParams, parameters, returnType);
+ return new ClosureDeclaration(parent, name, position, endPosition,
+ typeParams, numRequiredParams, numNamedParams, parameters, returnType);
}
@override
String toString() {
StringBuffer sb = new StringBuffer();
sb.write('Closure $parent::$name');
+ if (position != TreeNode.noOffset) {
+ sb.write(' pos = $position, end-pos = $endPosition');
+ }
if (typeParams.isNotEmpty) {
sb.write(' <${typeParams.join(', ')}>');
}
diff --git a/pkg/vm/lib/bytecode/gen_bytecode.dart b/pkg/vm/lib/bytecode/gen_bytecode.dart
index 216ac55..e100111 100644
--- a/pkg/vm/lib/bytecode/gen_bytecode.dart
+++ b/pkg/vm/lib/bytecode/gen_bytecode.dart
@@ -1618,6 +1618,15 @@
final savedLoopDepth = currentLoopDepth;
currentLoopDepth = 0;
+ int position = TreeNode.noOffset;
+ int endPosition = TreeNode.noOffset;
+ if (emitSourcePositions) {
+ position = (node is ast.FunctionDeclaration)
+ ? node.fileOffset
+ : function.fileOffset;
+ endPosition = function.fileEndOffset;
+ }
+
if (function.typeParameters.isNotEmpty) {
functionTypeParameters ??= new List<TypeParameter>();
functionTypeParameters.addAll(function.typeParameters);
@@ -1644,6 +1653,8 @@
objectTable
.getHandle(savedIsClosure ? parentFunction : enclosingMember),
objectTable.getNameHandle(null, name),
+ position,
+ endPosition,
function.typeParameters
.map((tp) => new NameAndType(
objectTable.getNameHandle(null, tp.name),
diff --git a/runtime/vm/compiler/frontend/bytecode_reader.cc b/runtime/vm/compiler/frontend/bytecode_reader.cc
index 602d55b..7ca1f85 100644
--- a/runtime/vm/compiler/frontend/bytecode_reader.cc
+++ b/runtime/vm/compiler/frontend/bytecode_reader.cc
@@ -352,9 +352,12 @@
void BytecodeReaderHelper::ReadClosureDeclaration(const Function& function,
intptr_t closureIndex) {
- const int kHasOptionalPositionalParams = 1 << 0;
- const int kHasOptionalNamedParams = 1 << 1;
- const int kHasTypeParams = 1 << 2;
+ // Closure flags, must be in sync with ClosureDeclaration constants in
+ // pkg/vm/lib/bytecode/declarations.dart.
+ const int kHasOptionalPositionalParamsFlag = 1 << 0;
+ const int kHasOptionalNamedParamsFlag = 1 << 1;
+ const int kHasTypeParamsFlag = 1 << 2;
+ const int kHasSourcePositionsFlag = 1 << 3;
const intptr_t flags = helper_->reader_.ReadUInt();
@@ -369,20 +372,27 @@
String& name = String::CheckedHandle(Z, ReadObject());
ASSERT(name.IsSymbol());
+ TokenPosition position = TokenPosition::kNoSource;
+ TokenPosition end_position = TokenPosition::kNoSource;
+ if ((flags & kHasSourcePositionsFlag) != 0) {
+ position = helper_->ReadPosition();
+ end_position = helper_->ReadPosition();
+ }
+
const Function& closure = Function::Handle(
- Z, Function::NewClosureFunction(name, Function::Cast(parent),
- TokenPosition::kNoSource));
+ Z, Function::NewClosureFunction(name, Function::Cast(parent), position));
closure.set_is_declared_in_bytecode(true);
+ closure.set_end_token_pos(end_position);
closures_->SetAt(closureIndex, closure);
- Type& signature_type =
- Type::Handle(Z, ReadFunctionSignature(
- closure, (flags & kHasOptionalPositionalParams) != 0,
- (flags & kHasOptionalNamedParams) != 0,
- (flags & kHasTypeParams) != 0,
- /* has_positional_param_names = */ true));
+ Type& signature_type = Type::Handle(
+ Z, ReadFunctionSignature(closure,
+ (flags & kHasOptionalPositionalParamsFlag) != 0,
+ (flags & kHasOptionalNamedParamsFlag) != 0,
+ (flags & kHasTypeParamsFlag) != 0,
+ /* has_positional_param_names = */ true));
closure.SetSignatureType(signature_type);
}
diff --git a/runtime/vm/constants_kbc.h b/runtime/vm/constants_kbc.h
index 8a26be6..a9aa1c7 100644
--- a/runtime/vm/constants_kbc.h
+++ b/runtime/vm/constants_kbc.h
@@ -749,7 +749,7 @@
// 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 = 7;
+ static const intptr_t kMaxSupportedBytecodeFormatVersion = 8;
enum Opcode {
#define DECLARE_BYTECODE(name, encoding, kind, op1, op2, op3) k##name,