[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:
Johnni Winther
2021-04-07 08:30:47 +00:00
committed by commit-bot@chromium.org
parent a26a140d88
commit 9d80c4db57
8 changed files with 261 additions and 257 deletions
@@ -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));
}
+4 -4
View File
@@ -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');
+8 -3
View File
@@ -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}) {}
+33 -33
View File
@@ -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}");
}
}
+165 -167
View File
@@ -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;
+16 -19
View File
@@ -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);
});
+7 -2
View File
@@ -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(