[kernel,vm] Migrate vm transformations in package:kernel
TEST=existing Change-Id: I86dfda23fa32ecb924fa6c202e7142cb8a258dc6 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/192145 Commit-Queue: Johnni Winther <johnniwinther@google.com> Reviewed-by: Aske Simon Christensen <askesc@google.com>
This commit is contained in:
committed by
commit-bot@chromium.org
parent
a26a140d88
commit
9d80c4db57
@@ -1266,7 +1266,7 @@ class KernelTarget extends TargetImplementation {
|
||||
ticker.logMs("Evaluated constants");
|
||||
|
||||
backendTarget.performTransformationsOnProcedure(
|
||||
loader.coreTypes, loader.hierarchy, procedure,
|
||||
loader.coreTypes, loader.hierarchy, procedure, environmentDefines,
|
||||
logger: (String msg) => ticker.logMs(msg));
|
||||
}
|
||||
|
||||
|
||||
@@ -161,11 +161,11 @@ class CoreTypes {
|
||||
late final Constructor futureImplConstructor =
|
||||
index.getMember('dart:async', '_Future', '') as Constructor;
|
||||
|
||||
late final Member completeOnAsyncReturn =
|
||||
index.getTopLevelMember('dart:async', '_completeOnAsyncReturn');
|
||||
late final Procedure completeOnAsyncReturn = index.getTopLevelMember(
|
||||
'dart:async', '_completeOnAsyncReturn') as Procedure;
|
||||
|
||||
late final Member completeOnAsyncError =
|
||||
index.getTopLevelMember('dart:async', '_completeOnAsyncError');
|
||||
late final Procedure completeOnAsyncError = index.getTopLevelMember(
|
||||
'dart:async', '_completeOnAsyncError') as Procedure;
|
||||
|
||||
late final Library coreLibrary = index.getLibrary('dart:core');
|
||||
|
||||
|
||||
@@ -252,7 +252,7 @@ abstract class Target {
|
||||
// transformations.
|
||||
Map<String, String> environmentDefines,
|
||||
DiagnosticReporter diagnosticReporter,
|
||||
ReferenceFromIndex referenceFromIndex,
|
||||
ReferenceFromIndex? referenceFromIndex,
|
||||
{void logger(String msg),
|
||||
ChangedStructureNotifier changedStructureNotifier});
|
||||
|
||||
@@ -262,7 +262,12 @@ abstract class Target {
|
||||
/// purposes. It is illegal to modify any of the enclosing nodes of the
|
||||
/// procedure.
|
||||
void performTransformationsOnProcedure(
|
||||
CoreTypes coreTypes, ClassHierarchy hierarchy, Procedure procedure,
|
||||
CoreTypes coreTypes,
|
||||
ClassHierarchy hierarchy,
|
||||
Procedure procedure,
|
||||
// TODO(askesc): Consider how to generally pass compiler options to
|
||||
// transformations.
|
||||
Map<String, String> environmentDefines,
|
||||
{void Function(String msg)? logger}) {}
|
||||
|
||||
/// Whether a platform library may define a restricted type, such as `bool`,
|
||||
@@ -463,7 +468,7 @@ class NoneTarget extends Target {
|
||||
List<Library> libraries,
|
||||
Map<String, String> environmentDefines,
|
||||
DiagnosticReporter diagnosticReporter,
|
||||
ReferenceFromIndex referenceFromIndex,
|
||||
ReferenceFromIndex? referenceFromIndex,
|
||||
{void Function(String msg)? logger,
|
||||
ChangedStructureNotifier? changedStructureNotifier}) {}
|
||||
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
// 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.
|
||||
|
||||
// @dart = 2.9
|
||||
|
||||
library kernel.transformations.async;
|
||||
|
||||
import '../kernel.dart';
|
||||
@@ -83,7 +81,7 @@ class ExpressionLifter extends Transformer {
|
||||
|
||||
ExpressionLifter(this.continuationRewriter);
|
||||
|
||||
StaticTypeContext get _staticTypeContext =>
|
||||
StatefulStaticTypeContext get _staticTypeContext =>
|
||||
continuationRewriter.staticTypeContext;
|
||||
|
||||
Block blockOf(List<Statement> statements) {
|
||||
@@ -100,7 +98,7 @@ class ExpressionLifter extends Transformer {
|
||||
assert(statements.isEmpty);
|
||||
var saved = seenAwait;
|
||||
seenAwait = false;
|
||||
Expression result = expression.accept<TreeNode>(this);
|
||||
Expression result = transform(expression);
|
||||
outer.addAll(statements.reversed);
|
||||
statements.clear();
|
||||
seenAwait = seenAwait || saved;
|
||||
@@ -224,18 +222,18 @@ class ExpressionLifter extends Transformer {
|
||||
|
||||
TreeNode visitPropertySet(PropertySet expr) {
|
||||
return transformTreeNode(expr, () {
|
||||
expr.value = expr.value.accept<TreeNode>(this)..parent = expr;
|
||||
expr.receiver = expr.receiver.accept<TreeNode>(this)..parent = expr;
|
||||
expr.value = transform(expr.value)..parent = expr;
|
||||
expr.receiver = transform(expr.receiver)..parent = expr;
|
||||
});
|
||||
}
|
||||
|
||||
TreeNode visitArguments(Arguments args) {
|
||||
for (var named in args.named.reversed) {
|
||||
named.value = named.value.accept<TreeNode>(this)..parent = named;
|
||||
named.value = transform(named.value)..parent = named;
|
||||
}
|
||||
var positional = args.positional;
|
||||
for (var i = positional.length - 1; i >= 0; --i) {
|
||||
positional[i] = positional[i].accept<TreeNode>(this)..parent = args;
|
||||
positional[i] = transform(positional[i])..parent = args;
|
||||
}
|
||||
// Returns the arguments, which is assumed at the call sites because they do
|
||||
// not replace the arguments or set parent pointers.
|
||||
@@ -245,7 +243,7 @@ class ExpressionLifter extends Transformer {
|
||||
TreeNode visitMethodInvocation(MethodInvocation expr) {
|
||||
return transformTreeNode(expr, () {
|
||||
visitArguments(expr.arguments);
|
||||
expr.receiver = expr.receiver.accept<TreeNode>(this)..parent = expr;
|
||||
expr.receiver = transform(expr.receiver)..parent = expr;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -271,7 +269,7 @@ class ExpressionLifter extends Transformer {
|
||||
return transformTreeNode(expr, () {
|
||||
var expressions = expr.expressions;
|
||||
for (var i = expressions.length - 1; i >= 0; --i) {
|
||||
expressions[i] = expressions[i].accept<TreeNode>(this)..parent = expr;
|
||||
expressions[i] = transform(expressions[i])..parent = expr;
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -280,8 +278,7 @@ class ExpressionLifter extends Transformer {
|
||||
return transformTreeNode(expr, () {
|
||||
var expressions = expr.expressions;
|
||||
for (var i = expressions.length - 1; i >= 0; --i) {
|
||||
expressions[i] = expr.expressions[i].accept<TreeNode>(this)
|
||||
..parent = expr;
|
||||
expressions[i] = transform(expr.expressions[i])..parent = expr;
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -289,8 +286,8 @@ class ExpressionLifter extends Transformer {
|
||||
TreeNode visitMapLiteral(MapLiteral expr) {
|
||||
return transformTreeNode(expr, () {
|
||||
for (var entry in expr.entries.reversed) {
|
||||
entry.value = entry.value.accept<TreeNode>(this)..parent = entry;
|
||||
entry.key = entry.key.accept<TreeNode>(this)..parent = entry;
|
||||
entry.value = transform(entry.value)..parent = entry;
|
||||
entry.key = transform(entry.key)..parent = entry;
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -302,16 +299,15 @@ class ExpressionLifter extends Transformer {
|
||||
// Right is delimited because it is conditionally evaluated.
|
||||
var rightStatements = <Statement>[];
|
||||
seenAwait = false;
|
||||
expr.right =
|
||||
delimit(() => expr.right.accept<TreeNode>(this), rightStatements)
|
||||
..parent = expr;
|
||||
expr.right = delimit(() => transform(expr.right), rightStatements)
|
||||
..parent = expr;
|
||||
var rightAwait = seenAwait;
|
||||
|
||||
if (rightStatements.isEmpty) {
|
||||
// Easy case: right did not emit any statements.
|
||||
seenAwait = shouldName;
|
||||
return transformTreeNode(expr, () {
|
||||
expr.left = expr.left.accept<TreeNode>(this)..parent = expr;
|
||||
expr.left = transform(expr.left)..parent = expr;
|
||||
seenAwait = seenAwait || rightAwait;
|
||||
});
|
||||
}
|
||||
@@ -352,7 +348,7 @@ class ExpressionLifter extends Transformer {
|
||||
statements.add(new ExpressionStatement(new VariableSet(result, test)));
|
||||
|
||||
seenAwait = false;
|
||||
test.receiver = test.receiver.accept<TreeNode>(this)..parent = test;
|
||||
test.receiver = transform(test.receiver)..parent = test;
|
||||
|
||||
++nameIndex;
|
||||
seenAwait = seenAwait || rightAwait;
|
||||
@@ -368,7 +364,7 @@ class ExpressionLifter extends Transformer {
|
||||
|
||||
var thenStatements = <Statement>[];
|
||||
seenAwait = false;
|
||||
expr.then = delimit(() => expr.then.accept<TreeNode>(this), thenStatements)
|
||||
expr.then = delimit(() => transform(expr.then), thenStatements)
|
||||
..parent = expr;
|
||||
var thenAwait = seenAwait;
|
||||
|
||||
@@ -377,9 +373,9 @@ class ExpressionLifter extends Transformer {
|
||||
|
||||
var otherwiseStatements = <Statement>[];
|
||||
seenAwait = false;
|
||||
expr.otherwise = delimit(
|
||||
() => expr.otherwise.accept<TreeNode>(this), otherwiseStatements)
|
||||
..parent = expr;
|
||||
expr.otherwise =
|
||||
delimit(() => transform(expr.otherwise), otherwiseStatements)
|
||||
..parent = expr;
|
||||
var otherwiseAwait = seenAwait;
|
||||
|
||||
// Only one side of this branch will get executed at a time, so just make
|
||||
@@ -392,7 +388,7 @@ class ExpressionLifter extends Transformer {
|
||||
// Easy case: neither then nor otherwise emitted any statements.
|
||||
seenAwait = shouldName;
|
||||
return transformTreeNode(expr, () {
|
||||
expr.condition = expr.condition.accept<TreeNode>(this)..parent = expr;
|
||||
expr.condition = transform(expr.condition)..parent = expr;
|
||||
seenAwait = seenAwait || thenAwait || otherwiseAwait;
|
||||
});
|
||||
}
|
||||
@@ -416,7 +412,7 @@ class ExpressionLifter extends Transformer {
|
||||
statements.add(branch);
|
||||
|
||||
seenAwait = false;
|
||||
branch.condition = branch.condition.accept<TreeNode>(this)..parent = branch;
|
||||
branch.condition = transform(branch.condition)..parent = branch;
|
||||
|
||||
++nameIndex;
|
||||
seenAwait = seenAwait || thenAwait || otherwiseAwait;
|
||||
@@ -473,8 +469,7 @@ class ExpressionLifter extends Transformer {
|
||||
|
||||
seenAwait = false;
|
||||
var index = nameIndex;
|
||||
arguments.positional[0] = expr.operand.accept<TreeNode>(this)
|
||||
..parent = arguments;
|
||||
arguments.positional[0] = transform(expr.operand)..parent = arguments;
|
||||
|
||||
if (shouldName && index + 1 > nameIndex) nameIndex = index + 1;
|
||||
seenAwait = true;
|
||||
@@ -487,7 +482,7 @@ class ExpressionLifter extends Transformer {
|
||||
}
|
||||
|
||||
TreeNode visitLet(Let expr) {
|
||||
var body = expr.body.accept<TreeNode>(this);
|
||||
var body = transform(expr.body);
|
||||
|
||||
VariableDeclaration variable = expr.variable;
|
||||
if (seenAwait) {
|
||||
@@ -508,7 +503,7 @@ class ExpressionLifter extends Transformer {
|
||||
statements.add(variable);
|
||||
var index = nameIndex;
|
||||
seenAwait = false;
|
||||
variable.initializer = variable.initializer.accept<TreeNode>(this)
|
||||
variable.initializer = transform(variable.initializer!)
|
||||
..parent = variable;
|
||||
// Temporaries used in the initializer or the body are not live but the
|
||||
// temporary used for the body is.
|
||||
@@ -521,7 +516,7 @@ class ExpressionLifter extends Transformer {
|
||||
return transformTreeNode(expr, () {
|
||||
// The body has already been translated.
|
||||
expr.body = body..parent = expr;
|
||||
variable.initializer = variable.initializer.accept<TreeNode>(this)
|
||||
variable.initializer = transform(variable.initializer!)
|
||||
..parent = variable;
|
||||
});
|
||||
}
|
||||
@@ -535,17 +530,17 @@ class ExpressionLifter extends Transformer {
|
||||
|
||||
TreeNode visitBlockExpression(BlockExpression expr) {
|
||||
return transformTreeNode(expr, () {
|
||||
expr.value = expr.value.accept<TreeNode>(this)..parent = expr;
|
||||
expr.value = transform(expr.value)..parent = expr;
|
||||
List<Statement> body = <Statement>[];
|
||||
for (Statement stmt in expr.body.statements.reversed) {
|
||||
Statement translation = stmt.accept<TreeNode>(this);
|
||||
Statement? translation = _rewriteStatement(stmt);
|
||||
if (translation != null) body.add(translation);
|
||||
}
|
||||
expr.body = new Block(body.reversed.toList())..parent = expr;
|
||||
});
|
||||
}
|
||||
|
||||
TreeNode defaultStatement(Statement stmt) {
|
||||
Statement? _rewriteStatement(Statement stmt) {
|
||||
// This method translates a statement nested in an expression (e.g., in a
|
||||
// block expression). It produces a translated statement, a list of
|
||||
// statements which are side effects necessary for any await, and a flag
|
||||
@@ -570,4 +565,9 @@ class ExpressionLifter extends Transformer {
|
||||
statements.addAll(results.reversed);
|
||||
return null;
|
||||
}
|
||||
|
||||
TreeNode defaultStatement(Statement stmt) {
|
||||
throw new UnsupportedError(
|
||||
"Use _rewriteStatement to transform statement: ${stmt}");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
// 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.
|
||||
|
||||
// @dart = 2.9
|
||||
|
||||
library kernel.transformations.continuation;
|
||||
|
||||
import 'dart:math' as math;
|
||||
@@ -50,7 +48,7 @@ class ContinuationVariables {
|
||||
|
||||
void transformLibraries(
|
||||
TypeEnvironment typeEnvironment, List<Library> libraries,
|
||||
{bool productMode}) {
|
||||
{required bool productMode}) {
|
||||
var helper =
|
||||
new HelperNodes.fromCoreTypes(typeEnvironment.coreTypes, productMode);
|
||||
var rewriter = new RecursiveContinuationRewriter(
|
||||
@@ -62,7 +60,7 @@ void transformLibraries(
|
||||
|
||||
Component transformComponent(
|
||||
TypeEnvironment typeEnvironment, Component component,
|
||||
{bool productMode}) {
|
||||
{required bool productMode}) {
|
||||
var helper =
|
||||
new HelperNodes.fromCoreTypes(typeEnvironment.coreTypes, productMode);
|
||||
var rewriter = new RecursiveContinuationRewriter(
|
||||
@@ -72,7 +70,7 @@ Component transformComponent(
|
||||
|
||||
Procedure transformProcedure(
|
||||
TypeEnvironment typeEnvironment, Procedure procedure,
|
||||
{bool productMode}) {
|
||||
{required bool productMode}) {
|
||||
var helper =
|
||||
new HelperNodes.fromCoreTypes(typeEnvironment.coreTypes, productMode);
|
||||
var rewriter = new RecursiveContinuationRewriter(
|
||||
@@ -101,14 +99,14 @@ class RecursiveContinuationRewriter extends RemovingTransformer {
|
||||
return transform(node);
|
||||
}
|
||||
|
||||
visitField(Field node, TreeNode removalSentinel) {
|
||||
visitField(Field node, TreeNode? removalSentinel) {
|
||||
staticTypeContext.enterMember(node);
|
||||
final result = super.visitField(node, removalSentinel);
|
||||
staticTypeContext.leaveMember(node);
|
||||
return result;
|
||||
}
|
||||
|
||||
visitConstructor(Constructor node, TreeNode removalSentinel) {
|
||||
visitConstructor(Constructor node, TreeNode? removalSentinel) {
|
||||
staticTypeContext.enterMember(node);
|
||||
final result = super.visitConstructor(node, removalSentinel);
|
||||
staticTypeContext.leaveMember(node);
|
||||
@@ -116,7 +114,7 @@ class RecursiveContinuationRewriter extends RemovingTransformer {
|
||||
}
|
||||
|
||||
@override
|
||||
visitProcedure(Procedure node, TreeNode removalSentinel) {
|
||||
visitProcedure(Procedure node, TreeNode? removalSentinel) {
|
||||
staticTypeContext.enterMember(node);
|
||||
final result =
|
||||
node.isAbstract ? node : super.visitProcedure(node, removalSentinel);
|
||||
@@ -125,15 +123,15 @@ class RecursiveContinuationRewriter extends RemovingTransformer {
|
||||
}
|
||||
|
||||
@override
|
||||
visitLibrary(Library node, TreeNode removalSentinel) {
|
||||
visitLibrary(Library node, TreeNode? removalSentinel) {
|
||||
staticTypeContext.enterLibrary(node);
|
||||
Library result = super.visitLibrary(node, removalSentinel);
|
||||
Library result = super.visitLibrary(node, removalSentinel) as Library;
|
||||
staticTypeContext.leaveLibrary(node);
|
||||
return result;
|
||||
}
|
||||
|
||||
@override
|
||||
visitFunctionNode(FunctionNode node, TreeNode removalSentinel) {
|
||||
visitFunctionNode(FunctionNode node, TreeNode? removalSentinel) {
|
||||
switch (node.asyncMarker) {
|
||||
case AsyncMarker.Sync:
|
||||
case AsyncMarker.SyncYielding:
|
||||
@@ -149,13 +147,11 @@ class RecursiveContinuationRewriter extends RemovingTransformer {
|
||||
case AsyncMarker.AsyncStar:
|
||||
return new AsyncStarFunctionRewriter(helper, node, staticTypeContext)
|
||||
.rewrite();
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
TreeNode visitForInStatement(ForInStatement stmt, TreeNode removalSentinel) {
|
||||
TreeNode visitForInStatement(ForInStatement stmt, TreeNode? removalSentinel) {
|
||||
if (stmt.isAsync) {
|
||||
return super.visitForInStatement(stmt, removalSentinel);
|
||||
}
|
||||
@@ -193,7 +189,7 @@ class RecursiveContinuationRewriter extends RemovingTransformer {
|
||||
assert(const [
|
||||
Nullability.nonNullable,
|
||||
Nullability.legacy
|
||||
].contains(coreTypes.iterableGetIterator.function.returnType.nullability));
|
||||
].contains(coreTypes.iterableGetIterator.function!.returnType.nullability));
|
||||
|
||||
final DartType elementType = stmt.getElementType(staticTypeContext);
|
||||
final iteratorType = InterfaceType(
|
||||
@@ -271,18 +267,19 @@ abstract class ContinuationRewriterBase extends RecursiveContinuationRewriter {
|
||||
DartType elementTypeFromAsyncReturnType() =>
|
||||
elementTypeFromFutureOr(enclosingFunction.returnType);
|
||||
|
||||
Statement createContinuationPoint([Expression value]) {
|
||||
Statement createContinuationPoint([Expression? value]) {
|
||||
if (value == null) value = new NullLiteral();
|
||||
capturedTryDepth = math.max(capturedTryDepth, currentTryDepth);
|
||||
capturedCatchDepth = math.max(capturedCatchDepth, currentCatchDepth);
|
||||
return new YieldStatement(value, isNative: true);
|
||||
}
|
||||
|
||||
TreeNode visitTryCatch(TryCatch node, TreeNode removalSentinel) {
|
||||
TreeNode visitTryCatch(TryCatch node, TreeNode? removalSentinel) {
|
||||
// ignore: unnecessary_null_comparison
|
||||
if (node.body != null) {
|
||||
++currentTryDepth;
|
||||
node.body = transform(node.body);
|
||||
node.body?.parent = node;
|
||||
node.body.parent = node;
|
||||
--currentTryDepth;
|
||||
}
|
||||
|
||||
@@ -292,17 +289,19 @@ abstract class ContinuationRewriterBase extends RecursiveContinuationRewriter {
|
||||
return node;
|
||||
}
|
||||
|
||||
TreeNode visitTryFinally(TryFinally node, TreeNode removalSentinel) {
|
||||
TreeNode visitTryFinally(TryFinally node, TreeNode? removalSentinel) {
|
||||
// ignore: unnecessary_null_comparison
|
||||
if (node.body != null) {
|
||||
++currentTryDepth;
|
||||
node.body = transform(node.body);
|
||||
node.body?.parent = node;
|
||||
node.body.parent = node;
|
||||
--currentTryDepth;
|
||||
}
|
||||
// ignore: unnecessary_null_comparison
|
||||
if (node.finalizer != null) {
|
||||
++currentCatchDepth;
|
||||
node.finalizer = transform(node.finalizer);
|
||||
node.finalizer?.parent = node;
|
||||
node.finalizer.parent = node;
|
||||
--currentCatchDepth;
|
||||
}
|
||||
return node;
|
||||
@@ -335,7 +334,7 @@ abstract class ContinuationRewriterBase extends RecursiveContinuationRewriter {
|
||||
// unique to given sub-closure to prevent shared variables being overwritten.
|
||||
class ShadowRewriter extends Transformer {
|
||||
final FunctionNode enclosingFunction;
|
||||
Map<VariableDeclaration, VariableDeclaration> _shadowedParameters = {};
|
||||
Map<VariableDeclaration, VariableDeclaration?> _shadowedParameters = {};
|
||||
|
||||
ShadowRewriter(this.enclosingFunction) {
|
||||
for (final parameter in enclosingFunction.positionalParameters
|
||||
@@ -348,32 +347,33 @@ class ShadowRewriter extends Transformer {
|
||||
|
||||
// Return all used parameters.
|
||||
Iterable<VariableDeclaration> get shadowedParameters =>
|
||||
_shadowedParameters.values.where((e) => e != null);
|
||||
_shadowedParameters.values.whereType<VariableDeclaration>();
|
||||
|
||||
VariableDeclaration _rewrite(VariableDeclaration variable) {
|
||||
if (_shadowedParameters.containsKey(variable)) {
|
||||
// Fill in placeholder.
|
||||
if (_shadowedParameters[variable] == null) {
|
||||
_shadowedParameters[variable] = VariableDeclaration(
|
||||
VariableDeclaration? placeholder = _shadowedParameters[variable];
|
||||
if (placeholder == null) {
|
||||
placeholder = _shadowedParameters[variable] = VariableDeclaration(
|
||||
variable.name,
|
||||
type: variable.type,
|
||||
initializer: VariableGet(variable),
|
||||
);
|
||||
}
|
||||
variable = _shadowedParameters[variable];
|
||||
variable = placeholder;
|
||||
}
|
||||
return variable;
|
||||
}
|
||||
|
||||
@override
|
||||
TreeNode visitVariableGet(VariableGet node) {
|
||||
node = super.visitVariableGet(node);
|
||||
node = super.visitVariableGet(node) as VariableGet;
|
||||
return node..variable = _rewrite(node.variable);
|
||||
}
|
||||
|
||||
@override
|
||||
TreeNode visitVariableSet(VariableSet node) {
|
||||
node = super.visitVariableSet(node);
|
||||
node = super.visitVariableSet(node) as VariableSet;
|
||||
return node..variable = _rewrite(node.variable);
|
||||
}
|
||||
}
|
||||
@@ -401,8 +401,8 @@ class SyncStarFunctionRewriter extends ContinuationRewriterBase {
|
||||
// initialised to the original parameter values) and rewrite
|
||||
// the body to use these variables instead.
|
||||
final shadowRewriter = ShadowRewriter(enclosingFunction);
|
||||
enclosingFunction.body =
|
||||
enclosingFunction.body.accept<TreeNode>(shadowRewriter);
|
||||
enclosingFunction.body = shadowRewriter.transform(enclosingFunction.body!)
|
||||
..parent = enclosingFunction;
|
||||
|
||||
// TODO(cskau): Figure out why inlining this below causes segfaults.
|
||||
// Maybe related to http://dartbug.com/41596 ?
|
||||
@@ -464,9 +464,8 @@ class SyncStarFunctionRewriter extends ContinuationRewriterBase {
|
||||
ContinuationRewriterBase.elementTypeFrom(
|
||||
helper.iterableClass, enclosingFunction.returnType)
|
||||
]))),
|
||||
]);
|
||||
|
||||
enclosingFunction.body.parent = enclosingFunction;
|
||||
])
|
||||
..parent = enclosingFunction;
|
||||
enclosingFunction.asyncMarker = AsyncMarker.Sync;
|
||||
|
||||
return enclosingFunction;
|
||||
@@ -478,13 +477,13 @@ class SyncStarFunctionRewriter extends ContinuationRewriterBase {
|
||||
// :iterator.isYieldEach=
|
||||
// and return `true` as long as it did something and `false` when it's done.
|
||||
return new Block(<Statement>[
|
||||
transform(enclosingFunction.body),
|
||||
transform(enclosingFunction.body!),
|
||||
new ReturnStatement(new BoolLiteral(false))
|
||||
..fileOffset = enclosingFunction.fileEndOffset
|
||||
]);
|
||||
}
|
||||
|
||||
visitYieldStatement(YieldStatement node, TreeNode removalSentinel) {
|
||||
visitYieldStatement(YieldStatement node, TreeNode? removalSentinel) {
|
||||
Expression transformedExpression = transform(node.expression);
|
||||
|
||||
var statements = <Statement>[];
|
||||
@@ -508,7 +507,7 @@ class SyncStarFunctionRewriter extends ContinuationRewriterBase {
|
||||
}
|
||||
|
||||
TreeNode visitReturnStatement(
|
||||
ReturnStatement node, TreeNode removalSentinel) {
|
||||
ReturnStatement node, TreeNode? removalSentinel) {
|
||||
// sync* functions cannot return a value.
|
||||
assert(node.expression == null || node.expression is NullLiteral);
|
||||
node.expression = new BoolLiteral(false)..parent = node;
|
||||
@@ -526,12 +525,12 @@ abstract class AsyncRewriterBase extends ContinuationRewriterBase {
|
||||
// :async_op_error has type (Object e, StackTrace s) -> dynamic
|
||||
final VariableDeclaration catchErrorContinuationVariable;
|
||||
|
||||
LabeledStatement labeledBody;
|
||||
LabeledStatement? labeledBody;
|
||||
|
||||
ExpressionLifter expressionRewriter;
|
||||
ExpressionLifter? expressionRewriter;
|
||||
|
||||
AsyncRewriterBase(HelperNodes helper, FunctionNode enclosingFunction,
|
||||
StaticTypeContext staticTypeContext)
|
||||
StatefulStaticTypeContext staticTypeContext)
|
||||
: nestedClosureVariable = VariableDeclaration(
|
||||
ContinuationVariables.asyncOp,
|
||||
type: FunctionType([
|
||||
@@ -566,7 +565,7 @@ abstract class AsyncRewriterBase extends ContinuationRewriterBase {
|
||||
// modified <node.body>;
|
||||
// }
|
||||
final parameters = <VariableDeclaration>[
|
||||
expressionRewriter.asyncResult,
|
||||
expressionRewriter!.asyncResult,
|
||||
new VariableDeclaration(ContinuationVariables.exceptionParam),
|
||||
new VariableDeclaration(ContinuationVariables.stackTraceParam),
|
||||
];
|
||||
@@ -587,12 +586,12 @@ abstract class AsyncRewriterBase extends ContinuationRewriterBase {
|
||||
// TODO(kustermann): If we didn't need any variables we should not emit
|
||||
// these.
|
||||
statements.addAll(variableDeclarations());
|
||||
statements.addAll(expressionRewriter.variables);
|
||||
statements.addAll(expressionRewriter!.variables);
|
||||
|
||||
// Now add the closure function itself.
|
||||
final closureFunction =
|
||||
new FunctionDeclaration(nestedClosureVariable, function)
|
||||
..fileOffset = enclosingFunction.parent.fileOffset;
|
||||
..fileOffset = enclosingFunction.parent!.fileOffset;
|
||||
statements.add(closureFunction);
|
||||
|
||||
// :async_op_then = _asyncThenWrapperHelper(asyncBody);
|
||||
@@ -615,7 +614,7 @@ abstract class AsyncRewriterBase extends ContinuationRewriterBase {
|
||||
Statement buildWrappedBody() {
|
||||
++currentTryDepth;
|
||||
labeledBody = new LabeledStatement(null);
|
||||
labeledBody.body = visitDelimited(enclosingFunction.body)
|
||||
labeledBody!.body = visitDelimited(enclosingFunction.body!)
|
||||
..parent = labeledBody;
|
||||
--currentTryDepth;
|
||||
|
||||
@@ -625,7 +624,7 @@ abstract class AsyncRewriterBase extends ContinuationRewriterBase {
|
||||
helper.coreTypes.stackTraceRawType(staticTypeContext.nonNullable));
|
||||
|
||||
return new TryCatch(
|
||||
buildReturn(labeledBody),
|
||||
buildReturn(labeledBody!),
|
||||
<Catch>[
|
||||
new Catch(
|
||||
exceptionVariable,
|
||||
@@ -638,22 +637,22 @@ abstract class AsyncRewriterBase extends ContinuationRewriterBase {
|
||||
);
|
||||
}
|
||||
|
||||
Statement buildCatchBody(
|
||||
Statement exceptionVariable, Statement stackTraceVariable);
|
||||
Statement buildCatchBody(VariableDeclaration exceptionVariable,
|
||||
VariableDeclaration stackTraceVariable);
|
||||
|
||||
Statement buildReturn(Statement body);
|
||||
|
||||
List<Statement> statements = <Statement>[];
|
||||
|
||||
TreeNode visitExpressionStatement(
|
||||
ExpressionStatement stmt, TreeNode removalSentinel) {
|
||||
stmt.expression = expressionRewriter.rewrite(stmt.expression, statements)
|
||||
ExpressionStatement stmt, TreeNode? removalSentinel) {
|
||||
stmt.expression = expressionRewriter!.rewrite(stmt.expression, statements)
|
||||
..parent = stmt;
|
||||
statements.add(stmt);
|
||||
return removalSentinel;
|
||||
return removalSentinel ?? EmptyStatement();
|
||||
}
|
||||
|
||||
TreeNode visitBlock(Block stmt, TreeNode removalSentinel) {
|
||||
TreeNode visitBlock(Block stmt, TreeNode? removalSentinel) {
|
||||
var saved = statements;
|
||||
statements = <Statement>[];
|
||||
for (var statement in stmt.statements) {
|
||||
@@ -661,15 +660,15 @@ abstract class AsyncRewriterBase extends ContinuationRewriterBase {
|
||||
}
|
||||
saved.add(new Block(statements));
|
||||
statements = saved;
|
||||
return removalSentinel;
|
||||
return removalSentinel ?? EmptyStatement();
|
||||
}
|
||||
|
||||
TreeNode visitEmptyStatement(EmptyStatement stmt, TreeNode removalSentinel) {
|
||||
TreeNode visitEmptyStatement(EmptyStatement stmt, TreeNode? removalSentinel) {
|
||||
statements.add(stmt);
|
||||
return removalSentinel;
|
||||
return removalSentinel ?? EmptyStatement();
|
||||
}
|
||||
|
||||
TreeNode visitAssertBlock(AssertBlock stmt, TreeNode removalSentinel) {
|
||||
TreeNode visitAssertBlock(AssertBlock stmt, TreeNode? removalSentinel) {
|
||||
var saved = statements;
|
||||
statements = <Statement>[];
|
||||
for (var statement in stmt.statements) {
|
||||
@@ -677,26 +676,26 @@ abstract class AsyncRewriterBase extends ContinuationRewriterBase {
|
||||
}
|
||||
saved.add(new Block(statements));
|
||||
statements = saved;
|
||||
return removalSentinel;
|
||||
return removalSentinel ?? EmptyStatement();
|
||||
}
|
||||
|
||||
TreeNode visitAssertStatement(
|
||||
AssertStatement stmt, TreeNode removalSentinel) {
|
||||
AssertStatement stmt, TreeNode? removalSentinel) {
|
||||
var condEffects = <Statement>[];
|
||||
var cond = expressionRewriter.rewrite(stmt.condition, condEffects);
|
||||
var cond = expressionRewriter!.rewrite(stmt.condition, condEffects);
|
||||
if (stmt.message == null) {
|
||||
stmt.condition = cond..parent = stmt;
|
||||
// If the translation of the condition produced a non-empty list of
|
||||
// statements, ensure they are guarded by whether asserts are enabled.
|
||||
statements.add(
|
||||
condEffects.isEmpty ? stmt : new AssertBlock(condEffects..add(stmt)));
|
||||
return removalSentinel;
|
||||
return removalSentinel ?? EmptyStatement();
|
||||
}
|
||||
|
||||
// The translation depends on the translation of the message, by cases.
|
||||
Statement result;
|
||||
var msgEffects = <Statement>[];
|
||||
stmt.message = expressionRewriter.rewrite(stmt.message, msgEffects)
|
||||
stmt.message = expressionRewriter!.rewrite(stmt.message!, msgEffects)
|
||||
..parent = stmt;
|
||||
if (condEffects.isEmpty) {
|
||||
if (msgEffects.isEmpty) {
|
||||
@@ -737,7 +736,7 @@ abstract class AsyncRewriterBase extends ContinuationRewriterBase {
|
||||
result = new AssertBlock(condEffects);
|
||||
}
|
||||
statements.add(result);
|
||||
return removalSentinel;
|
||||
return removalSentinel ?? EmptyStatement();
|
||||
}
|
||||
|
||||
Statement visitDelimited(Statement stmt) {
|
||||
@@ -750,22 +749,22 @@ abstract class AsyncRewriterBase extends ContinuationRewriterBase {
|
||||
return result;
|
||||
}
|
||||
|
||||
Statement visitLabeledStatement(
|
||||
LabeledStatement stmt, TreeNode removalSentinel) {
|
||||
TreeNode visitLabeledStatement(
|
||||
LabeledStatement stmt, TreeNode? removalSentinel) {
|
||||
stmt.body = visitDelimited(stmt.body)..parent = stmt;
|
||||
statements.add(stmt);
|
||||
return removalSentinel;
|
||||
return removalSentinel ?? EmptyStatement();
|
||||
}
|
||||
|
||||
Statement visitBreakStatement(BreakStatement stmt, TreeNode removalSentinel) {
|
||||
TreeNode visitBreakStatement(BreakStatement stmt, TreeNode? removalSentinel) {
|
||||
statements.add(stmt);
|
||||
return removalSentinel;
|
||||
return removalSentinel ?? EmptyStatement();
|
||||
}
|
||||
|
||||
TreeNode visitWhileStatement(WhileStatement stmt, TreeNode removalSentinel) {
|
||||
TreeNode visitWhileStatement(WhileStatement stmt, TreeNode? removalSentinel) {
|
||||
Statement body = visitDelimited(stmt.body);
|
||||
List<Statement> effects = <Statement>[];
|
||||
Expression cond = expressionRewriter.rewrite(stmt.condition, effects);
|
||||
Expression cond = expressionRewriter!.rewrite(stmt.condition, effects);
|
||||
if (effects.isEmpty) {
|
||||
stmt.condition = cond..parent = stmt;
|
||||
stmt.body = body..parent = stmt;
|
||||
@@ -788,13 +787,13 @@ abstract class AsyncRewriterBase extends ContinuationRewriterBase {
|
||||
stmt.body = new Block(effects)..parent = stmt;
|
||||
statements.add(labeled);
|
||||
}
|
||||
return removalSentinel;
|
||||
return removalSentinel ?? EmptyStatement();
|
||||
}
|
||||
|
||||
TreeNode visitDoStatement(DoStatement stmt, TreeNode removalSentinel) {
|
||||
TreeNode visitDoStatement(DoStatement stmt, TreeNode? removalSentinel) {
|
||||
Statement body = visitDelimited(stmt.body);
|
||||
List<Statement> effects = <Statement>[];
|
||||
stmt.condition = expressionRewriter.rewrite(stmt.condition, effects)
|
||||
stmt.condition = expressionRewriter!.rewrite(stmt.condition, effects)
|
||||
..parent = stmt;
|
||||
if (effects.isNotEmpty) {
|
||||
// The condition rewrote to a non-empty sequence of statements S* and
|
||||
@@ -807,44 +806,43 @@ abstract class AsyncRewriterBase extends ContinuationRewriterBase {
|
||||
}
|
||||
stmt.body = body..parent = stmt;
|
||||
statements.add(stmt);
|
||||
return removalSentinel;
|
||||
return removalSentinel ?? EmptyStatement();
|
||||
}
|
||||
|
||||
TreeNode visitForStatement(ForStatement stmt, TreeNode removalSentinel) {
|
||||
TreeNode visitForStatement(ForStatement stmt, TreeNode? removalSentinel) {
|
||||
// Because of for-loop scoping and variable capture, it is tricky to deal
|
||||
// with await in the loop's variable initializers or update expressions.
|
||||
bool isSimple = true;
|
||||
int length = stmt.variables.length;
|
||||
List<List<Statement>> initEffects =
|
||||
new List<List<Statement>>.filled(length, null);
|
||||
for (int i = 0; i < length; ++i) {
|
||||
new List<List<Statement>>.generate(length, (int i) {
|
||||
VariableDeclaration decl = stmt.variables[i];
|
||||
initEffects[i] = <Statement>[];
|
||||
List<Statement> statements = <Statement>[];
|
||||
if (decl.initializer != null) {
|
||||
decl.initializer = expressionRewriter.rewrite(
|
||||
decl.initializer, initEffects[i])
|
||||
..parent = decl;
|
||||
decl.initializer = expressionRewriter!
|
||||
.rewrite(decl.initializer!, statements)
|
||||
..parent = decl;
|
||||
}
|
||||
isSimple = isSimple && initEffects[i].isEmpty;
|
||||
}
|
||||
isSimple = isSimple && statements.isEmpty;
|
||||
return statements;
|
||||
});
|
||||
|
||||
length = stmt.updates.length;
|
||||
List<List<Statement>> updateEffects =
|
||||
new List<List<Statement>>.filled(length, null);
|
||||
for (int i = 0; i < length; ++i) {
|
||||
updateEffects[i] = <Statement>[];
|
||||
stmt.updates[i] = expressionRewriter.rewrite(
|
||||
stmt.updates[i], updateEffects[i])
|
||||
new List<List<Statement>>.generate(length, (int i) {
|
||||
List<Statement> statements = <Statement>[];
|
||||
stmt.updates[i] = expressionRewriter!.rewrite(stmt.updates[i], statements)
|
||||
..parent = stmt;
|
||||
isSimple = isSimple && updateEffects[i].isEmpty;
|
||||
}
|
||||
isSimple = isSimple && statements.isEmpty;
|
||||
return statements;
|
||||
});
|
||||
|
||||
Statement body = visitDelimited(stmt.body);
|
||||
Expression cond = stmt.condition;
|
||||
List<Statement> condEffects;
|
||||
Expression? cond = stmt.condition;
|
||||
List<Statement>? condEffects;
|
||||
if (cond != null) {
|
||||
condEffects = <Statement>[];
|
||||
cond = expressionRewriter.rewrite(stmt.condition, condEffects);
|
||||
cond = expressionRewriter!.rewrite(stmt.condition!, condEffects);
|
||||
}
|
||||
|
||||
if (isSimple) {
|
||||
@@ -860,11 +858,11 @@ abstract class AsyncRewriterBase extends ContinuationRewriterBase {
|
||||
// No condition in a for loop is the same as true.
|
||||
stmt.condition = null;
|
||||
condEffects
|
||||
.add(new IfStatement(cond, body, new BreakStatement(labeled)));
|
||||
.add(new IfStatement(cond!, body, new BreakStatement(labeled)));
|
||||
stmt.body = new Block(condEffects)..parent = stmt;
|
||||
statements.add(labeled);
|
||||
}
|
||||
return removalSentinel;
|
||||
return removalSentinel ?? EmptyStatement();
|
||||
}
|
||||
|
||||
// If the rewrite of the initializer or update expressions produces a
|
||||
@@ -920,7 +918,7 @@ abstract class AsyncRewriterBase extends ContinuationRewriterBase {
|
||||
if (decl.initializer != null) {
|
||||
initializers.addAll(initEffects[i]);
|
||||
initializers.add(
|
||||
new ExpressionStatement(new VariableSet(decl, decl.initializer)));
|
||||
new ExpressionStatement(new VariableSet(decl, decl.initializer!)));
|
||||
decl.initializer = null;
|
||||
}
|
||||
updates.add(new ExpressionStatement(
|
||||
@@ -939,7 +937,7 @@ abstract class AsyncRewriterBase extends ContinuationRewriterBase {
|
||||
|
||||
LabeledStatement labeled = new LabeledStatement(null);
|
||||
if (cond != null) {
|
||||
loopBody.addAll(condEffects);
|
||||
loopBody.addAll(condEffects!);
|
||||
} else {
|
||||
cond = new BoolLiteral(true);
|
||||
}
|
||||
@@ -951,10 +949,10 @@ abstract class AsyncRewriterBase extends ContinuationRewriterBase {
|
||||
statements.add(new Block(<Statement>[]
|
||||
..addAll(temps)
|
||||
..add(labeled)));
|
||||
return removalSentinel;
|
||||
return removalSentinel ?? EmptyStatement();
|
||||
}
|
||||
|
||||
TreeNode visitForInStatement(ForInStatement stmt, TreeNode removalSentinel) {
|
||||
TreeNode visitForInStatement(ForInStatement stmt, TreeNode? removalSentinel) {
|
||||
if (stmt.isAsync) {
|
||||
// Transform
|
||||
//
|
||||
@@ -1037,7 +1035,7 @@ abstract class AsyncRewriterBase extends ContinuationRewriterBase {
|
||||
new Name('current'),
|
||||
helper.streamIteratorCurrent)
|
||||
..fileOffset = stmt.bodyOffset;
|
||||
valueVariable.initializer.parent = valueVariable;
|
||||
valueVariable.initializer!.parent = valueVariable;
|
||||
|
||||
var whileBody = new Block(<Statement>[valueVariable, stmt.body]);
|
||||
var tryBody = new WhileStatement(whileCondition, whileBody);
|
||||
@@ -1063,17 +1061,17 @@ abstract class AsyncRewriterBase extends ContinuationRewriterBase {
|
||||
|
||||
var block = new Block(
|
||||
<Statement>[streamVariable, forIteratorVariable, tryFinally]);
|
||||
transform(block);
|
||||
return removalSentinel;
|
||||
transform<Statement>(block);
|
||||
return removalSentinel ?? EmptyStatement();
|
||||
} else {
|
||||
super.visitForInStatement(stmt, removalSentinel);
|
||||
return removalSentinel;
|
||||
return removalSentinel ?? EmptyStatement();
|
||||
}
|
||||
}
|
||||
|
||||
TreeNode visitSwitchStatement(
|
||||
SwitchStatement stmt, TreeNode removalSentinel) {
|
||||
stmt.expression = expressionRewriter.rewrite(stmt.expression, statements)
|
||||
SwitchStatement stmt, TreeNode? removalSentinel) {
|
||||
stmt.expression = expressionRewriter!.rewrite(stmt.expression, statements)
|
||||
..parent = stmt;
|
||||
for (var switchCase in stmt.cases) {
|
||||
// Expressions in switch cases cannot contain await so they do not need to
|
||||
@@ -1081,27 +1079,27 @@ abstract class AsyncRewriterBase extends ContinuationRewriterBase {
|
||||
switchCase.body = visitDelimited(switchCase.body)..parent = switchCase;
|
||||
}
|
||||
statements.add(stmt);
|
||||
return removalSentinel;
|
||||
return removalSentinel ?? EmptyStatement();
|
||||
}
|
||||
|
||||
TreeNode visitContinueSwitchStatement(
|
||||
ContinueSwitchStatement stmt, TreeNode removalSentinel) {
|
||||
ContinueSwitchStatement stmt, TreeNode? removalSentinel) {
|
||||
statements.add(stmt);
|
||||
return removalSentinel;
|
||||
return removalSentinel ?? EmptyStatement();
|
||||
}
|
||||
|
||||
TreeNode visitIfStatement(IfStatement stmt, TreeNode removalSentinel) {
|
||||
stmt.condition = expressionRewriter.rewrite(stmt.condition, statements)
|
||||
TreeNode visitIfStatement(IfStatement stmt, TreeNode? removalSentinel) {
|
||||
stmt.condition = expressionRewriter!.rewrite(stmt.condition, statements)
|
||||
..parent = stmt;
|
||||
stmt.then = visitDelimited(stmt.then)..parent = stmt;
|
||||
if (stmt.otherwise != null) {
|
||||
stmt.otherwise = visitDelimited(stmt.otherwise)..parent = stmt;
|
||||
stmt.otherwise = visitDelimited(stmt.otherwise!)..parent = stmt;
|
||||
}
|
||||
statements.add(stmt);
|
||||
return removalSentinel;
|
||||
return removalSentinel ?? EmptyStatement();
|
||||
}
|
||||
|
||||
TreeNode visitTryCatch(TryCatch stmt, TreeNode removalSentinel) {
|
||||
TreeNode visitTryCatch(TryCatch stmt, TreeNode? removalSentinel) {
|
||||
++currentTryDepth;
|
||||
stmt.body = visitDelimited(stmt.body)..parent = stmt;
|
||||
--currentTryDepth;
|
||||
@@ -1112,10 +1110,10 @@ abstract class AsyncRewriterBase extends ContinuationRewriterBase {
|
||||
}
|
||||
--currentCatchDepth;
|
||||
statements.add(stmt);
|
||||
return removalSentinel;
|
||||
return removalSentinel ?? EmptyStatement();
|
||||
}
|
||||
|
||||
TreeNode visitTryFinally(TryFinally stmt, TreeNode removalSentinel) {
|
||||
TreeNode visitTryFinally(TryFinally stmt, TreeNode? removalSentinel) {
|
||||
++currentTryDepth;
|
||||
stmt.body = visitDelimited(stmt.body)..parent = stmt;
|
||||
--currentTryDepth;
|
||||
@@ -1123,43 +1121,43 @@ abstract class AsyncRewriterBase extends ContinuationRewriterBase {
|
||||
stmt.finalizer = visitDelimited(stmt.finalizer)..parent = stmt;
|
||||
--currentCatchDepth;
|
||||
statements.add(stmt);
|
||||
return removalSentinel;
|
||||
return removalSentinel ?? EmptyStatement();
|
||||
}
|
||||
|
||||
TreeNode visitYieldStatement(YieldStatement stmt, TreeNode removalSentinel) {
|
||||
stmt.expression = expressionRewriter.rewrite(stmt.expression, statements)
|
||||
TreeNode visitYieldStatement(YieldStatement stmt, TreeNode? removalSentinel) {
|
||||
stmt.expression = expressionRewriter!.rewrite(stmt.expression, statements)
|
||||
..parent = stmt;
|
||||
statements.add(stmt);
|
||||
return removalSentinel;
|
||||
return removalSentinel ?? EmptyStatement();
|
||||
}
|
||||
|
||||
TreeNode visitVariableDeclaration(
|
||||
VariableDeclaration stmt, TreeNode removalSentinel) {
|
||||
VariableDeclaration stmt, TreeNode? removalSentinel) {
|
||||
if (stmt.initializer != null) {
|
||||
stmt.initializer = expressionRewriter.rewrite(
|
||||
stmt.initializer, statements)
|
||||
..parent = stmt;
|
||||
stmt.initializer = expressionRewriter!
|
||||
.rewrite(stmt.initializer!, statements)
|
||||
..parent = stmt;
|
||||
}
|
||||
statements.add(stmt);
|
||||
return removalSentinel;
|
||||
return removalSentinel ?? EmptyStatement();
|
||||
}
|
||||
|
||||
TreeNode visitFunctionDeclaration(
|
||||
FunctionDeclaration stmt, TreeNode removalSentinel) {
|
||||
stmt.function = transform(stmt.function)..parent = stmt;
|
||||
FunctionDeclaration stmt, TreeNode? removalSentinel) {
|
||||
stmt.function = transform(stmt.function!)..parent = stmt;
|
||||
statements.add(stmt);
|
||||
return removalSentinel;
|
||||
return removalSentinel ?? EmptyStatement();
|
||||
}
|
||||
|
||||
defaultExpression(TreeNode node, TreeNode removalSentinel) =>
|
||||
defaultExpression(TreeNode node, TreeNode? removalSentinel) =>
|
||||
throw 'unreachable $node';
|
||||
}
|
||||
|
||||
class AsyncStarFunctionRewriter extends AsyncRewriterBase {
|
||||
VariableDeclaration controllerVariable;
|
||||
VariableDeclaration? controllerVariable;
|
||||
|
||||
AsyncStarFunctionRewriter(HelperNodes helper, FunctionNode enclosingFunction,
|
||||
StaticTypeContext staticTypeContext)
|
||||
StatefulStaticTypeContext staticTypeContext)
|
||||
: super(helper, enclosingFunction, staticTypeContext);
|
||||
|
||||
FunctionNode rewrite() {
|
||||
@@ -1172,7 +1170,7 @@ class AsyncStarFunctionRewriter extends AsyncRewriterBase {
|
||||
ContinuationVariables.controller,
|
||||
type: new InterfaceType(helper.asyncStarStreamControllerClass,
|
||||
staticTypeContext.nullable, [elementType]));
|
||||
statements.add(controllerVariable);
|
||||
statements.add(controllerVariable!);
|
||||
|
||||
// dynamic :controller_stream;
|
||||
VariableDeclaration controllerStreamVariable =
|
||||
@@ -1189,11 +1187,11 @@ class AsyncStarFunctionRewriter extends AsyncRewriterBase {
|
||||
helper.asyncStarStreamControllerConstructor, arguments)
|
||||
..fileOffset = enclosingFunction.fileOffset;
|
||||
var setController = new ExpressionStatement(
|
||||
new VariableSet(controllerVariable, buildController));
|
||||
new VariableSet(controllerVariable!, buildController));
|
||||
statements.add(setController);
|
||||
|
||||
// :controller_stream = :controller.stream;
|
||||
var completerGet = new VariableGet(controllerVariable);
|
||||
var completerGet = new VariableGet(controllerVariable!);
|
||||
statements.add(new ExpressionStatement(new VariableSet(
|
||||
controllerStreamVariable,
|
||||
new PropertyGet(completerGet, new Name('stream', helper.asyncLibrary),
|
||||
@@ -1204,8 +1202,7 @@ class AsyncStarFunctionRewriter extends AsyncRewriterBase {
|
||||
new ReturnStatement(new VariableGet(controllerStreamVariable));
|
||||
statements.add(returnStatement);
|
||||
|
||||
enclosingFunction.body = new Block(statements);
|
||||
enclosingFunction.body.parent = enclosingFunction;
|
||||
enclosingFunction.body = new Block(statements)..parent = enclosingFunction;
|
||||
enclosingFunction.asyncMarker = AsyncMarker.Sync;
|
||||
return enclosingFunction;
|
||||
}
|
||||
@@ -1216,7 +1213,7 @@ class AsyncStarFunctionRewriter extends AsyncRewriterBase {
|
||||
--currentTryDepth;
|
||||
|
||||
var finallyBody = new ExpressionStatement(new MethodInvocation(
|
||||
new VariableGet(controllerVariable),
|
||||
new VariableGet(controllerVariable!),
|
||||
new Name('close'),
|
||||
new Arguments(<Expression>[]),
|
||||
helper.asyncStarStreamControllerClose));
|
||||
@@ -1225,9 +1222,10 @@ class AsyncStarFunctionRewriter extends AsyncRewriterBase {
|
||||
return tryFinally;
|
||||
}
|
||||
|
||||
Statement buildCatchBody(exceptionVariable, stackTraceVariable) {
|
||||
Statement buildCatchBody(VariableDeclaration exceptionVariable,
|
||||
VariableDeclaration stackTraceVariable) {
|
||||
return new ExpressionStatement(new MethodInvocation(
|
||||
new VariableGet(controllerVariable),
|
||||
new VariableGet(controllerVariable!),
|
||||
new Name('addError'),
|
||||
new Arguments(<Expression>[
|
||||
new VariableGet(exceptionVariable),
|
||||
@@ -1245,11 +1243,11 @@ class AsyncStarFunctionRewriter extends AsyncRewriterBase {
|
||||
]);
|
||||
}
|
||||
|
||||
TreeNode visitYieldStatement(YieldStatement stmt, TreeNode removalSentinel) {
|
||||
Expression expr = expressionRewriter.rewrite(stmt.expression, statements);
|
||||
TreeNode visitYieldStatement(YieldStatement stmt, TreeNode? removalSentinel) {
|
||||
Expression expr = expressionRewriter!.rewrite(stmt.expression, statements);
|
||||
|
||||
var addExpression = new MethodInvocation(
|
||||
new VariableGet(controllerVariable),
|
||||
new VariableGet(controllerVariable!),
|
||||
new Name(stmt.isYieldStar ? 'addStream' : 'add', helper.asyncLibrary),
|
||||
new Arguments(<Expression>[expr]),
|
||||
stmt.isYieldStar
|
||||
@@ -1261,26 +1259,26 @@ class AsyncStarFunctionRewriter extends AsyncRewriterBase {
|
||||
addExpression,
|
||||
new ReturnStatement(new NullLiteral()),
|
||||
createContinuationPoint()..fileOffset = stmt.fileOffset));
|
||||
return removalSentinel;
|
||||
return removalSentinel ?? EmptyStatement();
|
||||
}
|
||||
|
||||
TreeNode visitReturnStatement(
|
||||
ReturnStatement node, TreeNode removalSentinel) {
|
||||
ReturnStatement node, TreeNode? removalSentinel) {
|
||||
// Async* functions cannot return a value.
|
||||
assert(node.expression == null || node.expression is NullLiteral);
|
||||
statements
|
||||
.add(new BreakStatement(labeledBody)..fileOffset = node.fileOffset);
|
||||
return removalSentinel;
|
||||
.add(new BreakStatement(labeledBody!)..fileOffset = node.fileOffset);
|
||||
return removalSentinel ?? EmptyStatement();
|
||||
}
|
||||
}
|
||||
|
||||
class AsyncFunctionRewriter extends AsyncRewriterBase {
|
||||
VariableDeclaration returnVariable;
|
||||
VariableDeclaration asyncFutureVariable;
|
||||
VariableDeclaration isSyncVariable;
|
||||
VariableDeclaration? returnVariable;
|
||||
VariableDeclaration? asyncFutureVariable;
|
||||
VariableDeclaration? isSyncVariable;
|
||||
|
||||
AsyncFunctionRewriter(HelperNodes helper, FunctionNode enclosingFunction,
|
||||
StaticTypeContext staticTypeContext)
|
||||
StatefulStaticTypeContext staticTypeContext)
|
||||
: super(helper, enclosingFunction, staticTypeContext);
|
||||
|
||||
FunctionNode rewrite() {
|
||||
@@ -1309,18 +1307,18 @@ class AsyncFunctionRewriter extends AsyncRewriterBase {
|
||||
..fileOffset = enclosingFunction.body?.fileOffset ?? -1,
|
||||
isFinal: true,
|
||||
type: futureType);
|
||||
statements.add(asyncFutureVariable);
|
||||
statements.add(asyncFutureVariable!);
|
||||
|
||||
// bool :is_sync = false;
|
||||
isSyncVariable = VariableDeclaration(ContinuationVariables.isSync,
|
||||
initializer: BoolLiteral(false),
|
||||
type: helper.coreTypes.boolLegacyRawType);
|
||||
statements.add(isSyncVariable);
|
||||
statements.add(isSyncVariable!);
|
||||
|
||||
// asy::FutureOr<dynamic>* :return_value;
|
||||
returnVariable = VariableDeclaration(ContinuationVariables.returnValue,
|
||||
type: returnType);
|
||||
statements.add(returnVariable);
|
||||
statements.add(returnVariable!);
|
||||
|
||||
setupAsyncContinuations(statements);
|
||||
|
||||
@@ -1334,14 +1332,13 @@ class AsyncFunctionRewriter extends AsyncRewriterBase {
|
||||
|
||||
// :is_sync = true;
|
||||
final setIsSync =
|
||||
ExpressionStatement(VariableSet(isSyncVariable, BoolLiteral(true)));
|
||||
ExpressionStatement(VariableSet(isSyncVariable!, BoolLiteral(true)));
|
||||
statements.add(setIsSync);
|
||||
|
||||
// return :async_future;
|
||||
statements.add(ReturnStatement(VariableGet(asyncFutureVariable)));
|
||||
statements.add(ReturnStatement(VariableGet(asyncFutureVariable!)));
|
||||
|
||||
enclosingFunction.body = Block(statements);
|
||||
enclosingFunction.body.parent = enclosingFunction;
|
||||
enclosingFunction.body = Block(statements)..parent = enclosingFunction;
|
||||
enclosingFunction.asyncMarker = AsyncMarker.Sync;
|
||||
return enclosingFunction;
|
||||
}
|
||||
@@ -1352,10 +1349,10 @@ class AsyncFunctionRewriter extends AsyncRewriterBase {
|
||||
return ExpressionStatement(StaticInvocation(
|
||||
helper.completeOnAsyncError,
|
||||
Arguments([
|
||||
VariableGet(asyncFutureVariable),
|
||||
VariableGet(asyncFutureVariable!),
|
||||
VariableGet(exceptionVariable),
|
||||
VariableGet(stackTraceVariable),
|
||||
VariableGet(isSyncVariable)
|
||||
VariableGet(isSyncVariable!)
|
||||
])));
|
||||
}
|
||||
|
||||
@@ -1372,22 +1369,22 @@ class AsyncFunctionRewriter extends AsyncRewriterBase {
|
||||
ExpressionStatement(StaticInvocation(
|
||||
helper.completeOnAsyncReturn,
|
||||
Arguments([
|
||||
VariableGet(asyncFutureVariable),
|
||||
VariableGet(returnVariable),
|
||||
VariableGet(isSyncVariable)
|
||||
VariableGet(asyncFutureVariable!),
|
||||
VariableGet(returnVariable!),
|
||||
VariableGet(isSyncVariable!)
|
||||
]))),
|
||||
ReturnStatement()..fileOffset = enclosingFunction.fileEndOffset
|
||||
]);
|
||||
}
|
||||
|
||||
visitReturnStatement(ReturnStatement node, TreeNode removalSentinel) {
|
||||
visitReturnStatement(ReturnStatement node, TreeNode? removalSentinel) {
|
||||
var expr = node.expression == null
|
||||
? new NullLiteral()
|
||||
: expressionRewriter.rewrite(node.expression, statements);
|
||||
: expressionRewriter!.rewrite(node.expression!, statements);
|
||||
statements.add(new ExpressionStatement(
|
||||
new VariableSet(returnVariable, expr)..fileOffset = node.fileOffset));
|
||||
statements.add(new BreakStatement(labeledBody));
|
||||
return removalSentinel;
|
||||
new VariableSet(returnVariable!, expr)..fileOffset = node.fileOffset));
|
||||
statements.add(new BreakStatement(labeledBody!));
|
||||
return removalSentinel ?? EmptyStatement();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1401,11 +1398,11 @@ class HelperNodes {
|
||||
final Member asyncStarStreamControllerClose;
|
||||
final Constructor asyncStarStreamControllerConstructor;
|
||||
final Member asyncStarStreamControllerStream;
|
||||
final Member asyncStarMoveNextHelper;
|
||||
final Procedure asyncStarMoveNextHelper;
|
||||
final Procedure asyncThenWrapper;
|
||||
final Procedure awaitHelper;
|
||||
final Member completeOnAsyncReturn;
|
||||
final Member completeOnAsyncError;
|
||||
final Procedure completeOnAsyncReturn;
|
||||
final Procedure completeOnAsyncError;
|
||||
final Library coreLibrary;
|
||||
final CoreTypes coreTypes;
|
||||
final Class futureClass;
|
||||
@@ -1499,6 +1496,7 @@ class HelperNodes {
|
||||
coreTypes.syncIteratorYieldEachIterable,
|
||||
coreTypes.boolClass,
|
||||
productMode,
|
||||
coreTypes.index.getTopLevelMember('dart:_internal', 'unsafeCast'));
|
||||
coreTypes.index.getTopLevelMember('dart:_internal', 'unsafeCast')
|
||||
as Procedure);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
// 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.
|
||||
|
||||
// @dart = 2.9
|
||||
|
||||
library kernel.transformations.mixin_full_resolution;
|
||||
|
||||
import '../ast.dart';
|
||||
@@ -22,7 +20,7 @@ void transformLibraries(
|
||||
CoreTypes coreTypes,
|
||||
ClassHierarchy hierarchy,
|
||||
List<Library> libraries,
|
||||
ReferenceFromIndex referenceFromIndex) {
|
||||
ReferenceFromIndex? referenceFromIndex) {
|
||||
new MixinFullResolution(targetInfo, coreTypes, hierarchy)
|
||||
.transform(libraries, referenceFromIndex);
|
||||
}
|
||||
@@ -46,7 +44,7 @@ class MixinFullResolution {
|
||||
/// Transform the given new [libraries]. It is expected that all other
|
||||
/// libraries have already been transformed.
|
||||
void transform(
|
||||
List<Library> libraries, ReferenceFromIndex referenceFromIndex) {
|
||||
List<Library> libraries, ReferenceFromIndex? referenceFromIndex) {
|
||||
if (libraries.isEmpty) return;
|
||||
|
||||
var transformedClasses = new Set<Class>();
|
||||
@@ -71,7 +69,7 @@ class MixinFullResolution {
|
||||
Set<Class> processedClasses,
|
||||
Set<Class> transformedClasses,
|
||||
Class class_,
|
||||
ReferenceFromIndex referenceFromIndex) {
|
||||
ReferenceFromIndex? referenceFromIndex) {
|
||||
// If this class was already handled then so were all classes up to the
|
||||
// [Object] class.
|
||||
if (!processedClasses.add(class_)) return;
|
||||
@@ -79,7 +77,7 @@ class MixinFullResolution {
|
||||
Library enclosingLibrary = class_.enclosingLibrary;
|
||||
|
||||
if (!librariesToBeTransformed.contains(enclosingLibrary) &&
|
||||
enclosingLibrary.importUri?.scheme == "dart") {
|
||||
enclosingLibrary.importUri.scheme == "dart") {
|
||||
// If we're not asked to transform the platform libraries then we expect
|
||||
// that they will be already transformed.
|
||||
return;
|
||||
@@ -88,7 +86,7 @@ class MixinFullResolution {
|
||||
// Ensure super classes have been transformed before this class.
|
||||
if (class_.superclass != null) {
|
||||
transformClass(librariesToBeTransformed, processedClasses,
|
||||
transformedClasses, class_.superclass, referenceFromIndex);
|
||||
transformedClasses, class_.superclass!, referenceFromIndex);
|
||||
}
|
||||
|
||||
// If this is not a mixin application we don't need to make forwarding
|
||||
@@ -99,12 +97,13 @@ class MixinFullResolution {
|
||||
transformedClasses.add(class_);
|
||||
|
||||
// Clone fields and methods from the mixin class.
|
||||
var substitution = getSubstitutionMap(class_.mixedInType);
|
||||
var substitution = getSubstitutionMap(class_.mixedInType!);
|
||||
var cloner = new CloneVisitorWithMembers(typeSubstitution: substitution);
|
||||
|
||||
IndexedLibrary indexedLibrary =
|
||||
IndexedLibrary? indexedLibrary =
|
||||
referenceFromIndex?.lookupLibrary(enclosingLibrary);
|
||||
IndexedClass indexedClass = indexedLibrary?.lookupIndexedClass(class_.name);
|
||||
IndexedClass? indexedClass =
|
||||
indexedLibrary?.lookupIndexedClass(class_.name);
|
||||
|
||||
if (class_.mixin.fields.isNotEmpty) {
|
||||
// When we copy a field from the mixed in class, we remove any
|
||||
@@ -114,17 +113,17 @@ class MixinFullResolution {
|
||||
var setters = <Name, Procedure>{};
|
||||
for (var procedure in class_.procedures) {
|
||||
if (procedure.isSetter) {
|
||||
setters[procedure.name] = procedure;
|
||||
setters[procedure.name!] = procedure;
|
||||
} else {
|
||||
nonSetters[procedure.name] = procedure;
|
||||
nonSetters[procedure.name!] = procedure;
|
||||
}
|
||||
}
|
||||
|
||||
for (var field in class_.mixin.fields) {
|
||||
Reference getterReference =
|
||||
indexedClass?.lookupGetterReference(field.name);
|
||||
Reference setterReference =
|
||||
indexedClass?.lookupSetterReference(field.name);
|
||||
Reference? getterReference =
|
||||
indexedClass?.lookupGetterReference(field.name!);
|
||||
Reference? setterReference =
|
||||
indexedClass?.lookupSetterReference(field.name!);
|
||||
if (getterReference == null) {
|
||||
getterReference = nonSetters[field.name]?.reference;
|
||||
getterReference?.canonicalName?.unbind();
|
||||
@@ -135,11 +134,11 @@ class MixinFullResolution {
|
||||
}
|
||||
Field clone =
|
||||
cloner.cloneField(field, getterReference, setterReference);
|
||||
Procedure setter = setters[field.name];
|
||||
Procedure? setter = setters[field.name!];
|
||||
if (setter != null) {
|
||||
setters.remove(field.name);
|
||||
VariableDeclaration parameter =
|
||||
setter.function.positionalParameters.first;
|
||||
setter.function!.positionalParameters.first;
|
||||
clone.isCovariant = parameter.isCovariant;
|
||||
clone.isGenericCovariantImpl = parameter.isGenericCovariantImpl;
|
||||
}
|
||||
@@ -168,21 +167,21 @@ class MixinFullResolution {
|
||||
// NoSuchMethod forwarders aren't cloned.
|
||||
if (procedure.isNoSuchMethodForwarder) continue;
|
||||
|
||||
Reference reference;
|
||||
Reference? reference;
|
||||
if (procedure.isSetter) {
|
||||
reference = indexedClass?.lookupSetterReference(procedure.name);
|
||||
reference = indexedClass?.lookupSetterReference(procedure.name!);
|
||||
} else {
|
||||
reference = indexedClass?.lookupGetterReference(procedure.name);
|
||||
reference = indexedClass?.lookupGetterReference(procedure.name!);
|
||||
}
|
||||
|
||||
// Linear search for a forwarding stub with the same name.
|
||||
int originalIndex;
|
||||
int? originalIndex;
|
||||
for (int i = 0; i < originalLength; ++i) {
|
||||
var originalProcedure = class_.procedures[i];
|
||||
if (originalProcedure.name == procedure.name &&
|
||||
originalProcedure.kind == procedure.kind) {
|
||||
FunctionNode src = originalProcedure.function;
|
||||
FunctionNode dst = procedure.function;
|
||||
FunctionNode src = originalProcedure.function!;
|
||||
FunctionNode dst = procedure.function!;
|
||||
|
||||
if (src.positionalParameters.length !=
|
||||
dst.positionalParameters.length ||
|
||||
@@ -196,13 +195,13 @@ class MixinFullResolution {
|
||||
}
|
||||
}
|
||||
if (originalIndex != null) {
|
||||
reference ??= class_.procedures[originalIndex]?.reference;
|
||||
reference ??= class_.procedures[originalIndex].reference;
|
||||
}
|
||||
Procedure clone = cloner.cloneProcedure(procedure, reference);
|
||||
if (originalIndex != null) {
|
||||
Procedure originalProcedure = class_.procedures[originalIndex];
|
||||
FunctionNode src = originalProcedure.function;
|
||||
FunctionNode dst = clone.function;
|
||||
FunctionNode src = originalProcedure.function!;
|
||||
FunctionNode dst = clone.function!;
|
||||
assert(src.typeParameters.length == dst.typeParameters.length);
|
||||
for (int j = 0; j < src.typeParameters.length; ++j) {
|
||||
dst.typeParameters[j].flags = src.typeParameters[j].flags;
|
||||
@@ -229,7 +228,7 @@ class MixinFullResolution {
|
||||
|
||||
// This class implements the mixin type. Also, backends rely on the fact
|
||||
// that eliminated mixin is appended into the end of interfaces list.
|
||||
class_.implementedTypes.add(class_.mixedInType);
|
||||
class_.implementedTypes.add(class_.mixedInType!);
|
||||
|
||||
// This class is now a normal class.
|
||||
class_.mixedInType = null;
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
// 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.
|
||||
|
||||
// @dart = 2.9
|
||||
|
||||
library vm.constants_native_effects;
|
||||
|
||||
import '../ast.dart';
|
||||
@@ -25,12 +23,13 @@ class VmConstantsBackend extends ConstantsBackend {
|
||||
final Library coreLibrary = coreTypes.coreLibrary;
|
||||
final Class immutableMapClass = coreLibrary.classes
|
||||
.firstWhere((Class klass) => klass.name == '_ImmutableMap');
|
||||
// ignore: unnecessary_null_comparison
|
||||
assert(immutableMapClass != null);
|
||||
Field unmodifiableSetMap = coreTypes.index
|
||||
.getMember('dart:collection', '_UnmodifiableSet', '_map');
|
||||
.getMember('dart:collection', '_UnmodifiableSet', '_map') as Field;
|
||||
|
||||
return new VmConstantsBackend._(immutableMapClass, unmodifiableSetMap,
|
||||
unmodifiableSetMap.enclosingClass);
|
||||
unmodifiableSetMap.enclosingClass!);
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -38,12 +37,11 @@ class VmConstantsBackend extends ConstantsBackend {
|
||||
// The _ImmutableMap class is implemented via one field pointing to a list
|
||||
// of key/value pairs -- see runtime/lib/immutable_map.dart!
|
||||
final List<Constant> kvListPairs =
|
||||
new List<Constant>.filled(2 * constant.entries.length, null);
|
||||
for (int i = 0; i < constant.entries.length; i++) {
|
||||
final ConstantMapEntry entry = constant.entries[i];
|
||||
kvListPairs[2 * i] = entry.key;
|
||||
kvListPairs[2 * i + 1] = entry.value;
|
||||
}
|
||||
new List<Constant>.generate(2 * constant.entries.length, (int i) {
|
||||
final int index = i ~/ 2;
|
||||
final ConstantMapEntry entry = constant.entries[index];
|
||||
return i % 2 == 0 ? entry.key : entry.value;
|
||||
});
|
||||
// This is a bit fishy, since we merge the key and the value type by
|
||||
// putting both into the same list.
|
||||
final ListConstant kvListConstant =
|
||||
@@ -69,11 +67,11 @@ class VmConstantsBackend extends ConstantsBackend {
|
||||
void forEachLoweredMapConstantEntry(
|
||||
Constant constant, void Function(Constant key, Constant value) f) {
|
||||
assert(isLoweredMapConstant(constant));
|
||||
final InstanceConstant instance = constant;
|
||||
final InstanceConstant instance = constant as InstanceConstant;
|
||||
assert(immutableMapClass.fields.length == 1);
|
||||
final Field kvPairListField = immutableMapClass.fields[0];
|
||||
final ListConstant kvListConstant =
|
||||
instance.fieldValues[kvPairListField.getterReference];
|
||||
instance.fieldValues[kvPairListField.getterReference] as ListConstant;
|
||||
assert(kvListConstant.entries.length % 2 == 0);
|
||||
for (int index = 0; index < kvListConstant.entries.length; index += 2) {
|
||||
f(kvListConstant.entries[index], kvListConstant.entries[index + 1]);
|
||||
@@ -85,10 +83,9 @@ class VmConstantsBackend extends ConstantsBackend {
|
||||
final DartType elementType = constant.typeArgument;
|
||||
final List<Constant> entries = constant.entries;
|
||||
final List<ConstantMapEntry> mapEntries =
|
||||
new List<ConstantMapEntry>.filled(entries.length, null);
|
||||
for (int i = 0; i < entries.length; ++i) {
|
||||
mapEntries[i] = new ConstantMapEntry(entries[i], new NullConstant());
|
||||
}
|
||||
new List<ConstantMapEntry>.generate(entries.length, (int index) {
|
||||
return new ConstantMapEntry(entries[index], new NullConstant());
|
||||
});
|
||||
Constant map = lowerMapConstant(
|
||||
new MapConstant(elementType, const NullType(), mapEntries));
|
||||
return new InstanceConstant(unmodifiableSetClass.reference, [elementType],
|
||||
@@ -101,7 +98,7 @@ class VmConstantsBackend extends ConstantsBackend {
|
||||
constant.classNode == unmodifiableSetClass) {
|
||||
InstanceConstant instance = constant;
|
||||
return isLoweredMapConstant(
|
||||
instance.fieldValues[unmodifiableSetMap.getterReference]);
|
||||
instance.fieldValues[unmodifiableSetMap.getterReference]!);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -110,9 +107,9 @@ class VmConstantsBackend extends ConstantsBackend {
|
||||
void forEachLoweredSetConstantElement(
|
||||
Constant constant, void Function(Constant element) f) {
|
||||
assert(isLoweredSetConstant(constant));
|
||||
final InstanceConstant instance = constant;
|
||||
final InstanceConstant instance = constant as InstanceConstant;
|
||||
final Constant mapConstant =
|
||||
instance.fieldValues[unmodifiableSetMap.getterReference];
|
||||
instance.fieldValues[unmodifiableSetMap.getterReference]!;
|
||||
forEachLoweredMapConstantEntry(mapConstant, (Constant key, Constant value) {
|
||||
f(key);
|
||||
});
|
||||
|
||||
@@ -196,10 +196,15 @@ class VmTarget extends Target {
|
||||
|
||||
@override
|
||||
void performTransformationsOnProcedure(
|
||||
CoreTypes coreTypes, ClassHierarchy hierarchy, Procedure procedure,
|
||||
CoreTypes coreTypes,
|
||||
ClassHierarchy hierarchy,
|
||||
Procedure procedure,
|
||||
Map<String, String> environmentDefines,
|
||||
{void logger(String msg)}) {
|
||||
bool productMode = environmentDefines["dart.vm.product"] == "true";
|
||||
transformAsync.transformProcedure(
|
||||
new TypeEnvironment(coreTypes, hierarchy), procedure);
|
||||
new TypeEnvironment(coreTypes, hierarchy), procedure,
|
||||
productMode: productMode);
|
||||
logger?.call("Transformed async functions");
|
||||
|
||||
lowering.transformProcedure(
|
||||
|
||||
Reference in New Issue
Block a user