[vm/bytecode] Add async/async*/sync* attributes to closures
Change-Id: Ibb0f202ada840ee112f46d5db3d8f9459817c358
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/106730
Reviewed-by: RĂ©gis Crelier <regis@google.com>
Reviewed-by: Ryan Macnak <rmacnak@google.com>
diff --git a/pkg/vm/lib/bytecode/dbc.dart b/pkg/vm/lib/bytecode/dbc.dart
index 244e800..e89f666 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 = 10;
+const int currentBytecodeFormatVersion = 11;
/// 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 58827b6..2519397 100644
--- a/pkg/vm/lib/bytecode/declarations.dart
+++ b/pkg/vm/lib/bytecode/declarations.dart
@@ -890,7 +890,11 @@
static const int hasOptionalNamedParamsFlag = 1 << 1;
static const int hasTypeParamsFlag = 1 << 2;
static const int hasSourcePositionsFlag = 1 << 3;
+ static const int isAsyncFlag = 1 << 4;
+ static const int isAsyncStarFlag = 1 << 5;
+ static const int isSyncStarFlag = 1 << 6;
+ final int flags;
final ObjectHandle parent;
final ObjectHandle name;
final int position;
@@ -903,6 +907,7 @@
ClosureCode code;
ClosureDeclaration(
+ this.flags,
this.parent,
this.name,
this.position,
@@ -914,20 +919,6 @@
this.returnType);
void write(BufferedWriter writer) {
- int flags = 0;
- if (numRequiredParams != parameters.length) {
- if (numNamedParams > 0) {
- flags |= hasOptionalNamedParamsFlag;
- } else {
- flags |= hasOptionalPositionalParamsFlag;
- }
- }
- if (typeParams.isNotEmpty) {
- flags |= hasTypeParamsFlag;
- }
- if (position != TreeNode.noOffset) {
- flags |= hasSourcePositionsFlag;
- }
writer.writePackedUInt30(flags);
writer.writePackedObject(parent);
writer.writePackedObject(name);
@@ -996,7 +987,7 @@
(_) => new NameAndType(
reader.readPackedObject(), reader.readPackedObject()));
final returnType = reader.readPackedObject();
- return new ClosureDeclaration(parent, name, position, endPosition,
+ return new ClosureDeclaration(flags, parent, name, position, endPosition,
typeParams, numRequiredParams, numNamedParams, parameters, returnType);
}
@@ -1004,6 +995,15 @@
String toString() {
final StringBuffer sb = new StringBuffer();
sb.write('Closure $parent::$name');
+ if ((flags & isAsyncFlag) != 0) {
+ sb.write(' async');
+ }
+ if ((flags & isAsyncStarFlag) != 0) {
+ sb.write(' async*');
+ }
+ if ((flags & isSyncStarFlag) != 0) {
+ sb.write(' sync*');
+ }
if (position != TreeNode.noOffset) {
sb.write(' pos = $position, end-pos = $endPosition');
}
diff --git a/pkg/vm/lib/bytecode/gen_bytecode.dart b/pkg/vm/lib/bytecode/gen_bytecode.dart
index 01426c5..d79d963 100644
--- a/pkg/vm/lib/bytecode/gen_bytecode.dart
+++ b/pkg/vm/lib/bytecode/gen_bytecode.dart
@@ -1852,7 +1852,8 @@
}
}
- int _genClosureBytecode(TreeNode node, String name, FunctionNode function) {
+ int _genClosureBytecode(
+ LocalFunction node, String name, FunctionNode function) {
_pushAssemblerState();
locals.enterScope(node);
@@ -1865,15 +1866,6 @@
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);
@@ -1890,27 +1882,8 @@
locals.sortedNamedParameters.forEach(_evaluateDefaultParameterValue);
final int closureIndex = closures.length;
- objectTable.declareClosure(function, enclosingMember, closureIndex);
- final List<NameAndType> parameters = function.positionalParameters
- .followedBy(function.namedParameters)
- .map((v) => new NameAndType(objectTable.getNameHandle(null, v.name),
- objectTable.getHandle(v.type)))
- .toList();
- final ClosureDeclaration closure = new ClosureDeclaration(
- objectTable
- .getHandle(savedIsClosure ? parentFunction : enclosingMember),
- objectTable.getNameHandle(null, name),
- position,
- endPosition,
- function.typeParameters
- .map((tp) => new NameAndType(
- objectTable.getNameHandle(null, tp.name),
- objectTable.getHandle(tp.bound)))
- .toList(),
- function.requiredParameterCount,
- function.namedParameters.length,
- parameters,
- objectTable.getHandle(function.returnType));
+ final closure = getClosureDeclaration(node, function, name, closureIndex,
+ savedIsClosure ? parentFunction : enclosingMember);
closures.add(closure);
final int closureFunctionIndex = cp.addClosureFunction(closureIndex);
@@ -1972,6 +1945,71 @@
return closureFunctionIndex;
}
+ ClosureDeclaration getClosureDeclaration(LocalFunction node,
+ FunctionNode function, String name, int closureIndex, TreeNode parent) {
+ objectTable.declareClosure(function, enclosingMember, closureIndex);
+
+ int flags = 0;
+ int position = TreeNode.noOffset;
+ int endPosition = TreeNode.noOffset;
+ if (emitSourcePositions) {
+ position = (node is ast.FunctionDeclaration)
+ ? node.fileOffset
+ : function.fileOffset;
+ endPosition = function.fileEndOffset;
+ if (position != TreeNode.noOffset) {
+ flags |= ClosureDeclaration.hasSourcePositionsFlag;
+ }
+ }
+
+ switch (function.dartAsyncMarker) {
+ case AsyncMarker.Async:
+ flags |= ClosureDeclaration.isAsyncFlag;
+ break;
+ case AsyncMarker.AsyncStar:
+ flags |= ClosureDeclaration.isAsyncStarFlag;
+ break;
+ case AsyncMarker.SyncStar:
+ flags |= ClosureDeclaration.isSyncStarFlag;
+ break;
+ default:
+ break;
+ }
+
+ final List<NameAndType> parameters = function.positionalParameters
+ .followedBy(function.namedParameters)
+ .map((v) => new NameAndType(objectTable.getNameHandle(null, v.name),
+ objectTable.getHandle(v.type)))
+ .toList();
+ if (function.requiredParameterCount != parameters.length) {
+ if (function.namedParameters.isNotEmpty) {
+ flags |= ClosureDeclaration.hasOptionalNamedParamsFlag;
+ } else {
+ flags |= ClosureDeclaration.hasOptionalPositionalParamsFlag;
+ }
+ }
+
+ final typeParams = function.typeParameters
+ .map((tp) => new NameAndType(objectTable.getNameHandle(null, tp.name),
+ objectTable.getHandle(tp.bound)))
+ .toList();
+ if (typeParams.isNotEmpty) {
+ flags |= ClosureDeclaration.hasTypeParamsFlag;
+ }
+
+ return new ClosureDeclaration(
+ flags,
+ objectTable.getHandle(parent),
+ objectTable.getNameHandle(null, name),
+ position,
+ endPosition,
+ typeParams,
+ function.requiredParameterCount,
+ function.namedParameters.length,
+ parameters,
+ objectTable.getHandle(function.returnType));
+ }
+
void _genSyncYieldingPrologue(FunctionNode function, Label continuationLabel,
int switchVarIndexInFrame) {
// switch_var = :await_jump_var
@@ -2045,7 +2083,7 @@
asm.emitStoreFieldTOS(cp.addInstanceField(closureContext));
}
- void _genClosure(TreeNode node, String name, FunctionNode function) {
+ void _genClosure(LocalFunction node, String name, FunctionNode function) {
final int closureFunctionIndex = _genClosureBytecode(node, name, function);
_genAllocateClosureInstance(node, closureFunctionIndex, function);
}
diff --git a/pkg/vm/testcases/bytecode/async.dart.expect b/pkg/vm/testcases/bytecode/async.dart.expect
index 32e7ee9..e142924 100644
--- a/pkg/vm/testcases/bytecode/async.dart.expect
+++ b/pkg/vm/testcases/bytecode/async.dart.expect
@@ -75,7 +75,7 @@
[38] = Reserved
[39] = EndClosureFunctionScope
}
-Closure #lib::asyncInFieldInitializer (field)::'<anonymous closure>' (dart:async::Future < dart:core::int > x) -> dart:async::Future < dart:core::Null >
+Closure #lib::asyncInFieldInitializer (field)::'<anonymous closure>' async (dart:async::Future < dart:core::int > x) -> dart:async::Future < dart:core::Null >
ClosureCode {
EntryFixed 2, 4
CheckStack 0
@@ -1708,7 +1708,7 @@
[38] = Reserved
[39] = EndClosureFunctionScope
}
-Closure #lib::closure::'nested' () -> dart:async::Future < dart:core::int >
+Closure #lib::closure::'nested' async () -> dart:async::Future < dart:core::int >
ClosureCode {
EntryFixed 1, 4
CheckStack 0
diff --git a/runtime/vm/compiler/frontend/bytecode_reader.cc b/runtime/vm/compiler/frontend/bytecode_reader.cc
index 5d3ba7d..c7f1d7a 100644
--- a/runtime/vm/compiler/frontend/bytecode_reader.cc
+++ b/runtime/vm/compiler/frontend/bytecode_reader.cc
@@ -472,6 +472,9 @@
const int kHasOptionalNamedParamsFlag = 1 << 1;
const int kHasTypeParamsFlag = 1 << 2;
const int kHasSourcePositionsFlag = 1 << 3;
+ const int kIsAsyncFlag = 1 << 4;
+ const int kIsAsyncStarFlag = 1 << 5;
+ const int kIsSyncStarFlag = 1 << 6;
const intptr_t flags = reader_.ReadUInt();
@@ -499,6 +502,19 @@
closure.set_is_declared_in_bytecode(true);
closure.set_end_token_pos(end_position);
+ if ((flags & kIsSyncStarFlag) != 0) {
+ closure.set_modifier(RawFunction::kSyncGen);
+ } else if ((flags & kIsAsyncFlag) != 0) {
+ closure.set_modifier(RawFunction::kAsync);
+ closure.set_is_inlinable(!FLAG_causal_async_stacks);
+ } else if ((flags & kIsAsyncStarFlag) != 0) {
+ closure.set_modifier(RawFunction::kAsyncGen);
+ closure.set_is_inlinable(!FLAG_causal_async_stacks);
+ }
+ if (Function::Cast(parent).IsAsyncOrGenerator()) {
+ closure.set_is_generated_body(true);
+ }
+
closures_->SetAt(closureIndex, closure);
Type& signature_type = Type::Handle(
diff --git a/runtime/vm/constants_kbc.h b/runtime/vm/constants_kbc.h
index 5c422d8..caac3a1 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 = 10;
+ static const intptr_t kMaxSupportedBytecodeFormatVersion = 11;
enum Opcode {
#define DECLARE_BYTECODE(name, encoding, kind, op1, op2, op3) k##name,
diff --git a/tools/VERSION b/tools/VERSION
index aa48b1b..831acfe 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -35,5 +35,5 @@
PATCH 3
PRERELEASE 0
PRERELEASE_PATCH 0
-ABI_VERSION 5
+ABI_VERSION 6
OLDEST_SUPPORTED_ABI_VERSION 3