[dart2js] Evaluate implicit constants in scope visitor
Change-Id: I2351571a665c8ffff8e9d57649fbf42b483e747b
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/142983
Commit-Queue: Johnni Winther <johnniwinther@google.com>
Reviewed-by: Mayank Patke <fishythefish@google.com>
diff --git a/pkg/compiler/lib/src/inferrer/builder_kernel.dart b/pkg/compiler/lib/src/inferrer/builder_kernel.dart
index fc8b914..4bcc834 100644
--- a/pkg/compiler/lib/src/inferrer/builder_kernel.dart
+++ b/pkg/compiler/lib/src/inferrer/builder_kernel.dart
@@ -206,7 +206,7 @@
TypeInformation run() {
if (_analyzedMember.isField) {
- if (_analyzedNode == null || _analyzedNode is ir.NullLiteral) {
+ if (_analyzedNode == null || isNullLiteral(_analyzedNode)) {
// Eagerly bailout, because computing the closure data only
// works for functions and field assignments.
return _types.nullType;
@@ -301,8 +301,7 @@
assert(definition.kind == MemberKind.regular);
ir.Field node = definition.node;
if (type == null &&
- (node.initializer == null ||
- node.initializer is ir.NullLiteral)) {
+ (node.initializer == null || isNullLiteral(node.initializer))) {
_inferrer.recordTypeOfField(member, _types.nullType);
}
}
diff --git a/pkg/compiler/lib/src/ir/constants.dart b/pkg/compiler/lib/src/ir/constants.dart
index c63a3b4..a905b0c 100644
--- a/pkg/compiler/lib/src/ir/constants.dart
+++ b/pkg/compiler/lib/src/ir/constants.dart
@@ -37,10 +37,19 @@
@override
ErrorReporter get errorReporter => super.errorReporter;
+ /// Evaluates [node] to a constant in the given [staticTypeContext].
+ ///
+ /// If [requireConstant] is `true`, an error is reported if [node] is not
+ /// a valid constant. Otherwise, `null` if [node] is not a valid constant.
+ ///
+ /// If [replaceImplicitConstant] is `true`, if [node] is not a constant
+ /// expression but evaluates to a constant, [node] is replaced with an
+ /// [ir.ConstantExpression] holding the constant. Otherwise the [node] is not
+ /// replaced even when it evaluated to a constant.
@override
ir.Constant evaluate(
ir.StaticTypeContext staticTypeContext, ir.Expression node,
- {bool requireConstant: true}) {
+ {bool requireConstant: true, bool replaceImplicitConstant: true}) {
errorReporter.requiresConstant = requireConstant;
if (node is ir.ConstantExpression) {
ir.Constant constant = node.constant;
@@ -67,8 +76,12 @@
constant.expression is ir.InvalidExpression) {
return null;
}
- // TODO(johnniwinther,sigmund): Replace [node] with an
- // `ir.ConstantExpression` holding the [constant].
+ if (constant != null && replaceImplicitConstant) {
+ // Note: Using [replaceWith] is slow and should be avoided.
+ node.replaceWith(ir.ConstantExpression(
+ constant, node.getStaticType(staticTypeContext))
+ ..fileOffset = node.fileOffset);
+ }
return constant;
} catch (e) {
return null;
diff --git a/pkg/compiler/lib/src/ir/impact_data.dart b/pkg/compiler/lib/src/ir/impact_data.dart
index a76ff95..b5a7e94 100644
--- a/pkg/compiler/lib/src/ir/impact_data.dart
+++ b/pkg/compiler/lib/src/ir/impact_data.dart
@@ -392,31 +392,31 @@
@override
void registerSymbolLiteral(String value) {
- _data._symbolLiterals ??= [];
+ _data._symbolLiterals ??= {};
_data._symbolLiterals.add(value);
}
@override
void registerStringLiteral(String value) {
- _data._stringLiterals ??= [];
+ _data._stringLiterals ??= {};
_data._stringLiterals.add(value);
}
@override
void registerBoolLiteral(bool value) {
- _data._boolLiterals ??= [];
+ _data._boolLiterals ??= {};
_data._boolLiterals.add(value);
}
@override
void registerDoubleLiteral(double value) {
- _data._doubleLiterals ??= [];
+ _data._doubleLiterals ??= {};
_data._doubleLiterals.add(value);
}
@override
void registerIntLiteral(int value) {
- _data._intLiterals ??= [];
+ _data._intLiterals ??= {};
_data._intLiterals.add(value);
}
@@ -508,11 +508,11 @@
List<_MapLiteral> _mapLiterals;
List<_ContainerLiteral> _listLiterals;
List<_ContainerLiteral> _setLiterals;
- List<String> _symbolLiterals;
- List<String> _stringLiterals;
- List<bool> _boolLiterals;
- List<double> _doubleLiterals;
- List<int> _intLiterals;
+ Set<String> _symbolLiterals;
+ Set<String> _stringLiterals;
+ Set<bool> _boolLiterals;
+ Set<double> _doubleLiterals;
+ Set<int> _intLiterals;
List<_RuntimeTypeUse> _runtimeTypeUses;
List<_ForInData> _forInData;
@@ -599,13 +599,16 @@
_setLiterals = source.readList(
() => new _ContainerLiteral.fromDataSource(source),
emptyAsNull: true);
- _symbolLiterals = source.readStrings(emptyAsNull: true);
- _stringLiterals = source.readStrings(emptyAsNull: true);
- _boolLiterals = source.readList(() => source.readBool(), emptyAsNull: true);
- _doubleLiterals =
- source.readList(() => source.readDoubleValue(), emptyAsNull: true);
- _intLiterals =
- source.readList(() => source.readIntegerValue(), emptyAsNull: true);
+ _symbolLiterals = source.readStrings(emptyAsNull: true).toSet();
+ _stringLiterals = source.readStrings(emptyAsNull: true).toSet();
+ _boolLiterals =
+ source.readList(() => source.readBool(), emptyAsNull: true).toSet();
+ _doubleLiterals = source
+ .readList(() => source.readDoubleValue(), emptyAsNull: true)
+ .toSet();
+ _intLiterals = source
+ .readList(() => source.readIntegerValue(), emptyAsNull: true)
+ .toSet();
_runtimeTypeUses = source.readList(
() => new _RuntimeTypeUse.fromDataSource(source),
emptyAsNull: true);
diff --git a/pkg/compiler/lib/src/ir/scope.dart b/pkg/compiler/lib/src/ir/scope.dart
index 2a9cee6..90bc23a 100644
--- a/pkg/compiler/lib/src/ir/scope.dart
+++ b/pkg/compiler/lib/src/ir/scope.dart
@@ -10,7 +10,7 @@
class ScopeModel {
final ClosureScopeModel closureScopeModel;
final VariableScopeModel variableScopeModel;
- final InitializerComplexity initializerComplexity;
+ final EvaluationComplexity initializerComplexity;
const ScopeModel(
{this.closureScopeModel,
diff --git a/pkg/compiler/lib/src/ir/scope_visitor.dart b/pkg/compiler/lib/src/ir/scope_visitor.dart
index 27d9b0b..0dacf07 100644
--- a/pkg/compiler/lib/src/ir/scope_visitor.dart
+++ b/pkg/compiler/lib/src/ir/scope_visitor.dart
@@ -6,6 +6,7 @@
import 'package:kernel/type_environment.dart' as ir;
import 'package:front_end/src/api_prototype/constant_evaluator.dart' as ir;
+import '../ir/constants.dart';
import 'closure.dart';
import 'scope.dart';
@@ -13,9 +14,9 @@
/// assigned/captured/free at various points to build a [ClosureScopeModel] and
/// a [VariableScopeModel] that can respond to queries about how a particular
/// variable is being used at any point in the code.
-class ScopeModelBuilder extends ir.Visitor<InitializerComplexity>
+class ScopeModelBuilder extends ir.Visitor<EvaluationComplexity>
with VariableCollectorMixin {
- final ir.ConstantEvaluator _constantEvaluator;
+ final Dart2jsConstantEvaluator _constantEvaluator;
ir.StaticTypeContext _staticTypeContext;
final ClosureScopeModel _model = new ClosureScopeModel();
@@ -84,7 +85,7 @@
ScopeModel computeModel(ir.Member node) {
if (node.isAbstract && !node.isExternal) {
return const ScopeModel(
- initializerComplexity: const InitializerComplexity.lazy());
+ initializerComplexity: const EvaluationComplexity.lazy());
}
_staticTypeContext =
@@ -99,13 +100,13 @@
_hasThisLocal = false;
}
- InitializerComplexity initializerComplexity =
- const InitializerComplexity.lazy();
+ EvaluationComplexity initializerComplexity =
+ const EvaluationComplexity.lazy();
if (node is ir.Field) {
if (node.initializer != null) {
initializerComplexity = node.accept(this);
} else {
- initializerComplexity = const InitializerComplexity.constant();
+ initializerComplexity = const EvaluationComplexity.constant();
_model.scopeInfo = new KernelScopeInfo(_hasThisLocal);
}
} else {
@@ -119,21 +120,91 @@
}
@override
- InitializerComplexity defaultNode(ir.Node node) =>
+ EvaluationComplexity defaultNode(ir.Node node) =>
throw UnsupportedError('Unhandled node $node (${node.runtimeType})');
- InitializerComplexity visitNode(ir.Node node) {
+ EvaluationComplexity visitNode(ir.Node node) {
return node?.accept(this);
}
- InitializerComplexity visitNodes(List<ir.Node> nodes) {
- InitializerComplexity complexity = const InitializerComplexity.constant();
+ /// Tries to evaluate [node] as a constant expression.
+ ///
+ /// If [node] it succeeds, an [EvaluationComplexity] containing the new
+ /// constant is returned. Otherwise a 'lazy' [EvaluationComplexity] is
+ /// returned, signaling that [node] is not a constant expression.
+ ///
+ /// This method should be called in the visit methods of all expressions that
+ /// could potentially be constant to bubble up the constness of expressions.
+ ///
+ /// For instance in `var a = 1 + 2` [visitIntLiteral] calls this method
+ /// for `1` and `2` to convert these from int literals to int constants, and
+ /// [visitMethodInvocation] call this method, when seeing that all of its
+ /// subexpressions are constant, and it itself therefore is potentially
+ /// constant, thus computing that `1 + 2` can be replaced by the int constant
+ /// `3`.
+ ///
+ /// Note that [node] is _not_ replaced with a new constant expression. It is
+ /// the responsibility of the caller to do so. This is needed for performance
+ /// reasons since calling `TreeNode.replaceChild` searches linearly through
+ /// the children of the parent node, which lead to a O(n^2) complexity that
+ /// is severe and observable for instance for large list literals.
+ EvaluationComplexity _evaluateImplicitConstant(ir.Expression node) {
+ ir.Constant constant = _constantEvaluator.evaluate(_staticTypeContext, node,
+ requireConstant: false, replaceImplicitConstant: false);
+ if (constant != null) {
+ return new EvaluationComplexity.constant(constant);
+ }
+ return const EvaluationComplexity.lazy();
+ }
+
+ /// The evaluation complexity of the last visited expression.
+ EvaluationComplexity _lastExpressionComplexity;
+
+ /// Visit [node] and returns the corresponding `ConstantExpression` if [node]
+ /// evaluated to a constant.
+ ///
+ /// This method stores the complexity of [node] in [_lastExpressionComplexity]
+ /// and sets the parent of the created `ConstantExpression` to the parent
+ /// of [node]. The caller must replace [node] within the parent node. This
+ /// is done to avoid calling `Node.replaceChild` which searches linearly
+ /// through the children nodes `node.parent` in order to replace `node` which
+ /// results in O(n^2) complexity of replacing elements in for instance a list
+ /// of `n` elements.
+ ir.Expression _handleExpression(ir.Expression node) {
+ _lastExpressionComplexity = visitNode(node);
+ if (_lastExpressionComplexity.isFreshConstant) {
+ return new ir.ConstantExpression(_lastExpressionComplexity.constant,
+ node.getStaticType(_staticTypeContext))
+ ..fileOffset = node.fileOffset
+ ..parent = node.parent;
+ }
+ return node;
+ }
+
+ /// Visit all [nodes] returning the combined complexity.
+ EvaluationComplexity visitNodes(List<ir.Node> nodes) {
+ EvaluationComplexity complexity = const EvaluationComplexity.constant();
for (ir.Node node in nodes) {
complexity = complexity.combine(visitNode(node));
}
return complexity;
}
+ /// Visit all [nodes] returning the combined complexity.
+ ///
+ /// If subexpressions can be evaluated as constants, they are replaced by
+ /// constant expressions in [nodes].
+ EvaluationComplexity visitExpressions(List<ir.Expression> nodes) {
+ EvaluationComplexity combinedComplexity =
+ const EvaluationComplexity.constant();
+ for (int i = 0; i < nodes.length; i++) {
+ nodes[i] = _handleExpression(nodes[i]);
+ combinedComplexity =
+ combinedComplexity.combine(_lastExpressionComplexity);
+ }
+ return combinedComplexity;
+ }
+
/// Update the [CapturedScope] object corresponding to
/// this node if any variables are captured.
void attachCapturedScopeVariables(ir.TreeNode node) {
@@ -211,12 +282,13 @@
}
@override
- InitializerComplexity visitNamedExpression(ir.NamedExpression node) {
- return visitNode(node.value);
+ EvaluationComplexity visitNamedExpression(ir.NamedExpression node) {
+ throw UnsupportedError(
+ 'NamedExpression should be handled through visitArguments');
}
@override
- InitializerComplexity visitTryCatch(ir.TryCatch node) {
+ EvaluationComplexity visitTryCatch(ir.TryCatch node) {
bool oldInTry = _inTry;
_inTry = true;
visitInVariableScope(node, () {
@@ -224,11 +296,11 @@
});
visitNodes(node.catches);
_inTry = oldInTry;
- return const InitializerComplexity.lazy();
+ return const EvaluationComplexity.lazy();
}
@override
- InitializerComplexity visitTryFinally(ir.TryFinally node) {
+ EvaluationComplexity visitTryFinally(ir.TryFinally node) {
bool oldInTry = _inTry;
_inTry = true;
visitInVariableScope(node, () {
@@ -236,24 +308,24 @@
});
visitNode(node.finalizer);
_inTry = oldInTry;
- return const InitializerComplexity.lazy();
+ return const EvaluationComplexity.lazy();
}
@override
- InitializerComplexity visitVariableGet(ir.VariableGet node) {
+ EvaluationComplexity visitVariableGet(ir.VariableGet node) {
_markVariableAsUsed(node.variable, VariableUse.explicit);
// Don't visit `node.promotedType`.
- return const InitializerComplexity.lazy();
+ return const EvaluationComplexity.lazy();
}
@override
- InitializerComplexity visitVariableSet(ir.VariableSet node) {
+ EvaluationComplexity visitVariableSet(ir.VariableSet node) {
_mutatedVariables.add(node.variable);
_markVariableAsUsed(node.variable, VariableUse.explicit);
visitInContext(node.variable.type, VariableUse.localType);
- visitNode(node.value);
+ node.value = _handleExpression(node.value);
registerAssignedVariable(node.variable);
- return const InitializerComplexity.lazy();
+ return const EvaluationComplexity.lazy();
}
void _handleVariableDeclaration(
@@ -263,13 +335,15 @@
}
visitInContext(node.type, usage);
- visitNode(node.initializer);
+ if (node.initializer != null) {
+ node.initializer = _handleExpression(node.initializer);
+ }
}
@override
- InitializerComplexity visitVariableDeclaration(ir.VariableDeclaration node) {
+ EvaluationComplexity visitVariableDeclaration(ir.VariableDeclaration node) {
_handleVariableDeclaration(node, VariableUse.localType);
- return const InitializerComplexity.lazy();
+ return const EvaluationComplexity.lazy();
}
/// Add this variable to the set of free variables if appropriate and add to
@@ -304,15 +378,15 @@
}
@override
- InitializerComplexity visitThisExpression(ir.ThisExpression thisExpression) {
+ EvaluationComplexity visitThisExpression(ir.ThisExpression thisExpression) {
if (_hasThisLocal) {
_registerNeedsThis(VariableUse.explicit);
}
- return const InitializerComplexity.lazy();
+ return const EvaluationComplexity.lazy();
}
@override
- InitializerComplexity visitTypeParameter(ir.TypeParameter typeParameter) {
+ EvaluationComplexity visitTypeParameter(ir.TypeParameter typeParameter) {
TypeVariableTypeWithContext typeVariable(ir.Library library) =>
new TypeVariableTypeWithContext(
ir.TypeParameterType.withDefaultNullabilityForLibrary(
@@ -348,7 +422,7 @@
visitNode(typeParameter.bound);
- return const InitializerComplexity.constant();
+ return const EvaluationComplexity.constant();
}
/// Add `this` as a variable that needs to be accessed (and thus may become a
@@ -367,7 +441,7 @@
}
@override
- InitializerComplexity visitForInStatement(ir.ForInStatement node) {
+ EvaluationComplexity visitForInStatement(ir.ForInStatement node) {
// We need to set `inTry` to true if this is an async for-in because we
// desugar it into a try-finally in the SSA phase.
bool oldInTry = _inTry;
@@ -377,40 +451,40 @@
enterNewScope(node, () {
visitNode(node.variable);
visitInVariableScope(node, () {
- visitNode(node.iterable);
+ node.iterable = _handleExpression(node.iterable);
visitNode(node.body);
});
});
if (node.isAsync) {
_inTry = oldInTry;
}
- return const InitializerComplexity.lazy();
+ return const EvaluationComplexity.lazy();
}
@override
- InitializerComplexity visitWhileStatement(ir.WhileStatement node) {
+ EvaluationComplexity visitWhileStatement(ir.WhileStatement node) {
enterNewScope(node, () {
visitInVariableScope(node, () {
- visitNode(node.condition);
+ node.condition = _handleExpression(node.condition);
visitNode(node.body);
});
});
- return const InitializerComplexity.lazy();
+ return const EvaluationComplexity.lazy();
}
@override
- InitializerComplexity visitDoStatement(ir.DoStatement node) {
+ EvaluationComplexity visitDoStatement(ir.DoStatement node) {
enterNewScope(node, () {
visitInVariableScope(node, () {
visitNode(node.body);
- visitNode(node.condition);
+ node.condition = _handleExpression(node.condition);
});
});
- return const InitializerComplexity.lazy();
+ return const EvaluationComplexity.lazy();
}
@override
- InitializerComplexity visitForStatement(ir.ForStatement node) {
+ EvaluationComplexity visitForStatement(ir.ForStatement node) {
List<ir.VariableDeclaration> boxedLoopVariables =
<ir.VariableDeclaration>[];
enterNewScope(node, () {
@@ -418,7 +492,7 @@
// check if a loop variable was captured in one of these subexpressions.
visitNodes(node.variables);
visitInVariableScope(node, () {
- visitNodes(node.updates);
+ visitExpressions(node.updates);
});
// Loop variables that have not been captured yet can safely be flagged as
@@ -433,7 +507,9 @@
// This must happen after the above, so any loop variables mutated in the
// condition or body are indeed flagged as mutated.
visitInVariableScope(node, () {
- visitNode(node.condition);
+ if (node.condition != null) {
+ node.condition = _handleExpression(node.condition);
+ }
visitNode(node.body);
});
@@ -460,11 +536,11 @@
scope.thisUsedAsFreeVariableIfNeedsRti,
scope.hasThisLocal);
}
- return const InitializerComplexity.lazy();
+ return const EvaluationComplexity.lazy();
}
@override
- InitializerComplexity visitSuperMethodInvocation(
+ EvaluationComplexity visitSuperMethodInvocation(
ir.SuperMethodInvocation node) {
if (_hasThisLocal) {
_registerNeedsThis(VariableUse.explicit);
@@ -473,26 +549,25 @@
visitNodesInContext(node.arguments.types,
new VariableUse.staticTypeArgument(node.interfaceTarget));
}
- visitNodes(node.arguments.positional);
- visitNodes(node.arguments.named);
- return const InitializerComplexity.lazy();
+ visitArguments(node.arguments);
+ return const EvaluationComplexity.lazy();
}
@override
- InitializerComplexity visitSuperPropertySet(ir.SuperPropertySet node) {
+ EvaluationComplexity visitSuperPropertySet(ir.SuperPropertySet node) {
if (_hasThisLocal) {
_registerNeedsThis(VariableUse.explicit);
}
- visitNode(node.value);
- return const InitializerComplexity.lazy();
+ node.value = _handleExpression(node.value);
+ return const EvaluationComplexity.lazy();
}
@override
- InitializerComplexity visitSuperPropertyGet(ir.SuperPropertyGet node) {
+ EvaluationComplexity visitSuperPropertyGet(ir.SuperPropertyGet node) {
if (_hasThisLocal) {
_registerNeedsThis(VariableUse.explicit);
}
- return const InitializerComplexity.lazy();
+ return const EvaluationComplexity.lazy();
}
void visitInvokable(ir.TreeNode node, void f()) {
@@ -565,170 +640,183 @@
}
@override
- InitializerComplexity visitField(ir.Field node) {
+ EvaluationComplexity visitField(ir.Field node) {
_currentTypeUsage = VariableUse.fieldType;
- InitializerComplexity complexity;
+ EvaluationComplexity complexity;
visitInvokable(node, () {
- complexity = visitNode(node.initializer);
+ node.initializer = _handleExpression(node.initializer);
+ complexity = _lastExpressionComplexity;
});
_currentTypeUsage = null;
return complexity;
}
@override
- InitializerComplexity visitConstructor(ir.Constructor node) {
+ EvaluationComplexity visitConstructor(ir.Constructor node) {
visitInvokable(node, () {
visitNodes(node.initializers);
visitNode(node.function);
});
- return const InitializerComplexity.lazy();
+ return const EvaluationComplexity.lazy();
}
@override
- InitializerComplexity visitProcedure(ir.Procedure node) {
+ EvaluationComplexity visitProcedure(ir.Procedure node) {
visitInvokable(node, () {
visitNode(node.function);
});
- return const InitializerComplexity.lazy();
+ return const EvaluationComplexity.lazy();
}
@override
- InitializerComplexity visitFunctionExpression(ir.FunctionExpression node) {
+ EvaluationComplexity visitFunctionExpression(ir.FunctionExpression node) {
visitInvokable(node, () {
visitInVariableScope(node, () {
visitNode(node.function);
});
});
- return const InitializerComplexity.lazy();
+ return const EvaluationComplexity.lazy();
}
@override
- InitializerComplexity visitFunctionDeclaration(ir.FunctionDeclaration node) {
+ EvaluationComplexity visitFunctionDeclaration(ir.FunctionDeclaration node) {
visitInvokable(node, () {
visitInVariableScope(node, () {
visitNode(node.function);
});
});
- return const InitializerComplexity.lazy();
+ return const EvaluationComplexity.lazy();
}
@override
- InitializerComplexity visitDynamicType(ir.DynamicType node) =>
- const InitializerComplexity.constant();
+ EvaluationComplexity visitDynamicType(ir.DynamicType node) =>
+ const EvaluationComplexity.constant();
@override
- InitializerComplexity visitBottomType(ir.BottomType node) =>
- const InitializerComplexity.lazy();
+ EvaluationComplexity visitBottomType(ir.BottomType node) =>
+ const EvaluationComplexity.lazy();
@override
- InitializerComplexity visitNeverType(ir.NeverType node) =>
- const InitializerComplexity.lazy();
+ EvaluationComplexity visitNeverType(ir.NeverType node) =>
+ const EvaluationComplexity.lazy();
@override
- InitializerComplexity visitInvalidType(ir.InvalidType node) =>
- const InitializerComplexity.lazy();
+ EvaluationComplexity visitInvalidType(ir.InvalidType node) =>
+ const EvaluationComplexity.lazy();
@override
- InitializerComplexity visitVoidType(ir.VoidType node) =>
- const InitializerComplexity.constant();
+ EvaluationComplexity visitVoidType(ir.VoidType node) =>
+ const EvaluationComplexity.constant();
@override
- InitializerComplexity visitInterfaceType(ir.InterfaceType node) {
+ EvaluationComplexity visitInterfaceType(ir.InterfaceType node) {
return visitNodes(node.typeArguments);
}
@override
- InitializerComplexity visitFutureOrType(ir.FutureOrType node) {
+ EvaluationComplexity visitFutureOrType(ir.FutureOrType node) {
return visitNode(node.typeArgument);
}
@override
- InitializerComplexity visitFunctionType(ir.FunctionType node) {
- InitializerComplexity complexity = visitNode(node.returnType);
+ EvaluationComplexity visitFunctionType(ir.FunctionType node) {
+ EvaluationComplexity complexity = visitNode(node.returnType);
complexity = complexity.combine(visitNodes(node.positionalParameters));
complexity = complexity.combine(visitNodes(node.namedParameters));
return complexity.combine(visitNodes(node.typeParameters));
}
@override
- InitializerComplexity visitNamedType(ir.NamedType node) {
+ EvaluationComplexity visitNamedType(ir.NamedType node) {
return visitNode(node.type);
}
@override
- InitializerComplexity visitTypeParameterType(ir.TypeParameterType node) {
+ EvaluationComplexity visitTypeParameterType(ir.TypeParameterType node) {
_analyzeTypeVariable(node, _currentTypeUsage);
- return const InitializerComplexity.lazy();
+ return const EvaluationComplexity.lazy();
}
- InitializerComplexity visitInContext(ir.Node node, VariableUse use) {
+ EvaluationComplexity visitInContext(ir.Node node, VariableUse use) {
VariableUse oldCurrentTypeUsage = _currentTypeUsage;
_currentTypeUsage = use;
- InitializerComplexity complexity = visitNode(node);
+ EvaluationComplexity complexity = visitNode(node);
_currentTypeUsage = oldCurrentTypeUsage;
return complexity;
}
- InitializerComplexity visitNodesInContext(
+ EvaluationComplexity visitNodesInContext(
List<ir.Node> nodes, VariableUse use) {
VariableUse oldCurrentTypeUsage = _currentTypeUsage;
_currentTypeUsage = use;
- InitializerComplexity complexity = visitNodes(nodes);
+ EvaluationComplexity complexity = visitNodes(nodes);
_currentTypeUsage = oldCurrentTypeUsage;
return complexity;
}
@override
- InitializerComplexity visitTypeLiteral(ir.TypeLiteral node) {
- return visitInContext(node.type, VariableUse.explicit);
- }
-
- @override
- InitializerComplexity visitIsExpression(ir.IsExpression node) {
- visitNode(node.operand);
+ EvaluationComplexity visitTypeLiteral(ir.TypeLiteral node) {
visitInContext(node.type, VariableUse.explicit);
- return const InitializerComplexity.lazy();
+ return _evaluateImplicitConstant(node);
}
@override
- InitializerComplexity visitAsExpression(ir.AsExpression node) {
- visitNode(node.operand);
+ EvaluationComplexity visitIsExpression(ir.IsExpression node) {
+ node.operand = _handleExpression(node.operand);
+ EvaluationComplexity complexity = _lastExpressionComplexity;
+ visitInContext(node.type, VariableUse.explicit);
+ if (complexity.isConstant) {
+ return _evaluateImplicitConstant(node);
+ }
+ return const EvaluationComplexity.lazy();
+ }
+
+ @override
+ EvaluationComplexity visitAsExpression(ir.AsExpression node) {
+ node.operand = _handleExpression(node.operand);
+ EvaluationComplexity complexity = _lastExpressionComplexity;
visitInContext(node.type,
node.isTypeError ? VariableUse.implicitCast : VariableUse.explicit);
- return const InitializerComplexity.lazy();
+ if (complexity.isConstant) {
+ return _evaluateImplicitConstant(node);
+ }
+ return const EvaluationComplexity.lazy();
}
@override
- InitializerComplexity visitNullCheck(ir.NullCheck node) {
- visitNode(node.operand);
- return const InitializerComplexity.lazy();
+ EvaluationComplexity visitNullCheck(ir.NullCheck node) {
+ node.operand = _handleExpression(node.operand);
+ EvaluationComplexity complexity = _lastExpressionComplexity;
+ if (complexity.isConstant) {
+ return _evaluateImplicitConstant(node);
+ }
+ return const EvaluationComplexity.lazy();
}
@override
- InitializerComplexity visitAwaitExpression(ir.AwaitExpression node) {
- visitNode(node.operand);
- return const InitializerComplexity.lazy();
+ EvaluationComplexity visitAwaitExpression(ir.AwaitExpression node) {
+ node.operand = _handleExpression(node.operand);
+ return const EvaluationComplexity.lazy();
}
@override
- InitializerComplexity visitYieldStatement(ir.YieldStatement node) {
- visitNode(node.expression);
- return const InitializerComplexity.lazy();
+ EvaluationComplexity visitYieldStatement(ir.YieldStatement node) {
+ node.expression = _handleExpression(node.expression);
+ return const EvaluationComplexity.lazy();
}
@override
- InitializerComplexity visitLoadLibrary(ir.LoadLibrary node) {
- return const InitializerComplexity.lazy();
+ EvaluationComplexity visitLoadLibrary(ir.LoadLibrary node) {
+ return const EvaluationComplexity.lazy();
}
@override
- InitializerComplexity visitCheckLibraryIsLoaded(
- ir.CheckLibraryIsLoaded node) {
- return const InitializerComplexity.lazy();
+ EvaluationComplexity visitCheckLibraryIsLoaded(ir.CheckLibraryIsLoaded node) {
+ return const EvaluationComplexity.lazy();
}
@override
- InitializerComplexity visitFunctionNode(ir.FunctionNode node) {
+ EvaluationComplexity visitFunctionNode(ir.FunctionNode node) {
VariableUse parameterUsage = node.parent is ir.Member
? new VariableUse.memberParameter(node.parent)
: new VariableUse.localParameter(node.parent);
@@ -744,106 +832,116 @@
node.parent is ir.Member
? new VariableUse.memberReturnType(node.parent)
: new VariableUse.localReturnType(node.parent));
- visitNode(node.body);
- return const InitializerComplexity.lazy();
+ if (node.body != null) {
+ visitNode(node.body);
+ }
+ return const EvaluationComplexity.lazy();
}
@override
- InitializerComplexity visitListLiteral(ir.ListLiteral node) {
- InitializerComplexity complexity =
+ EvaluationComplexity visitListLiteral(ir.ListLiteral node) {
+ EvaluationComplexity complexity =
visitInContext(node.typeArgument, VariableUse.listLiteral);
- complexity = complexity.combine(visitNodes(node.expressions));
+ complexity = complexity.combine(visitExpressions(node.expressions));
if (node.isConst) {
- return const InitializerComplexity.constant();
+ return const EvaluationComplexity.constant();
} else {
return complexity.makeEager();
}
}
@override
- InitializerComplexity visitSetLiteral(ir.SetLiteral node) {
- InitializerComplexity complexity =
+ EvaluationComplexity visitSetLiteral(ir.SetLiteral node) {
+ EvaluationComplexity complexity =
visitInContext(node.typeArgument, VariableUse.setLiteral);
- complexity = complexity.combine(visitNodes(node.expressions));
+ complexity = complexity.combine(visitExpressions(node.expressions));
if (node.isConst) {
- return const InitializerComplexity.constant();
+ return const EvaluationComplexity.constant();
} else {
return complexity.makeEager();
}
}
@override
- InitializerComplexity visitMapLiteral(ir.MapLiteral node) {
- InitializerComplexity complexity =
+ EvaluationComplexity visitMapLiteral(ir.MapLiteral node) {
+ EvaluationComplexity complexity =
visitInContext(node.keyType, VariableUse.mapLiteral);
complexity = complexity
.combine(visitInContext(node.valueType, VariableUse.mapLiteral));
complexity = complexity.combine(visitNodes(node.entries));
if (node.isConst) {
- return const InitializerComplexity.constant();
+ return const EvaluationComplexity.constant();
} else {
return complexity.makeEager();
}
}
@override
- InitializerComplexity visitMapEntry(ir.MapEntry node) {
- InitializerComplexity complexity = visitNode(node.key);
- return complexity.combine(visitNode(node.value));
+ EvaluationComplexity visitMapEntry(ir.MapEntry node) {
+ node.key = _handleExpression(node.key);
+ EvaluationComplexity keyComplexity = _lastExpressionComplexity;
+
+ node.value = _handleExpression(node.value);
+ EvaluationComplexity valueComplexity = _lastExpressionComplexity;
+
+ return keyComplexity.combine(valueComplexity);
}
@override
- InitializerComplexity visitNullLiteral(ir.NullLiteral node) =>
- const InitializerComplexity.constant();
+ EvaluationComplexity visitNullLiteral(ir.NullLiteral node) =>
+ _evaluateImplicitConstant(node);
@override
- InitializerComplexity visitStringLiteral(ir.StringLiteral node) =>
- const InitializerComplexity.constant();
+ EvaluationComplexity visitStringLiteral(ir.StringLiteral node) =>
+ _evaluateImplicitConstant(node);
@override
- InitializerComplexity visitIntLiteral(ir.IntLiteral node) =>
- const InitializerComplexity.constant();
+ EvaluationComplexity visitIntLiteral(ir.IntLiteral node) =>
+ _evaluateImplicitConstant(node);
@override
- InitializerComplexity visitDoubleLiteral(ir.DoubleLiteral node) =>
- const InitializerComplexity.constant();
+ EvaluationComplexity visitDoubleLiteral(ir.DoubleLiteral node) =>
+ _evaluateImplicitConstant(node);
@override
- InitializerComplexity visitSymbolLiteral(ir.SymbolLiteral node) =>
- const InitializerComplexity.constant();
+ EvaluationComplexity visitSymbolLiteral(ir.SymbolLiteral node) =>
+ _evaluateImplicitConstant(node);
@override
- InitializerComplexity visitBoolLiteral(ir.BoolLiteral node) =>
- const InitializerComplexity.constant();
+ EvaluationComplexity visitBoolLiteral(ir.BoolLiteral node) =>
+ _evaluateImplicitConstant(node);
@override
- InitializerComplexity visitStringConcatenation(ir.StringConcatenation node) {
- visitNodes(node.expressions);
- return const InitializerComplexity.lazy();
+ EvaluationComplexity visitStringConcatenation(ir.StringConcatenation node) {
+ EvaluationComplexity complexity = visitExpressions(node.expressions);
+ if (complexity.isConstant) {
+ return _evaluateImplicitConstant(node);
+ }
+ return complexity;
}
@override
- InitializerComplexity visitStaticGet(ir.StaticGet node) {
+ EvaluationComplexity visitStaticGet(ir.StaticGet node) {
ir.Member target = node.target;
if (target is ir.Field) {
return target.isConst
- ? const InitializerComplexity.constant()
- : new InitializerComplexity.eager(fields: <ir.Field>{target});
+ ? const EvaluationComplexity.constant()
+ : new EvaluationComplexity.eager(fields: <ir.Field>{target});
} else if (target is ir.Procedure &&
target.kind == ir.ProcedureKind.Method) {
- return const InitializerComplexity.constant();
+ return _evaluateImplicitConstant(node);
}
- return const InitializerComplexity.lazy();
+ return const EvaluationComplexity.lazy();
}
@override
- InitializerComplexity visitStaticSet(ir.StaticSet node) {
- visitNode(node.value);
- return const InitializerComplexity.lazy();
+ EvaluationComplexity visitStaticSet(ir.StaticSet node) {
+ node.value = _handleExpression(node.value);
+ return const EvaluationComplexity.lazy();
}
@override
- InitializerComplexity visitStaticInvocation(ir.StaticInvocation node) {
+ EvaluationComplexity visitStaticInvocation(ir.StaticInvocation node) {
if (node.arguments.types.isNotEmpty) {
VariableUse usage;
if (node.target.kind == ir.ProcedureKind.Factory) {
@@ -854,40 +952,68 @@
visitNodesInContext(node.arguments.types, usage);
}
- visitNodes(node.arguments.positional);
- visitNodes(node.arguments.named);
+
+ EvaluationComplexity complexity = visitArguments(node.arguments);
+ if (complexity.isConstant &&
+ node.target ==
+ _staticTypeContext.typeEnvironment.coreTypes.identicalProcedure) {
+ return _evaluateImplicitConstant(node);
+ }
return node.isConst
- ? const InitializerComplexity.constant()
- : const InitializerComplexity.lazy();
+ ? const EvaluationComplexity.constant()
+ : const EvaluationComplexity.lazy();
}
@override
- InitializerComplexity visitConstructorInvocation(
+ EvaluationComplexity visitArguments(ir.Arguments node) {
+ EvaluationComplexity combinedComplexity = visitExpressions(node.positional);
+ for (int i = 0; i < node.named.length; i++) {
+ node.named[i].value = _handleExpression(node.named[i].value);
+ combinedComplexity =
+ combinedComplexity.combine(_lastExpressionComplexity);
+ }
+ return combinedComplexity;
+ }
+
+ @override
+ EvaluationComplexity visitConstructorInvocation(
ir.ConstructorInvocation node) {
if (node.arguments.types.isNotEmpty) {
visitNodesInContext(node.arguments.types,
new VariableUse.constructorTypeArgument(node.target));
}
- visitNodes(node.arguments.positional);
- visitNodes(node.arguments.named);
+ visitArguments(node.arguments);
return node.isConst
- ? const InitializerComplexity.constant()
- : const InitializerComplexity.lazy();
+ ? const EvaluationComplexity.constant()
+ : const EvaluationComplexity.lazy();
}
@override
- InitializerComplexity visitConditionalExpression(
+ EvaluationComplexity visitConditionalExpression(
ir.ConditionalExpression node) {
- InitializerComplexity complexity = visitNode(node.condition);
- complexity = complexity.combine(visitNode(node.then));
- return complexity.combine(visitNode(node.otherwise));
+ node.condition = _handleExpression(node.condition);
+ EvaluationComplexity conditionComplexity = _lastExpressionComplexity;
+
+ node.then = _handleExpression(node.then);
+ EvaluationComplexity thenComplexity = _lastExpressionComplexity;
+
+ node.otherwise = _handleExpression(node.otherwise);
+ EvaluationComplexity elseComplexity = _lastExpressionComplexity;
+
+ EvaluationComplexity complexity =
+ conditionComplexity.combine(thenComplexity).combine(elseComplexity);
+ if (complexity.isConstant) {
+ return _evaluateImplicitConstant(node);
+ }
// Don't visit `node.staticType`.
+ return complexity;
}
@override
- InitializerComplexity visitMethodInvocation(ir.MethodInvocation node) {
+ EvaluationComplexity visitMethodInvocation(ir.MethodInvocation node) {
+ node.receiver = _handleExpression(node.receiver);
+ EvaluationComplexity receiverComplexity = _lastExpressionComplexity;
ir.TreeNode receiver = node.receiver;
- visitNode(receiver);
if (node.arguments.types.isNotEmpty) {
VariableUse usage;
if (receiver is ir.VariableGet &&
@@ -899,211 +1025,250 @@
}
visitNodesInContext(node.arguments.types, usage);
}
- visitNodes(node.arguments.positional);
- visitNodes(node.arguments.named);
- // TODO(johnniwinther): Recognize constant operations.
- return const InitializerComplexity.lazy();
+ EvaluationComplexity complexity = visitArguments(node.arguments);
+ ir.Member interfaceTarget = node.interfaceTarget;
+ if (receiverComplexity.combine(complexity).isConstant &&
+ interfaceTarget is ir.Procedure &&
+ interfaceTarget.kind == ir.ProcedureKind.Operator) {
+ return _evaluateImplicitConstant(node);
+ }
+ return const EvaluationComplexity.lazy();
}
@override
- InitializerComplexity visitPropertyGet(ir.PropertyGet node) {
- visitNode(node.receiver);
- return const InitializerComplexity.lazy();
+ EvaluationComplexity visitPropertyGet(ir.PropertyGet node) {
+ node.receiver = _handleExpression(node.receiver);
+ EvaluationComplexity complexity = _lastExpressionComplexity;
+ if (complexity.isConstant && node.name.name == 'length') {
+ return _evaluateImplicitConstant(node);
+ }
+ return const EvaluationComplexity.lazy();
}
@override
- InitializerComplexity visitPropertySet(ir.PropertySet node) {
- visitNode(node.receiver);
- visitNode(node.value);
- return const InitializerComplexity.lazy();
+ EvaluationComplexity visitPropertySet(ir.PropertySet node) {
+ node.receiver = _handleExpression(node.receiver);
+ node.value = _handleExpression(node.value);
+ return const EvaluationComplexity.lazy();
}
@override
- InitializerComplexity visitDirectPropertyGet(ir.DirectPropertyGet node) {
- visitNode(node.receiver);
- return const InitializerComplexity.lazy();
+ EvaluationComplexity visitDirectPropertyGet(ir.DirectPropertyGet node) {
+ node.receiver = _handleExpression(node.receiver);
+ return const EvaluationComplexity.lazy();
}
@override
- InitializerComplexity visitDirectPropertySet(ir.DirectPropertySet node) {
- visitNode(node.receiver);
- visitNode(node.value);
- return const InitializerComplexity.lazy();
+ EvaluationComplexity visitDirectPropertySet(ir.DirectPropertySet node) {
+ node.receiver = _handleExpression(node.receiver);
+ node.value = _handleExpression(node.value);
+ return const EvaluationComplexity.lazy();
}
@override
- InitializerComplexity visitNot(ir.Not node) {
- return visitNode(node.operand);
+ EvaluationComplexity visitNot(ir.Not node) {
+ node.operand = _handleExpression(node.operand);
+ EvaluationComplexity complexity = _lastExpressionComplexity;
+ if (complexity.isConstant) {
+ return _evaluateImplicitConstant(node);
+ }
+ return complexity;
}
@override
- InitializerComplexity visitLogicalExpression(ir.LogicalExpression node) {
- InitializerComplexity complexity = visitNode(node.left);
- return complexity.combine(visitNode(node.right));
+ EvaluationComplexity visitLogicalExpression(ir.LogicalExpression node) {
+ node.left = _handleExpression(node.left);
+ EvaluationComplexity leftComplexity = _lastExpressionComplexity;
+
+ node.right = _handleExpression(node.right);
+ EvaluationComplexity rightComplexity = _lastExpressionComplexity;
+
+ EvaluationComplexity complexity = leftComplexity.combine(rightComplexity);
+ if (complexity.isConstant) {
+ return _evaluateImplicitConstant(node);
+ }
+ return complexity;
}
@override
- InitializerComplexity visitLet(ir.Let node) {
+ EvaluationComplexity visitLet(ir.Let node) {
visitNode(node.variable);
- visitNode(node.body);
- return const InitializerComplexity.lazy();
+ node.body = _handleExpression(node.body);
+ return const EvaluationComplexity.lazy();
}
@override
- InitializerComplexity visitBlockExpression(ir.BlockExpression node) {
+ EvaluationComplexity visitBlockExpression(ir.BlockExpression node) {
visitNode(node.body);
- visitNode(node.value);
- return const InitializerComplexity.lazy();
+ node.value = _handleExpression(node.value);
+ return const EvaluationComplexity.lazy();
}
@override
- InitializerComplexity visitCatch(ir.Catch node) {
+ EvaluationComplexity visitCatch(ir.Catch node) {
visitInContext(node.guard, VariableUse.explicit);
- visitNode(node.exception);
- visitNode(node.stackTrace);
+ if (node.exception != null) {
+ visitNode(node.exception);
+ }
+ if (node.stackTrace != null) {
+ visitNode(node.stackTrace);
+ }
visitInVariableScope(node, () {
visitNode(node.body);
});
- return const InitializerComplexity.lazy();
+ return const EvaluationComplexity.lazy();
}
@override
- InitializerComplexity visitInstantiation(ir.Instantiation node) {
- InitializerComplexity complexity = visitNodesInContext(
+ EvaluationComplexity visitInstantiation(ir.Instantiation node) {
+ EvaluationComplexity typeArgumentsComplexity = visitNodesInContext(
node.typeArguments, new VariableUse.instantiationTypeArgument(node));
- return complexity.combine(visitNode(node.expression));
+ node.expression = _handleExpression(node.expression);
+ EvaluationComplexity expressionComplexity = _lastExpressionComplexity;
+
+ EvaluationComplexity complexity =
+ typeArgumentsComplexity.combine(expressionComplexity);
+ if (complexity.isConstant) {
+ return _evaluateImplicitConstant(node);
+ }
+ return complexity;
}
@override
- InitializerComplexity visitThrow(ir.Throw node) {
- visitNode(node.expression);
- return const InitializerComplexity.lazy();
+ EvaluationComplexity visitThrow(ir.Throw node) {
+ node.expression = _handleExpression(node.expression);
+ return const EvaluationComplexity.lazy();
}
@override
- InitializerComplexity visitRethrow(ir.Rethrow node) =>
- const InitializerComplexity.lazy();
+ EvaluationComplexity visitRethrow(ir.Rethrow node) =>
+ const EvaluationComplexity.lazy();
@override
- InitializerComplexity visitBlock(ir.Block node) {
+ EvaluationComplexity visitBlock(ir.Block node) {
visitNodes(node.statements);
- return const InitializerComplexity.lazy();
+ return const EvaluationComplexity.lazy();
}
@override
- InitializerComplexity visitAssertStatement(ir.AssertStatement node) {
+ EvaluationComplexity visitAssertStatement(ir.AssertStatement node) {
visitInVariableScope(node, () {
- visitNode(node.condition);
- visitNode(node.message);
+ node.condition = _handleExpression(node.condition);
+ if (node.message != null) {
+ node.message = _handleExpression(node.message);
+ }
});
- return const InitializerComplexity.lazy();
+ return const EvaluationComplexity.lazy();
}
@override
- InitializerComplexity visitReturnStatement(ir.ReturnStatement node) {
- visitNode(node.expression);
- return const InitializerComplexity.lazy();
+ EvaluationComplexity visitReturnStatement(ir.ReturnStatement node) {
+ if (node.expression != null) {
+ node.expression = _handleExpression(node.expression);
+ }
+ return const EvaluationComplexity.lazy();
}
@override
- InitializerComplexity visitEmptyStatement(ir.EmptyStatement node) {
- return const InitializerComplexity.lazy();
+ EvaluationComplexity visitEmptyStatement(ir.EmptyStatement node) {
+ return const EvaluationComplexity.lazy();
}
@override
- InitializerComplexity visitExpressionStatement(ir.ExpressionStatement node) {
- visitNode(node.expression);
- return const InitializerComplexity.lazy();
+ EvaluationComplexity visitExpressionStatement(ir.ExpressionStatement node) {
+ node.expression = _handleExpression(node.expression);
+ return const EvaluationComplexity.lazy();
}
@override
- InitializerComplexity visitSwitchStatement(ir.SwitchStatement node) {
- visitNode(node.expression);
+ EvaluationComplexity visitSwitchStatement(ir.SwitchStatement node) {
+ node.expression = _handleExpression(node.expression);
visitInVariableScope(node, () {
visitNodes(node.cases);
});
- return const InitializerComplexity.lazy();
+ return const EvaluationComplexity.lazy();
}
@override
- InitializerComplexity visitSwitchCase(ir.SwitchCase node) {
+ EvaluationComplexity visitSwitchCase(ir.SwitchCase node) {
visitNode(node.body);
- return const InitializerComplexity.lazy();
+ return const EvaluationComplexity.lazy();
}
@override
- InitializerComplexity visitContinueSwitchStatement(
+ EvaluationComplexity visitContinueSwitchStatement(
ir.ContinueSwitchStatement node) {
registerContinueSwitch();
- return const InitializerComplexity.lazy();
+ return const EvaluationComplexity.lazy();
}
@override
- InitializerComplexity visitBreakStatement(ir.BreakStatement node) {
- return const InitializerComplexity.lazy();
+ EvaluationComplexity visitBreakStatement(ir.BreakStatement node) {
+ return const EvaluationComplexity.lazy();
}
@override
- InitializerComplexity visitLabeledStatement(ir.LabeledStatement node) {
+ EvaluationComplexity visitLabeledStatement(ir.LabeledStatement node) {
visitNode(node.body);
- return const InitializerComplexity.lazy();
+ return const EvaluationComplexity.lazy();
}
@override
- InitializerComplexity visitFieldInitializer(ir.FieldInitializer node) {
- visitNode(node.value);
- return const InitializerComplexity.lazy();
+ EvaluationComplexity visitFieldInitializer(ir.FieldInitializer node) {
+ node.value = _handleExpression(node.value);
+ return const EvaluationComplexity.lazy();
}
@override
- InitializerComplexity visitLocalInitializer(ir.LocalInitializer node) {
- visitNode(node.variable.initializer);
- return const InitializerComplexity.lazy();
+ EvaluationComplexity visitLocalInitializer(ir.LocalInitializer node) {
+ node.variable.initializer = _handleExpression(node.variable.initializer);
+ return const EvaluationComplexity.lazy();
}
@override
- InitializerComplexity visitSuperInitializer(ir.SuperInitializer node) {
+ EvaluationComplexity visitSuperInitializer(ir.SuperInitializer node) {
if (node.arguments.types.isNotEmpty) {
visitNodesInContext(node.arguments.types,
new VariableUse.constructorTypeArgument(node.target));
}
- visitNodes(node.arguments.positional);
- visitNodes(node.arguments.named);
- return const InitializerComplexity.lazy();
+ visitArguments(node.arguments);
+ return const EvaluationComplexity.lazy();
}
@override
- InitializerComplexity visitRedirectingInitializer(
+ EvaluationComplexity visitRedirectingInitializer(
ir.RedirectingInitializer node) {
if (node.arguments.types.isNotEmpty) {
visitNodesInContext(node.arguments.types,
new VariableUse.constructorTypeArgument(node.target));
}
- visitNodes(node.arguments.positional);
- visitNodes(node.arguments.named);
- return const InitializerComplexity.lazy();
+ visitArguments(node.arguments);
+ return const EvaluationComplexity.lazy();
}
@override
- InitializerComplexity visitAssertInitializer(ir.AssertInitializer node) {
+ EvaluationComplexity visitAssertInitializer(ir.AssertInitializer node) {
visitNode(node.statement);
- return const InitializerComplexity.lazy();
+ return const EvaluationComplexity.lazy();
}
@override
- InitializerComplexity visitIfStatement(ir.IfStatement node) {
- visitNode(node.condition);
+ EvaluationComplexity visitIfStatement(ir.IfStatement node) {
+ EvaluationComplexity conditionComplexity = visitNode(node.condition);
+ if (conditionComplexity.isFreshConstant) {}
visitNode(node.then);
- visitNode(node.otherwise);
- return const InitializerComplexity.lazy();
+ if (node.otherwise != null) {
+ visitNode(node.otherwise);
+ }
+ return const EvaluationComplexity.lazy();
}
@override
- InitializerComplexity visitConstantExpression(ir.ConstantExpression node) {
+ EvaluationComplexity visitConstantExpression(ir.ConstantExpression node) {
if (node.constant is ir.UnevaluatedConstant) {
node.constant = _constantEvaluator.evaluate(_staticTypeContext, node);
}
- return const InitializerComplexity.constant();
+ return const EvaluationComplexity.constant();
}
/// Returns true if the node is a field, or a constructor (factory or
@@ -1156,30 +1321,31 @@
definitelyLazy,
}
-class InitializerComplexity {
+class EvaluationComplexity {
final ComplexityLevel level;
final Set<ir.Field> fields;
+ final ir.Constant constant;
- // TODO(johnniwinther): This should hold the constant literal from CFE when
- // provided.
- const InitializerComplexity.constant()
+ const EvaluationComplexity.constant([this.constant])
: level = ComplexityLevel.constant,
fields = null;
// TODO(johnniwinther): Use this to collect data on the size of the
// initializer.
- InitializerComplexity.eager({this.fields})
- : level = ComplexityLevel.potentiallyEager;
+ EvaluationComplexity.eager({this.fields})
+ : level = ComplexityLevel.potentiallyEager,
+ constant = null;
- const InitializerComplexity.lazy()
+ const EvaluationComplexity.lazy()
: level = ComplexityLevel.definitelyLazy,
- fields = null;
+ fields = null,
+ constant = null;
- InitializerComplexity combine(InitializerComplexity other) {
+ EvaluationComplexity combine(EvaluationComplexity other) {
if (identical(this, other)) {
return this;
} else if (isLazy || other.isLazy) {
- return const InitializerComplexity.lazy();
+ return const EvaluationComplexity.lazy();
} else if (isEager || other.isEager) {
if (fields != null && other.fields != null) {
fields.addAll(other.fields);
@@ -1190,9 +1356,7 @@
return other;
}
} else if (isConstant && other.isConstant) {
- // TODO(johnniwinther): This is case doesn't work if InitializerComplexity
- // objects of constant complexity hold the constant literal.
- return this;
+ return const EvaluationComplexity.constant();
} else if (isEager) {
assert(other.isConstant);
return this;
@@ -1203,16 +1367,18 @@
}
}
- InitializerComplexity makeEager() {
+ EvaluationComplexity makeEager() {
if (isLazy || isEager) {
return this;
} else {
- return new InitializerComplexity.eager();
+ return new EvaluationComplexity.eager();
}
}
bool get isConstant => level == ComplexityLevel.constant;
+ bool get isFreshConstant => isConstant && constant != null;
+
bool get isEager => level == ComplexityLevel.potentiallyEager;
bool get isLazy => level == ComplexityLevel.definitelyLazy;
diff --git a/pkg/compiler/lib/src/ir/static_type.dart b/pkg/compiler/lib/src/ir/static_type.dart
index a5ab288..9180994 100644
--- a/pkg/compiler/lib/src/ir/static_type.dart
+++ b/pkg/compiler/lib/src/ir/static_type.dart
@@ -13,6 +13,7 @@
import 'scope.dart';
import 'static_type_base.dart';
import 'static_type_cache.dart';
+import 'util.dart';
/// Enum values for how the target of a static type should be interpreted.
enum ClassRelation {
@@ -706,7 +707,7 @@
ir.Expression right = node.arguments.positional[0];
TypeMap afterInvocation = typeMap;
if (left is ir.VariableGet &&
- right is ir.NullLiteral &&
+ isNullLiteral(right) &&
!_invalidatedVariables.contains(left.variable)) {
// If `left == null` is true, we promote the type of the variable to
// `Null` by registering that is known _not_ to be of its declared type.
@@ -716,7 +717,7 @@
.promote(left.variable, left.variable.type, isTrue: true);
}
if (right is ir.VariableGet &&
- left is ir.NullLiteral &&
+ isNullLiteral(left) &&
!_invalidatedVariables.contains(right.variable)) {
// If `null == right` is true, we promote the type of the variable to
// `Null` by registering that is known _not_ to be of its declared type.
diff --git a/pkg/compiler/lib/src/ir/util.dart b/pkg/compiler/lib/src/ir/util.dart
index d963863..15d7550 100644
--- a/pkg/compiler/lib/src/ir/util.dart
+++ b/pkg/compiler/lib/src/ir/util.dart
@@ -83,6 +83,12 @@
}
}
+/// Returns `true` if [node] is a null literal or a null constant.
+bool isNullLiteral(ir.Expression node) {
+ return node is ir.NullLiteral ||
+ (node is ir.ConstantExpression && node.constant is ir.NullConstant);
+}
+
/// Kernel encodes a null-aware expression `a?.b` as
///
/// let final #1 = a in #1 == null ? null : #1.b
@@ -117,13 +123,13 @@
node.variable.isFinal &&
body is ir.ConditionalExpression &&
body.condition is ir.MethodInvocation &&
- body.then is ir.NullLiteral) {
+ isNullLiteral(body.then)) {
ir.MethodInvocation invocation = body.condition;
ir.Expression receiver = invocation.receiver;
if (invocation.name.text == '==' &&
receiver is ir.VariableGet &&
receiver.variable == node.variable &&
- invocation.arguments.positional.single is ir.NullLiteral) {
+ isNullLiteral(invocation.arguments.positional.single)) {
// We have
// let #t1 = e0 in #t1 == null ? null : e1
return new NullAwareExpression(node.variable, body.otherwise);
diff --git a/pkg/compiler/lib/src/js_backend/field_analysis.dart b/pkg/compiler/lib/src/js_backend/field_analysis.dart
index a40b882..ac07284 100644
--- a/pkg/compiler/lib/src/js_backend/field_analysis.dart
+++ b/pkg/compiler/lib/src/js_backend/field_analysis.dart
@@ -124,7 +124,7 @@
_classData[class_] = new ClassData(constructors, fieldData);
}
- void registerStaticField(KField field, InitializerComplexity complexity) {
+ void registerStaticField(KField field, EvaluationComplexity complexity) {
ir.Field node = _elementMap.getMemberNode(field);
ir.Expression expression = node.initializer;
ConstantValue value = _elementMap.getConstantValue(
@@ -156,7 +156,7 @@
class StaticFieldData {
final ConstantValue initialValue;
- final InitializerComplexity complexity;
+ final EvaluationComplexity complexity;
StaticFieldData(this.initialValue, this.complexity);
@@ -468,7 +468,7 @@
if (!isEager) {
// The field might be eager depending on the initializer complexity
// and its dependencies.
- InitializerComplexity complexity = staticFieldData.complexity;
+ EvaluationComplexity complexity = staticFieldData.complexity;
isEager = complexity?.isEager ?? false;
if (isEager && complexity.fields != null) {
for (ir.Field node in complexity.fields) {
diff --git a/pkg/compiler/lib/src/js_model/element_map.dart b/pkg/compiler/lib/src/js_model/element_map.dart
index 10bb603..18cde59 100644
--- a/pkg/compiler/lib/src/js_model/element_map.dart
+++ b/pkg/compiler/lib/src/js_model/element_map.dart
@@ -520,7 +520,7 @@
ir.Field node = definition.node;
if (node.isInstanceMember &&
!node.isFinal &&
- node.initializer is ir.NullLiteral) {
+ isNullLiteral(node.initializer)) {
return null;
}
return node.initializer;
diff --git a/pkg/compiler/lib/src/kernel/element_map_impl.dart b/pkg/compiler/lib/src/kernel/element_map_impl.dart
index ab22c77..d4fba7c 100644
--- a/pkg/compiler/lib/src/kernel/element_map_impl.dart
+++ b/pkg/compiler/lib/src/kernel/element_map_impl.dart
@@ -1558,6 +1558,12 @@
ir.Node argument = node.arguments.positional.first;
if (argument is ir.TypeLiteral && argument.type is ir.InterfaceType) {
return getInterfaceType(argument.type);
+ } else if (argument is ir.ConstantExpression &&
+ argument.constant is ir.TypeLiteralConstant) {
+ ir.TypeLiteralConstant constant = argument.constant;
+ if (constant.type is ir.InterfaceType) {
+ return getInterfaceType(constant.type);
+ }
}
return null;
}
diff --git a/pkg/compiler/lib/src/ssa/builder_kernel.dart b/pkg/compiler/lib/src/ssa/builder_kernel.dart
index b3b3e6f..b169612 100644
--- a/pkg/compiler/lib/src/ssa/builder_kernel.dart
+++ b/pkg/compiler/lib/src/ssa/builder_kernel.dart
@@ -4108,10 +4108,44 @@
}
}
- void _handleCreateInvocationMirror(ir.StaticInvocation invocation) {
- ir.StringLiteral nameLiteral = invocation.arguments.positional[0];
- String name = nameLiteral.value;
+ String _readStringLiteral(ir.Expression node) {
+ if (node is ir.StringLiteral) {
+ return node.value;
+ } else if (node is ir.ConstantExpression &&
+ node.constant is ir.StringConstant) {
+ ir.StringConstant constant = node.constant;
+ return constant.value;
+ } else {
+ return reporter.internalError(
+ _elementMap.getSpannable(targetElement, node),
+ "Unexpected string literal: "
+ "${node is ir.ConstantExpression ? node.constant : node}");
+ }
+ }
+ int _readIntLiteral(ir.Expression node) {
+ if (node is ir.IntLiteral) {
+ return node.value;
+ } else if (node is ir.ConstantExpression &&
+ node.constant is ir.IntConstant) {
+ ir.IntConstant constant = node.constant;
+ return constant.value;
+ } else if (node is ir.ConstantExpression &&
+ node.constant is ir.DoubleConstant) {
+ ir.DoubleConstant constant = node.constant;
+ assert(constant.value.floor() == constant.value,
+ "Unexpected int literal value ${constant.value}.");
+ return constant.value.toInt();
+ } else {
+ return reporter.internalError(
+ _elementMap.getSpannable(targetElement, node),
+ "Unexpected int literal: "
+ "${node is ir.ConstantExpression ? node.constant : node}");
+ }
+ }
+
+ void _handleCreateInvocationMirror(ir.StaticInvocation invocation) {
+ String name = _readStringLiteral(invocation.arguments.positional[0]);
ir.ListLiteral typeArgumentsLiteral = invocation.arguments.positional[1];
List<DartType> typeArguments =
typeArgumentsLiteral.expressions.map((ir.Expression expression) {
@@ -4123,11 +4157,11 @@
invocation.arguments.positional[2];
ir.Expression namedArgumentsLiteral = invocation.arguments.positional[3];
Map<String, ir.Expression> namedArguments = {};
- ir.IntLiteral kindLiteral = invocation.arguments.positional[4];
+ int kind = _readIntLiteral(invocation.arguments.positional[4]);
Name memberName = new Name(name, _currentFrame.member.library);
Selector selector;
- switch (kindLiteral.value) {
+ switch (kind) {
case invocationMirrorGetterKind:
selector = new Selector.getter(memberName);
break;
@@ -4142,8 +4176,8 @@
} else {
if (namedArgumentsLiteral is ir.MapLiteral) {
namedArgumentsLiteral.entries.forEach((ir.MapEntry entry) {
- ir.StringLiteral key = entry.key;
- namedArguments[key.value] = entry.value;
+ String key = _readStringLiteral(entry.key);
+ namedArguments[key] = entry.value;
});
} else if (namedArgumentsLiteral is ir.ConstantExpression &&
namedArgumentsLiteral.constant is ir.MapConstant) {
@@ -6871,6 +6905,11 @@
visitConstantExpression(ir.ConstantExpression node) {
registerRegularNode();
registerReductiveNode();
+ ir.Constant constant = node.constant;
+ // Avoid copying long strings into call site.
+ if (constant is ir.StringConstant && isLongString(constant.value)) {
+ data.hasLongString = true;
+ }
}
@override
@@ -7014,12 +7053,16 @@
node.visitChildren(this);
}
+ /// Returns `true` if [value] is considered a long string for which copying
+ /// should be avoided.
+ bool isLongString(String value) => value.length > 14;
+
@override
visitStringLiteral(ir.StringLiteral node) {
registerRegularNode();
registerReductiveNode();
// Avoid copying long strings into call site.
- if (node.value.length > 14) {
+ if (isLongString(node.value)) {
data.hasLongString = true;
}
}
diff --git a/pkg/compiler/test/analyses/analysis_helper.dart b/pkg/compiler/test/analyses/analysis_helper.dart
index 90a11a2..eee894d 100644
--- a/pkg/compiler/test/analyses/analysis_helper.dart
+++ b/pkg/compiler/test/analyses/analysis_helper.dart
@@ -14,10 +14,10 @@
import 'package:compiler/src/diagnostics/diagnostic_listener.dart';
import 'package:compiler/src/diagnostics/messages.dart';
import 'package:compiler/src/diagnostics/source_span.dart';
+import 'package:compiler/src/ir/constants.dart';
import 'package:compiler/src/ir/scope.dart';
import 'package:compiler/src/ir/static_type.dart';
import 'package:compiler/src/ir/util.dart';
-import 'package:compiler/src/kernel/dart2js_target.dart';
import 'package:compiler/src/kernel/loader.dart';
import 'package:expect/expect.dart';
import 'package:front_end/src/api_prototype/constant_evaluator.dart' as ir;
@@ -75,21 +75,21 @@
@override
VariableScopeModel variableScopeModel;
- ir.ConstantEvaluator _constantEvaluator;
+ Dart2jsConstantEvaluator _constantEvaluator;
@override
ir.StaticTypeContext staticTypeContext;
StaticTypeVisitorBase(
- ir.Component component, ir.ClassHierarchy classHierarchy)
- : super(
+ ir.Component component, ir.ClassHierarchy classHierarchy,
+ {ir.EvaluationMode evaluationMode})
+ : assert(evaluationMode != null),
+ super(
new ir.TypeEnvironment(new ir.CoreTypes(component), classHierarchy),
classHierarchy) {
- _constantEvaluator = new ir.ConstantEvaluator(
- const Dart2jsConstantsBackend(supportsUnevaluatedConstants: true),
- const {},
- typeEnvironment,
- const ir.SimpleErrorReporter());
+ _constantEvaluator = new Dart2jsConstantEvaluator(
+ typeEnvironment, const ir.SimpleErrorReporter().report,
+ evaluationMode: evaluationMode);
}
@override
@@ -149,7 +149,8 @@
DynamicVisitor(this.reporter, this.component, this._allowedListPath,
this.analyzedUrisFilter)
: super(component,
- new ir.ClassHierarchy(component, new ir.CoreTypes(component)));
+ new ir.ClassHierarchy(component, new ir.CoreTypes(component)),
+ evaluationMode: ir.EvaluationMode.weak);
void run({bool verbose = false, bool generate = false}) {
if (!generate && _allowedListPath != null) {
diff --git a/pkg/compiler/test/analyses/static_type_visitor_test.dart b/pkg/compiler/test/analyses/static_type_visitor_test.dart
index 9fb7a2b..72b7143 100644
--- a/pkg/compiler/test/analyses/static_type_visitor_test.dart
+++ b/pkg/compiler/test/analyses/static_type_visitor_test.dart
@@ -12,6 +12,7 @@
import 'package:kernel/class_hierarchy.dart' as ir;
import 'package:kernel/core_types.dart' as ir;
import 'package:kernel/type_environment.dart' as ir;
+import 'package:front_end/src/api_prototype/constant_evaluator.dart' as ir;
import '../helpers/memory_compiler.dart';
import 'analysis_helper.dart';
@@ -35,7 +36,8 @@
class Visitor extends StaticTypeVisitorBase {
Visitor(ir.Component component)
: super(component,
- new ir.ClassHierarchy(component, new ir.CoreTypes(component)));
+ new ir.ClassHierarchy(component, new ir.CoreTypes(component)),
+ evaluationMode: ir.EvaluationMode.weak);
ir.DartType getStaticType(ir.Expression node) {
if (typeEnvironment == null) {
diff --git a/pkg/compiler/test/deferred/dont_inline_deferred_constants_test.dart b/pkg/compiler/test/deferred/dont_inline_deferred_constants_test.dart
index 284a1f5..a7fca88 100644
--- a/pkg/compiler/test/deferred/dont_inline_deferred_constants_test.dart
+++ b/pkg/compiler/test/deferred/dont_inline_deferred_constants_test.dart
@@ -18,10 +18,7 @@
'DeferredGlobalConstant(StringConstant("string1"))': {'lib1'},
'DeferredGlobalConstant(StringConstant("string2"))': {'lib1'},
// "string4" is shared between lib1 and lib2, but it can be inlined.
- 'DeferredGlobalConstant(StringConstant("string4"))':
- // TODO(johnniwinther): Should we inline CFE constants within deferred
- // library boundaries?
- {'lib12'},
+ 'DeferredGlobalConstant(StringConstant("string4"))': {},
// C(1) is shared between main, lib1 and lib2. Test that lib1 and lib2
// each has a reference to it. It is defined in the main output file.
'ConstructedConstant(C(p=IntConstant(1)))': {'main'},
diff --git a/pkg/compiler/test/deferred/not_in_main_test.dart b/pkg/compiler/test/deferred/not_in_main_test.dart
index 9550547..11e92a3 100644
--- a/pkg/compiler/test/deferred/not_in_main_test.dart
+++ b/pkg/compiler/test/deferred/not_in_main_test.dart
@@ -156,7 +156,7 @@
typedef void F(x);
main() {
- print(foo is F);
+ print(getFoo() is F);
def.loadLibrary().then((_) {
def.toto();
});
@@ -171,6 +171,7 @@
class A {}
class B extends A {}
foo(B b) => null;
+getFoo() => foo;
""",
};
@@ -207,7 +208,8 @@
import 'shared.dart';
main() {
- print(5 is A);
+ var v = 5;
+ print(v is A);
def.loadLibrary().then((_) {
def.toto();
});
diff --git a/pkg/compiler/test/deferred_loading/data/instantiation0/lib1.dart b/pkg/compiler/test/deferred_loading/data/instantiation0/lib1.dart
index 433780c..3904f05 100644
--- a/pkg/compiler/test/deferred_loading/data/instantiation0/lib1.dart
+++ b/pkg/compiler/test/deferred_loading/data/instantiation0/lib1.dart
@@ -9,7 +9,11 @@
typedef dynamic G<T>(T v);
-/*member: m:OutputUnit(1, {b}),constants=[InstantiationConstant([int*],FunctionConstant(getFoo))=OutputUnit(1, {b})]*/
+/*member: m:
+ OutputUnit(1, {b}),
+ constants=[
+ InstantiationConstant([int*],FunctionConstant(getFoo))=OutputUnit(1, {b})]
+*/
m(int x, {G<int> f: getFoo}) {
print(f(x));
}
diff --git a/pkg/compiler/test/deferred_loading/data/instantiation1/lib1.dart b/pkg/compiler/test/deferred_loading/data/instantiation1/lib1.dart
index 433780c..3904f05 100644
--- a/pkg/compiler/test/deferred_loading/data/instantiation1/lib1.dart
+++ b/pkg/compiler/test/deferred_loading/data/instantiation1/lib1.dart
@@ -9,7 +9,11 @@
typedef dynamic G<T>(T v);
-/*member: m:OutputUnit(1, {b}),constants=[InstantiationConstant([int*],FunctionConstant(getFoo))=OutputUnit(1, {b})]*/
+/*member: m:
+ OutputUnit(1, {b}),
+ constants=[
+ InstantiationConstant([int*],FunctionConstant(getFoo))=OutputUnit(1, {b})]
+*/
m(int x, {G<int> f: getFoo}) {
print(f(x));
}
diff --git a/pkg/compiler/test/deferred_loading/data/instantiation1/lib2.dart b/pkg/compiler/test/deferred_loading/data/instantiation1/lib2.dart
index 9c63363..e0ae1fb 100644
--- a/pkg/compiler/test/deferred_loading/data/instantiation1/lib2.dart
+++ b/pkg/compiler/test/deferred_loading/data/instantiation1/lib2.dart
@@ -9,7 +9,11 @@
typedef dynamic G<T, S>(T v, S w);
-/*member: m:OutputUnit(3, {c}),constants=[InstantiationConstant([int*, int*],FunctionConstant(getFoo))=OutputUnit(3, {c})]*/
+/*member: m:
+ OutputUnit(3, {c}),
+ constants=[
+ InstantiationConstant([int*, int*],FunctionConstant(getFoo))=OutputUnit(3, {c})]
+*/
m(int x, int y, {G<int, int> f: getFoo}) {
print(f(x, y));
}
diff --git a/pkg/compiler/test/deferred_loading/data/instantiation2/lib1.dart b/pkg/compiler/test/deferred_loading/data/instantiation2/lib1.dart
index 0f2e5f7..75e44c2 100644
--- a/pkg/compiler/test/deferred_loading/data/instantiation2/lib1.dart
+++ b/pkg/compiler/test/deferred_loading/data/instantiation2/lib1.dart
@@ -9,7 +9,11 @@
typedef dynamic G<T>(T v);
-/*member: m:OutputUnit(2, {b}),constants=[InstantiationConstant([int*],FunctionConstant(getFoo))=OutputUnit(2, {b})]*/
+/*member: m:
+ OutputUnit(2, {b}),
+ constants=[
+ InstantiationConstant([int*],FunctionConstant(getFoo))=OutputUnit(2, {b})]
+*/
m(int x, {G<int> f: getFoo}) {
print(f(x));
}
diff --git a/pkg/compiler/test/deferred_loading/data/instantiation2/lib2.dart b/pkg/compiler/test/deferred_loading/data/instantiation2/lib2.dart
index 1d845e3..c81081d 100644
--- a/pkg/compiler/test/deferred_loading/data/instantiation2/lib2.dart
+++ b/pkg/compiler/test/deferred_loading/data/instantiation2/lib2.dart
@@ -9,7 +9,11 @@
typedef dynamic G<T>(T v);
-/*member: m:OutputUnit(3, {c}),constants=[InstantiationConstant([int*],FunctionConstant(getFoo))=OutputUnit(3, {c})]*/
+/*member: m:
+ OutputUnit(3, {c}),
+ constants=[
+ InstantiationConstant([int*],FunctionConstant(getFoo))=OutputUnit(3, {c})]
+*/
m(int x, {G<int> f: getFoo}) {
print(f(x));
}
diff --git a/pkg/compiler/test/deferred_loading/data/instantiation3/lib1.dart b/pkg/compiler/test/deferred_loading/data/instantiation3/lib1.dart
index 7f641b8..843596b 100644
--- a/pkg/compiler/test/deferred_loading/data/instantiation3/lib1.dart
+++ b/pkg/compiler/test/deferred_loading/data/instantiation3/lib1.dart
@@ -11,7 +11,8 @@
/*member: m:
OutputUnit(1, {b}),
- constants=[FunctionConstant(getFoo)=OutputUnit(1, {b})]
+ constants=[
+ InstantiationConstant([int*],FunctionConstant(getFoo))=OutputUnit(1, {b})]
*/
m(int x, {G<int> f}) {
f ??= getFoo;
diff --git a/pkg/compiler/test/deferred_loading/data/instantiation4/lib1.dart b/pkg/compiler/test/deferred_loading/data/instantiation4/lib1.dart
index 4359611..57e5118 100644
--- a/pkg/compiler/test/deferred_loading/data/instantiation4/lib1.dart
+++ b/pkg/compiler/test/deferred_loading/data/instantiation4/lib1.dart
@@ -9,7 +9,7 @@
typedef dynamic G<T>(T v);
-/*member: m:OutputUnit(1, {b}),constants=[FunctionConstant(getFoo)=OutputUnit(1, {b})]*/
+/*member: m:OutputUnit(1, {b}),constants=[InstantiationConstant([int*],FunctionConstant(getFoo))=OutputUnit(1, {b})]*/
m(int x, {G<int> f}) {
f ??= getFoo;
print(f(x));
diff --git a/pkg/compiler/test/deferred_loading/data/instantiation4/lib2.dart b/pkg/compiler/test/deferred_loading/data/instantiation4/lib2.dart
index b346bb4..99d9dcd 100644
--- a/pkg/compiler/test/deferred_loading/data/instantiation4/lib2.dart
+++ b/pkg/compiler/test/deferred_loading/data/instantiation4/lib2.dart
@@ -11,7 +11,8 @@
/*member: m:
OutputUnit(3, {c}),
- constants=[FunctionConstant(getFoo)=OutputUnit(3, {c})]
+ constants=[
+ InstantiationConstant([int*, int*],FunctionConstant(getFoo))=OutputUnit(3, {c})]
*/
m(int x, int y, {G<int, int> f}) {
f ??= getFoo;
diff --git a/pkg/compiler/test/deferred_loading/data/instantiation5/lib1.dart b/pkg/compiler/test/deferred_loading/data/instantiation5/lib1.dart
index 76cebb1..562d112 100644
--- a/pkg/compiler/test/deferred_loading/data/instantiation5/lib1.dart
+++ b/pkg/compiler/test/deferred_loading/data/instantiation5/lib1.dart
@@ -11,7 +11,8 @@
/*member: m:
OutputUnit(2, {b}),
- constants=[FunctionConstant(getFoo)=OutputUnit(2, {b})]
+ constants=[
+ InstantiationConstant([int*],FunctionConstant(getFoo))=OutputUnit(2, {b})]
*/
m(int x, {G<int> f}) {
f ??= getFoo;
diff --git a/pkg/compiler/test/deferred_loading/data/instantiation5/lib2.dart b/pkg/compiler/test/deferred_loading/data/instantiation5/lib2.dart
index ee8d5ab..a2f7a32 100644
--- a/pkg/compiler/test/deferred_loading/data/instantiation5/lib2.dart
+++ b/pkg/compiler/test/deferred_loading/data/instantiation5/lib2.dart
@@ -11,7 +11,8 @@
/*member: m:
OutputUnit(3, {c}),
- constants=[FunctionConstant(getFoo)=OutputUnit(3, {c})]
+ constants=[
+ InstantiationConstant([int*],FunctionConstant(getFoo))=OutputUnit(3, {c})]
*/
m(int x, {G<int> f}) {
f ??= getFoo;
diff --git a/pkg/compiler/test/deferred_loading/data/static_separate/lib2.dart b/pkg/compiler/test/deferred_loading/data/static_separate/lib2.dart
index 52b4764..404e560 100644
--- a/pkg/compiler/test/deferred_loading/data/static_separate/lib2.dart
+++ b/pkg/compiler/test/deferred_loading/data/static_separate/lib2.dart
@@ -9,7 +9,12 @@
import "package:expect/expect.dart";
import "lib1.dart";
-/*member: foo:OutputUnit(3, {lib2}),constants=[ListConstant(<Map<int*,int*>*>[MapConstant(<int*, int*>{IntConstant(1): IntConstant(3)})])=OutputUnit(3, {lib2}),MapConstant(<int*, int*>{IntConstant(1): IntConstant(3)})=OutputUnit(3, {lib2})]*/
+/*member: foo:
+ OutputUnit(3, {lib2}),
+ constants=[
+ ListConstant(<Map<int*,int*>*>[MapConstant(<int*, int*>{IntConstant(1): IntConstant(3)})])=OutputUnit(3, {lib2}),
+ MapConstant(<int*, int*>{IntConstant(1): IntConstant(3)})=OutputUnit(3, {lib2})]
+*/
foo() {
Expect.equals(1, C.foo());
Expect.mapEquals({}, C1.foo);
diff --git a/pkg/compiler/test/field_analysis/jdata/static_initializers.dart b/pkg/compiler/test/field_analysis/jdata/static_initializers.dart
index 1b4fdf6..16ba995 100644
--- a/pkg/compiler/test/field_analysis/jdata/static_initializers.dart
+++ b/pkg/compiler/test/field_analysis/jdata/static_initializers.dart
@@ -126,8 +126,7 @@
/*member: field3g:final,lazy*/
var field3g = [method()];
-// TODO(johnniwinther): Recognize this as of eager complexity.
-/*member: field3h:final,lazy*/
+/*member: field3h:final,eager*/
var field3h = [1 + 3];
/*member: field4a:constant=IntConstant(5)*/
diff --git a/pkg/compiler/test/field_analysis/kdata/simple_initializers.dart b/pkg/compiler/test/field_analysis/kdata/simple_initializers.dart
index 929cb4c..0ca8e51 100644
--- a/pkg/compiler/test/field_analysis/kdata/simple_initializers.dart
+++ b/pkg/compiler/test/field_analysis/kdata/simple_initializers.dart
@@ -10,6 +10,7 @@
}
const bool const1 = true;
+const dynamic const2 = 42;
class Class1 {
/*member: Class1.field0:initial=NullConstant*/
@@ -56,6 +57,27 @@
/*member: Class1.field14:initial=BoolConstant(false)*/
var field14 = const1 is int;
+
+ /*member: Class1.field15:initial=IntConstant(42)*/
+ var field15 = const2 as int;
+
+ /*member: Class1.field16:initial=IntConstant(5)*/
+ var field16 = 2 + 3;
+
+ /*member: Class1.field17:initial=BoolConstant(false)*/
+ var field17 = identical(2, 3);
+
+ /*member: Class1.field18:initial=IntConstant(3)*/
+ var field18 = 'foo'.length;
+
+ /*member: Class1.field19:initial=StringConstant("23")*/
+ var field19 = '${2}${3}';
+
+ /*member: Class1.field20:initial=IntConstant(2)*/
+ var field20 = '${2}${3}'.length;
+
+ /*member: Class1.field21:initial=TypeConstant(Object)*/
+ var field21 = Object;
}
class Class2 {
@@ -101,6 +123,27 @@
/*member: Class2.field14:Class2.=BoolConstant(false),initial=NullConstant*/
var field14;
+ /*member: Class2.field15:Class2.=IntConstant(42),initial=NullConstant*/
+ var field15;
+
+ /*member: Class2.field16:Class2.=IntConstant(5),initial=NullConstant*/
+ var field16;
+
+ /*member: Class2.field17:Class2.=BoolConstant(false),initial=NullConstant*/
+ var field17;
+
+ /*member: Class2.field18:Class2.=IntConstant(3),initial=NullConstant*/
+ var field18;
+
+ /*member: Class2.field19:Class2.=StringConstant("23"),initial=NullConstant*/
+ var field19;
+
+ /*member: Class2.field20:Class2.=IntConstant(2),initial=NullConstant*/
+ var field20;
+
+ /*member: Class2.field21:Class2.=TypeConstant(Object),initial=NullConstant*/
+ var field21;
+
Class2()
: field1 = null,
field2 = true,
@@ -115,5 +158,12 @@
field11 = #foo,
field12 = 2 + 3,
field13 = const1,
- field14 = const1 is int;
+ field14 = const1 is int,
+ field15 = const2 as int,
+ field16 = 2 + 3,
+ field17 = identical(2, 3),
+ field18 = 'foo'.length,
+ field19 = '${2}${3}',
+ field20 = '${2}${3}'.length,
+ field21 = Object;
}
diff --git a/pkg/compiler/test/field_analysis/kdata/static_initializers.dart b/pkg/compiler/test/field_analysis/kdata/static_initializers.dart
index c8f2471..e573c34 100644
--- a/pkg/compiler/test/field_analysis/kdata/static_initializers.dart
+++ b/pkg/compiler/test/field_analysis/kdata/static_initializers.dart
@@ -114,15 +114,13 @@
/*member: field3g:complexity=lazy*/
var field3g = [method()];
-// TODO(johnniwinther): Recognize this as of eager complexity.
-/*member: field3h:complexity=lazy*/
+/*member: field3h:complexity=eager*/
var field3h = [1 + 3];
-// TODO(johnniwinther): Recognize `field4*` as of constant complexity.
-/*member: field4a:complexity=lazy,initial=IntConstant(5)*/
+/*member: field4a:complexity=constant,initial=IntConstant(5)*/
final field4a = 2 + 3;
-/*member: field4b:complexity=lazy,initial=IntConstant(5)*/
+/*member: field4b:complexity=constant,initial=IntConstant(5)*/
var field4b = 2 + 3;
const field4c = 2 + 3;
diff --git a/pkg/compiler/test/impact/data/expressions.dart b/pkg/compiler/test/impact/data/expressions.dart
index 7e6cdb0..5161a7a 100644
--- a/pkg/compiler/test/impact/data/expressions.dart
+++ b/pkg/compiler/test/impact/data/expressions.dart
@@ -73,13 +73,16 @@
/*member: testNot:type=[inst:JSBool]*/
testNot() => !false;
-/*member: testUnaryMinus:
- dynamic=[int.unary-],
- type=[inst:JSDouble,inst:JSInt,inst:JSNumber,inst:JSPositiveInt,inst:JSUInt31,inst:JSUInt32]
-*/
+/*member: testUnaryMinus:type=[
+ inst:JSDouble,
+ inst:JSInt,
+ inst:JSNumber,
+ inst:JSPositiveInt,
+ inst:JSUInt31,
+ inst:JSUInt32]*/
testUnaryMinus() => -1;
-/*member: testConditional:type=[inst:JSBool,inst:JSNull,inst:JSString]*/
+/*member: testConditional:type=[inst:JSNull]*/
// ignore: DEAD_CODE
testConditional() => true ? null : '';
@@ -107,634 +110,45 @@
*/
testPreDec(o) => --o;
-/*member: testIs:
- static=[
- Rti._bind(1),
- Rti._eval(1),
- _arrayInstanceType(1),
- _asBool(1),
- _asBoolQ(1),
- _asBoolS(1),
- _asDouble(1),
- _asDoubleQ(1),
- _asDoubleS(1),
- _asInt(1),
- _asIntQ(1),
- _asIntS(1),
- _asNum(1),
- _asNumQ(1),
- _asNumS(1),
- _asObject(1),
- _asString(1),
- _asStringQ(1),
- _asStringS(1),
- _asTop(1),
- _generalAsCheckImplementation(1),
- _generalIsTestImplementation(1),
- _generalNullableAsCheckImplementation(1),
- _generalNullableIsTestImplementation(1),
- _installSpecializedAsCheck(1),
- _installSpecializedIsTest(1),
- _instanceType(1),
- _isBool(1),
- _isInt(1),
- _isNum(1),
- _isObject(1),
- _isString(1),
- _isTop(1),
- findType(1),
- instanceType(1)],
- type=[
- inst:Closure,
- inst:JSBool,
- inst:JSNull,
- is:Class*]
-*/
+/*member: testIs:type=[inst:JSBool]*/
testIs() => null is Class;
-/*member: testIsGeneric:
- static=[
- Rti._bind(1),
- Rti._eval(1),
- _arrayInstanceType(1),
- _asBool(1),
- _asBoolQ(1),
- _asBoolS(1),
- _asDouble(1),
- _asDoubleQ(1),
- _asDoubleS(1),
- _asInt(1),
- _asIntQ(1),
- _asIntS(1),
- _asNum(1),
- _asNumQ(1),
- _asNumS(1),
- _asObject(1),
- _asString(1),
- _asStringQ(1),
- _asStringS(1),
- _asTop(1),
- _generalAsCheckImplementation(1),
- _generalIsTestImplementation(1),
- _generalNullableAsCheckImplementation(1),
- _generalNullableIsTestImplementation(1),
- _installSpecializedAsCheck(1),
- _installSpecializedIsTest(1),
- _instanceType(1),
- _isBool(1),
- _isInt(1),
- _isNum(1),
- _isObject(1),
- _isString(1),
- _isTop(1),
- findType(1),
- instanceType(1),
- setRuntimeTypeInfo(2)],
- type=[
- inst:Closure,
- inst:JSArray<dynamic>,
- inst:JSBool,
- inst:JSExtendableArray<dynamic>,
- inst:JSFixedArray<dynamic>,
- inst:JSMutableArray<dynamic>,
- inst:JSNull,
- inst:JSUnmodifiableArray<dynamic>,
- is:GenericClass<int*,String*>*]
-*/
+/*member: testIsGeneric:type=[inst:JSBool]*/
testIsGeneric() => null is GenericClass<int, String>;
-/*member: testIsGenericRaw:
- static=[
- Rti._bind(1),
- Rti._eval(1),
- _arrayInstanceType(1),
- _asBool(1),
- _asBoolQ(1),
- _asBoolS(1),
- _asDouble(1),
- _asDoubleQ(1),
- _asDoubleS(1),
- _asInt(1),
- _asIntQ(1),
- _asIntS(1),
- _asNum(1),
- _asNumQ(1),
- _asNumS(1),
- _asObject(1),
- _asString(1),
- _asStringQ(1),
- _asStringS(1),
- _asTop(1),
- _generalAsCheckImplementation(1),
- _generalIsTestImplementation(1),
- _generalNullableAsCheckImplementation(1),
- _generalNullableIsTestImplementation(1),
- _installSpecializedAsCheck(1),
- _installSpecializedIsTest(1),
- _instanceType(1),
- _isBool(1),
- _isInt(1),
- _isNum(1),
- _isObject(1),
- _isString(1),
- _isTop(1),
- findType(1),
- instanceType(1)],
- type=[
- inst:Closure,
- inst:JSBool,
- inst:JSNull,
- is:GenericClass<dynamic,dynamic>*]
-*/
+/*member: testIsGenericRaw:type=[inst:JSBool]*/
testIsGenericRaw() => null is GenericClass;
-/*member: testIsGenericDynamic:
- static=[
- Rti._bind(1),
- Rti._eval(1),
- _arrayInstanceType(1),
- _asBool(1),
- _asBoolQ(1),
- _asBoolS(1),
- _asDouble(1),
- _asDoubleQ(1),
- _asDoubleS(1),
- _asInt(1),
- _asIntQ(1),
- _asIntS(1),
- _asNum(1),
- _asNumQ(1),
- _asNumS(1),
- _asObject(1),
- _asString(1),
- _asStringQ(1),
- _asStringS(1),
- _asTop(1),
- _generalAsCheckImplementation(1),
- _generalIsTestImplementation(1),
- _generalNullableAsCheckImplementation(1),
- _generalNullableIsTestImplementation(1),
- _installSpecializedAsCheck(1),
- _installSpecializedIsTest(1),
- _instanceType(1),
- _isBool(1),
- _isInt(1),
- _isNum(1),
- _isObject(1),
- _isString(1),
- _isTop(1),
- findType(1),
- instanceType(1)],
- type=[
- inst:Closure,
- inst:JSBool,
- inst:JSNull,
- is:GenericClass<dynamic,dynamic>*]
-*/
+/*member: testIsGenericDynamic:type=[inst:JSBool]*/
testIsGenericDynamic() => null is GenericClass<dynamic, dynamic>;
-/*member: testIsNot:
- static=[
- Rti._bind(1),
- Rti._eval(1),
- _arrayInstanceType(1),
- _asBool(1),
- _asBoolQ(1),
- _asBoolS(1),
- _asDouble(1),
- _asDoubleQ(1),
- _asDoubleS(1),
- _asInt(1),
- _asIntQ(1),
- _asIntS(1),
- _asNum(1),
- _asNumQ(1),
- _asNumS(1),
- _asObject(1),
- _asString(1),
- _asStringQ(1),
- _asStringS(1),
- _asTop(1),
- _generalAsCheckImplementation(1),
- _generalIsTestImplementation(1),
- _generalNullableAsCheckImplementation(1),
- _generalNullableIsTestImplementation(1),
- _installSpecializedAsCheck(1),
- _installSpecializedIsTest(1),
- _instanceType(1),
- _isBool(1),
- _isInt(1),
- _isNum(1),
- _isObject(1),
- _isString(1),
- _isTop(1),
- findType(1),
- instanceType(1)],
- type=[
- inst:Closure,
- inst:JSBool,
- inst:JSNull,
- is:Class*]
-*/
+/*member: testIsNot:type=[inst:JSBool]*/
testIsNot() => null is! Class;
-/*member: testIsNotGeneric:
- static=[
- Rti._bind(1),
- Rti._eval(1),
- _arrayInstanceType(1),
- _asBool(1),
- _asBoolQ(1),
- _asBoolS(1),
- _asDouble(1),
- _asDoubleQ(1),
- _asDoubleS(1),
- _asInt(1),
- _asIntQ(1),
- _asIntS(1),
- _asNum(1),
- _asNumQ(1),
- _asNumS(1),
- _asObject(1),
- _asString(1),
- _asStringQ(1),
- _asStringS(1),
- _asTop(1),
- _generalAsCheckImplementation(1),
- _generalIsTestImplementation(1),
- _generalNullableAsCheckImplementation(1),
- _generalNullableIsTestImplementation(1),
- _installSpecializedAsCheck(1),
- _installSpecializedIsTest(1),
- _instanceType(1),
- _isBool(1),
- _isInt(1),
- _isNum(1),
- _isObject(1),
- _isString(1),
- _isTop(1),
- findType(1),
- instanceType(1),
- setRuntimeTypeInfo(2)],
- type=[
- inst:Closure,
- inst:JSArray<dynamic>,
- inst:JSBool,
- inst:JSExtendableArray<dynamic>,
- inst:JSFixedArray<dynamic>,
- inst:JSMutableArray<dynamic>,
- inst:JSNull,
- inst:JSUnmodifiableArray<dynamic>,
- is:GenericClass<int*,String*>*]
-*/
+/*member: testIsNotGeneric:type=[inst:JSBool]*/
testIsNotGeneric() => null is! GenericClass<int, String>;
-/*member: testIsNotGenericRaw:
- static=[
- Rti._bind(1),
- Rti._eval(1),
- _arrayInstanceType(1),
- _asBool(1),
- _asBoolQ(1),
- _asBoolS(1),
- _asDouble(1),
- _asDoubleQ(1),
- _asDoubleS(1),
- _asInt(1),
- _asIntQ(1),
- _asIntS(1),
- _asNum(1),
- _asNumQ(1),
- _asNumS(1),
- _asObject(1),
- _asString(1),
- _asStringQ(1),
- _asStringS(1),
- _asTop(1),
- _generalAsCheckImplementation(1),
- _generalIsTestImplementation(1),
- _generalNullableAsCheckImplementation(1),
- _generalNullableIsTestImplementation(1),
- _installSpecializedAsCheck(1),
- _installSpecializedIsTest(1),
- _instanceType(1),
- _isBool(1),
- _isInt(1),
- _isNum(1),
- _isObject(1),
- _isString(1),
- _isTop(1),
- findType(1),
- instanceType(1)],
- type=[
- inst:Closure,
- inst:JSBool,
- inst:JSNull,
- is:GenericClass<dynamic,dynamic>*]
-*/
+/*member: testIsNotGenericRaw:type=[inst:JSBool]*/
testIsNotGenericRaw() => null is! GenericClass;
-/*member: testIsNotGenericDynamic:
- static=[
- Rti._bind(1),
- Rti._eval(1),
- _arrayInstanceType(1),
- _asBool(1),
- _asBoolQ(1),
- _asBoolS(1),
- _asDouble(1),
- _asDoubleQ(1),
- _asDoubleS(1),
- _asInt(1),
- _asIntQ(1),
- _asIntS(1),
- _asNum(1),
- _asNumQ(1),
- _asNumS(1),
- _asObject(1),
- _asString(1),
- _asStringQ(1),
- _asStringS(1),
- _asTop(1),
- _generalAsCheckImplementation(1),
- _generalIsTestImplementation(1),
- _generalNullableAsCheckImplementation(1),
- _generalNullableIsTestImplementation(1),
- _installSpecializedAsCheck(1),
- _installSpecializedIsTest(1),
- _instanceType(1),
- _isBool(1),
- _isInt(1),
- _isNum(1),
- _isObject(1),
- _isString(1),
- _isTop(1),
- findType(1),
- instanceType(1)],
- type=[
- inst:Closure,
- inst:JSBool,
- inst:JSNull,
- is:GenericClass<dynamic,dynamic>*]
-*/
+/*member: testIsNotGenericDynamic:type=[inst:JSBool]*/
testIsNotGenericDynamic() => null is! GenericClass<dynamic, dynamic>;
-/*member: testIsTypedef:
- static=[
- Rti._bind(1),
- Rti._eval(1),
- _arrayInstanceType(1),
- _asBool(1),
- _asBoolQ(1),
- _asBoolS(1),
- _asDouble(1),
- _asDoubleQ(1),
- _asDoubleS(1),
- _asInt(1),
- _asIntQ(1),
- _asIntS(1),
- _asNum(1),
- _asNumQ(1),
- _asNumS(1),
- _asObject(1),
- _asString(1),
- _asStringQ(1),
- _asStringS(1),
- _asTop(1),
- _generalAsCheckImplementation(1),
- _generalIsTestImplementation(1),
- _generalNullableAsCheckImplementation(1),
- _generalNullableIsTestImplementation(1),
- _installSpecializedAsCheck(1),
- _installSpecializedIsTest(1),
- _instanceType(1),
- _isBool(1),
- _isInt(1),
- _isNum(1),
- _isObject(1),
- _isString(1),
- _isTop(1),
- findType(1),
- instanceType(1),
- setRuntimeTypeInfo(2)],
- type=[
- inst:Closure,
- inst:JSArray<dynamic>,
- inst:JSBool,
- inst:JSExtendableArray<dynamic>,
- inst:JSFixedArray<dynamic>,
- inst:JSMutableArray<dynamic>,
- inst:JSNull,
- inst:JSUnmodifiableArray<dynamic>,
- is:dynamic Function()*]
-*/
+/*member: testIsTypedef:type=[inst:JSBool]*/
testIsTypedef() => null is Typedef;
-/*member: testIsTypedefGeneric:
- static=[
- Rti._bind(1),
- Rti._eval(1),
- _arrayInstanceType(1),
- _asBool(1),
- _asBoolQ(1),
- _asBoolS(1),
- _asDouble(1),
- _asDoubleQ(1),
- _asDoubleS(1),
- _asInt(1),
- _asIntQ(1),
- _asIntS(1),
- _asNum(1),
- _asNumQ(1),
- _asNumS(1),
- _asObject(1),
- _asString(1),
- _asStringQ(1),
- _asStringS(1),
- _asTop(1),
- _generalAsCheckImplementation(1),
- _generalIsTestImplementation(1),
- _generalNullableAsCheckImplementation(1),
- _generalNullableIsTestImplementation(1),
- _installSpecializedAsCheck(1),
- _installSpecializedIsTest(1),
- _instanceType(1),
- _isBool(1),
- _isInt(1),
- _isNum(1),
- _isObject(1),
- _isString(1),
- _isTop(1),
- findType(1),
- instanceType(1),
- setRuntimeTypeInfo(2)],
- type=[
- inst:Closure,
- inst:JSArray<dynamic>,
- inst:JSBool,
- inst:JSExtendableArray<dynamic>,
- inst:JSFixedArray<dynamic>,
- inst:JSMutableArray<dynamic>,
- inst:JSNull,
- inst:JSUnmodifiableArray<dynamic>,
- is:int* Function(String*)*]
-*/
+/*member: testIsTypedefGeneric:type=[inst:JSBool]*/
testIsTypedefGeneric() => null is GenericTypedef<int, String>;
-/*member: testIsTypedefGenericRaw:
- static=[
- Rti._bind(1),
- Rti._eval(1),
- _arrayInstanceType(1),
- _asBool(1),
- _asBoolQ(1),
- _asBoolS(1),
- _asDouble(1),
- _asDoubleQ(1),
- _asDoubleS(1),
- _asInt(1),
- _asIntQ(1),
- _asIntS(1),
- _asNum(1),
- _asNumQ(1),
- _asNumS(1),
- _asObject(1),
- _asString(1),
- _asStringQ(1),
- _asStringS(1),
- _asTop(1),
- _generalAsCheckImplementation(1),
- _generalIsTestImplementation(1),
- _generalNullableAsCheckImplementation(1),
- _generalNullableIsTestImplementation(1),
- _installSpecializedAsCheck(1),
- _installSpecializedIsTest(1),
- _instanceType(1),
- _isBool(1),
- _isInt(1),
- _isNum(1),
- _isObject(1),
- _isString(1),
- _isTop(1),
- findType(1),
- instanceType(1),
- setRuntimeTypeInfo(2)],
- type=[
- inst:Closure,
- inst:JSArray<dynamic>,
- inst:JSBool,
- inst:JSExtendableArray<dynamic>,
- inst:JSFixedArray<dynamic>,
- inst:JSMutableArray<dynamic>,
- inst:JSNull,
- inst:JSUnmodifiableArray<dynamic>,
- is:dynamic Function(dynamic)*]
-*/
+/*member: testIsTypedefGenericRaw:type=[inst:JSBool]*/
testIsTypedefGenericRaw() => null is GenericTypedef;
-/*member: testIsTypedefGenericDynamic:
- static=[
- Rti._bind(1),
- Rti._eval(1),
- _arrayInstanceType(1),
- _asBool(1),
- _asBoolQ(1),
- _asBoolS(1),
- _asDouble(1),
- _asDoubleQ(1),
- _asDoubleS(1),
- _asInt(1),
- _asIntQ(1),
- _asIntS(1),
- _asNum(1),
- _asNumQ(1),
- _asNumS(1),
- _asObject(1),
- _asString(1),
- _asStringQ(1),
- _asStringS(1),
- _asTop(1),
- _generalAsCheckImplementation(1),
- _generalIsTestImplementation(1),
- _generalNullableAsCheckImplementation(1),
- _generalNullableIsTestImplementation(1),
- _installSpecializedAsCheck(1),
- _installSpecializedIsTest(1),
- _instanceType(1),
- _isBool(1),
- _isInt(1),
- _isNum(1),
- _isObject(1),
- _isString(1),
- _isTop(1),
- findType(1),
- instanceType(1),
- setRuntimeTypeInfo(2)],
- type=[
- inst:Closure,
- inst:JSArray<dynamic>,
- inst:JSBool,
- inst:JSExtendableArray<dynamic>,
- inst:JSFixedArray<dynamic>,
- inst:JSMutableArray<dynamic>,
- inst:JSNull,
- inst:JSUnmodifiableArray<dynamic>,
- is:dynamic Function(dynamic)*]
-*/
+/*member: testIsTypedefGenericDynamic:type=[inst:JSBool]*/
testIsTypedefGenericDynamic() => null is GenericTypedef<dynamic, dynamic>;
-/*member: testIsTypedefDeep:
- static=[
- Rti._bind(1),
- Rti._eval(1),
- _arrayInstanceType(1),
- _asBool(1),
- _asBoolQ(1),
- _asBoolS(1),
- _asDouble(1),
- _asDoubleQ(1),
- _asDoubleS(1),
- _asInt(1),
- _asIntQ(1),
- _asIntS(1),
- _asNum(1),
- _asNumQ(1),
- _asNumS(1),
- _asObject(1),
- _asString(1),
- _asStringQ(1),
- _asStringS(1),
- _asTop(1),
- _generalAsCheckImplementation(1),
- _generalIsTestImplementation(1),
- _generalNullableAsCheckImplementation(1),
- _generalNullableIsTestImplementation(1),
- _installSpecializedAsCheck(1),
- _installSpecializedIsTest(1),
- _instanceType(1),
- _isBool(1),
- _isInt(1),
- _isNum(1),
- _isObject(1),
- _isString(1),
- _isTop(1),
- findType(1),
- instanceType(1),
- setRuntimeTypeInfo(2)],
- type=[
- inst:Closure,
- inst:JSArray<dynamic>,
- inst:JSBool,
- inst:JSExtendableArray<dynamic>,
- inst:JSFixedArray<dynamic>,
- inst:JSMutableArray<dynamic>,
- inst:JSNull,
- inst:JSUnmodifiableArray<dynamic>,
- is:List<int* Function(dynamic Function(dynamic)*)*>*]
-*/
+/*member: testIsTypedefDeep:type=[inst:JSBool]*/
testIsTypedefDeep() => null is List<GenericTypedef<int, GenericTypedef>>;
-// ignore: UNNECESSARY_CAST
/*member: testAs:
static=[
Rti._bind(1),
@@ -777,9 +191,9 @@
inst:Closure,
inst:JSBool]
*/
+// ignore: UNNECESSARY_CAST
testAs(dynamic o) => o as Class;
-// ignore: UNNECESSARY_CAST
/*member: testAsGeneric:
static=[
Rti._bind(1),
@@ -828,9 +242,9 @@
inst:JSMutableArray<dynamic>,
inst:JSUnmodifiableArray<dynamic>]
*/
+// ignore: UNNECESSARY_CAST
testAsGeneric(dynamic o) => o as GenericClass<int, String>;
-// ignore: UNNECESSARY_CAST
/*member: testAsGenericRaw:
static=[
Rti._bind(1),
@@ -873,9 +287,9 @@
inst:Closure,
inst:JSBool]
*/
+// ignore: UNNECESSARY_CAST
testAsGenericRaw(dynamic o) => o as GenericClass;
-// ignore: UNNECESSARY_CAST
/*member: testAsGenericDynamic:
static=[
Rti._bind(1),
@@ -918,6 +332,7 @@
inst:Closure,
inst:JSBool]
*/
+// ignore: UNNECESSARY_CAST
testAsGenericDynamic(dynamic o) => o as GenericClass<dynamic, dynamic>;
/*member: testThrow:
diff --git a/pkg/compiler/test/impact/data/future_or.dart b/pkg/compiler/test/impact/data/future_or.dart
index 42e77c8..1a13b89 100644
--- a/pkg/compiler/test/impact/data/future_or.dart
+++ b/pkg/compiler/test/impact/data/future_or.dart
@@ -6,7 +6,6 @@
import "dart:async";
-@pragma('dart2js:disableFinal')
/*member: main:
dynamic=[runtimeType],
runtimeType=[unknown:FutureOr<int*>*],
@@ -22,6 +21,7 @@
inst:JSUInt31,
inst:JSUInt32]
*/
+@pragma('dart2js:disableFinal')
void main() {
FutureOr<int> i = new Future<int>.value(0);
print(i.runtimeType);
diff --git a/pkg/compiler/test/impact/data/invokes.dart b/pkg/compiler/test/impact/data/invokes.dart
index a7e816f..cb1acfc 100644
--- a/pkg/compiler/test/impact/data/invokes.dart
+++ b/pkg/compiler/test/impact/data/invokes.dart
@@ -993,40 +993,48 @@
def:localFunction,
localFunction(0),
setRuntimeTypeInfo(2)],
- type=[inst:Function,
+ type=[
+ inst:Function,
inst:JSArray<dynamic>,
inst:JSExtendableArray<dynamic>,
inst:JSFixedArray<dynamic>,
inst:JSMutableArray<dynamic>,
- inst:JSUnmodifiableArray<dynamic>]*/
+ inst:JSUnmodifiableArray<dynamic>]
+*/
testLocalFunctionInvoke() {
localFunction() {}
localFunction();
}
-/*member: testLocalFunctionGet:static=[
+/*member: testLocalFunctionGet:
+ static=[
def:localFunction,
setRuntimeTypeInfo(2)],
- type=[inst:Function,
+ type=[
+ inst:Function,
inst:JSArray<dynamic>,
inst:JSExtendableArray<dynamic>,
inst:JSFixedArray<dynamic>,
inst:JSMutableArray<dynamic>,
- inst:JSUnmodifiableArray<dynamic>]*/
+ inst:JSUnmodifiableArray<dynamic>]
+*/
testLocalFunctionGet() {
localFunction() {}
localFunction;
}
-/*member: testClosure:static=[
+/*member: testClosure:
+ static=[
def:<anonymous>,
setRuntimeTypeInfo(2)],
- type=[inst:Function,
+ type=[
+ inst:Function,
inst:JSArray<dynamic>,
inst:JSExtendableArray<dynamic>,
inst:JSFixedArray<dynamic>,
inst:JSMutableArray<dynamic>,
- inst:JSUnmodifiableArray<dynamic>]*/
+ inst:JSUnmodifiableArray<dynamic>]
+*/
testClosure() {
() {};
}
@@ -1036,7 +1044,8 @@
static=[
def:<anonymous>,
setRuntimeTypeInfo(2)],
- type=[inst:Function,
+ type=[
+ inst:Function,
inst:JSArray<dynamic>,
inst:JSExtendableArray<dynamic>,
inst:JSFixedArray<dynamic>,
diff --git a/pkg/compiler/test/impact/data/jsinterop_setter1.dart b/pkg/compiler/test/impact/data/jsinterop_setter1.dart
index af09127..4042ca9 100644
--- a/pkg/compiler/test/impact/data/jsinterop_setter1.dart
+++ b/pkg/compiler/test/impact/data/jsinterop_setter1.dart
@@ -11,7 +11,6 @@
import 'package:js/js.dart';
-@JS()
/*member: foo=:
static=[
Rti._bind(1),
@@ -65,6 +64,7 @@
native:SqlError,
param:Function*]
*/
+@JS()
external set foo(Function f);
/*member: _doStuff:
diff --git a/pkg/compiler/test/impact/data/jsinterop_setter2.dart b/pkg/compiler/test/impact/data/jsinterop_setter2.dart
index 5a9c987..d62e98f 100644
--- a/pkg/compiler/test/impact/data/jsinterop_setter2.dart
+++ b/pkg/compiler/test/impact/data/jsinterop_setter2.dart
@@ -11,7 +11,6 @@
import 'package:js/js.dart';
-@JS()
/*member: foo=:
static=[
Rti._bind(1),
@@ -72,6 +71,7 @@
native:SqlError,
param:void Function(String*,File*)*]
*/
+@JS()
external set foo(void Function(String, File) f);
/*member: _doStuff:
diff --git a/pkg/compiler/test/impact/data/literals.dart b/pkg/compiler/test/impact/data/literals.dart
index 95bbf0a..4956865 100644
--- a/pkg/compiler/test/impact/data/literals.dart
+++ b/pkg/compiler/test/impact/data/literals.dart
@@ -82,10 +82,7 @@
/*member: testString:type=[inst:JSString]*/
testString() => 'foo';
-/*member: testStringInterpolation:
- dynamic=[toString(0)],
- static=[S(1)],type=[inst:JSBool,inst:JSString]
-*/
+/*member: testStringInterpolation:type=[inst:JSString]*/
testStringInterpolation() => '${true}';
/*member: testStringInterpolationConst:type=[inst:JSString]*/
@@ -94,11 +91,7 @@
return b;
}
-/*member: testStringJuxtaposition:
- dynamic=[toString(0)],
- static=[S(1)],
- type=[inst:JSString]
-*/
+/*member: testStringJuxtaposition:type=[inst:JSString]*/
testStringJuxtaposition() => 'a' 'b';
/*member: testSymbol:static=[Symbol.(1)],type=[inst:Symbol]*/
diff --git a/pkg/compiler/test/impact/data/native.dart b/pkg/compiler/test/impact/data/native.dart
index 9b26aae..b4d4c7f 100644
--- a/pkg/compiler/test/impact/data/native.dart
+++ b/pkg/compiler/test/impact/data/native.dart
@@ -58,7 +58,6 @@
@Native("NativeClass")
class NativeClass {
- @annotation_Creates_SerializedScriptValue
/*member: NativeClass.field:
static=[
Rti._bind(1),
@@ -108,6 +107,7 @@
native:int,
param:Object*]
*/
+ @annotation_Creates_SerializedScriptValue
final Object field;
factory NativeClass._() {
diff --git a/pkg/compiler/test/inference/data/as.dart b/pkg/compiler/test/inference/data/as.dart
index 319f83f..203687c 100644
--- a/pkg/compiler/test/inference/data/as.dart
+++ b/pkg/compiler/test/inference/data/as.dart
@@ -36,7 +36,7 @@
/*member: asIntWithNegative:[null]*/
asIntWithNegative() {
_asIntWithNegative(0);
- _asIntWithNegative(/*invoke: [exact=JSUInt31]*/ -1);
+ _asIntWithNegative(-1);
}
////////////////////////////////////////////////////////////////////////////////
@@ -60,7 +60,7 @@
/*member: asIntOfMinusOne:[null]*/
asIntOfMinusOne() {
- _asIntOfMinusOne(/*invoke: [exact=JSUInt31]*/ -1);
+ _asIntOfMinusOne(-1);
}
////////////////////////////////////////////////////////////////////////////////
diff --git a/pkg/compiler/test/inference/data/closure.dart b/pkg/compiler/test/inference/data/closure.dart
index 2e14eff..863cd64 100644
--- a/pkg/compiler/test/inference/data/closure.dart
+++ b/pkg/compiler/test/inference/data/closure.dart
@@ -69,7 +69,7 @@
int lines = 0;
local(/*[null]*/ () {
- lines = /*invoke: [exact=JSUInt31]*/ -42;
+ lines = -42;
});
return lines;
}
@@ -80,10 +80,10 @@
int lines = 0;
local(/*[null]*/ () {
- lines = /*invoke: [exact=JSUInt31]*/ -42;
+ lines = -42;
});
local(/*[null]*/ () {
- lines = /*invoke: [exact=JSUInt31]*/ -87;
+ lines = -87;
});
return lines;
}
diff --git a/pkg/compiler/test/inference/data/list.dart b/pkg/compiler/test/inference/data/list.dart
index aa419a3..e05562f 100644
--- a/pkg/compiler/test/inference/data/list.dart
+++ b/pkg/compiler/test/inference/data/list.dart
@@ -126,9 +126,8 @@
// Create a Uint8ClampedList using a constant multiplication as length.
////////////////////////////////////////////////////////////////////////////////
-/*member: newUint8ClampedList:Container([exact=NativeUint8ClampedList], element: [exact=JSUInt31], length: null)*/
-newUint8ClampedList() =>
- new Uint8ClampedList(2 /*invoke: [exact=JSUInt31]*/ * 7);
+/*member: newUint8ClampedList:Container([exact=NativeUint8ClampedList], element: [exact=JSUInt31], length: 14)*/
+newUint8ClampedList() => new Uint8ClampedList(2 * 7);
////////////////////////////////////////////////////////////////////////////////
// Create a Uint8List using a const static field as length.
diff --git a/pkg/compiler/test/inference/data/list2.dart b/pkg/compiler/test/inference/data/list2.dart
index 33ea0e2..40ab257 100644
--- a/pkg/compiler/test/inference/data/list2.dart
+++ b/pkg/compiler/test/inference/data/list2.dart
@@ -39,7 +39,7 @@
bool boolFlag = true;
/*member: data:Container([exact=JSExtendableArray], element: [subclass=JSInt], length: null)*/
-List<int> data = [/*invoke: [exact=JSUInt31]*/ -1, 1];
+List<int> data = [-1, 1];
// -------- List.empty --------
diff --git a/pkg/compiler/test/inference/data/logical.dart b/pkg/compiler/test/inference/data/logical.dart
index 6f0c127..9f16905 100644
--- a/pkg/compiler/test/inference/data/logical.dart
+++ b/pkg/compiler/test/inference/data/logical.dart
@@ -72,14 +72,14 @@
/// Return negation of `false`.
////////////////////////////////////////////////////////////////////////////////
-/*member: returnNotFalse:[exact=JSBool]*/
+/*member: returnNotFalse:Value([exact=JSBool], value: true)*/
returnNotFalse() => !false;
////////////////////////////////////////////////////////////////////////////////
/// Return negation of `true`.
////////////////////////////////////////////////////////////////////////////////
-/*member: returnNotTrue:[exact=JSBool]*/
+/*member: returnNotTrue:Value([exact=JSBool], value: false)*/
returnNotTrue() => !true;
////////////////////////////////////////////////////////////////////////////////
@@ -104,13 +104,13 @@
////////////////////////////////////////////////////////////////////////////////
/// Return value of an is `int` test known to be true.
////////////////////////////////////////////////////////////////////////////////
-/*member: returnIsOneInt:[exact=JSBool]*/
+/*member: returnIsOneInt:Value([exact=JSBool], value: true)*/
returnIsOneInt() => 1 is int;
////////////////////////////////////////////////////////////////////////////////
/// Return value of an is `int` test known to be false.
////////////////////////////////////////////////////////////////////////////////
-/*member: returnIsNullInt:[exact=JSBool]*/
+/*member: returnIsNullInt:Value([exact=JSBool], value: false)*/
returnIsNullInt() => null is int;
////////////////////////////////////////////////////////////////////////////////
@@ -128,13 +128,13 @@
////////////////////////////////////////////////////////////////////////////////
/// Return value of a negated is `int` test known to be false.
////////////////////////////////////////////////////////////////////////////////
-/*member: returnNotIsOneInt:[exact=JSBool]*/
+/*member: returnNotIsOneInt:Value([exact=JSBool], value: false)*/
returnNotIsOneInt() => 1 is! int;
////////////////////////////////////////////////////////////////////////////////
/// Return value of a negated is `int` test known to be true.
////////////////////////////////////////////////////////////////////////////////
-/*member: returnNotIsNullInt:[exact=JSBool]*/
+/*member: returnNotIsNullInt:Value([exact=JSBool], value: true)*/
returnNotIsNullInt() => null is! int;
////////////////////////////////////////////////////////////////////////////////
diff --git a/pkg/compiler/test/inference/data/simple.dart b/pkg/compiler/test/inference/data/simple.dart
index 0fc4b6f..7709e28 100644
--- a/pkg/compiler/test/inference/data/simple.dart
+++ b/pkg/compiler/test/inference/data/simple.dart
@@ -80,14 +80,14 @@
////////////////////////////////////////////////////////////////////////////////
/*member: minusOne:[subclass=JSInt]*/
-minusOne() => /*invoke: [exact=JSUInt31]*/ -1;
+minusOne() => -1;
////////////////////////////////////////////////////////////////////////////////
/// Return a negative double literal.
////////////////////////////////////////////////////////////////////////////////
-/*member: minusHalf:[subclass=JSNumber]*/
-minusHalf() => /*invoke: [exact=JSDouble]*/ -0.5;
+/*member: minusHalf:[exact=JSDouble]*/
+minusHalf() => -0.5;
////////////////////////////////////////////////////////////////////////////////
/// Return an empty string.
@@ -107,14 +107,14 @@
/// Return a string juxtaposition.
////////////////////////////////////////////////////////////////////////////////
-/*member: stringJuxtaposition:[exact=JSString]*/
+/*member: stringJuxtaposition:Value([exact=JSString], value: "foobar")*/
stringJuxtaposition() => 'foo' 'bar';
////////////////////////////////////////////////////////////////////////////////
/// Return a string constant interpolation.
////////////////////////////////////////////////////////////////////////////////
-/*member: stringConstantInterpolation:[exact=JSString]*/
+/*member: stringConstantInterpolation:Value([exact=JSString], value: "foobar")*/
stringConstantInterpolation() => 'foo${'bar'}';
////////////////////////////////////////////////////////////////////////////////
diff --git a/pkg/compiler/test/inference/side_effects/string_interpolation.dart b/pkg/compiler/test/inference/side_effects/string_interpolation.dart
index 444f3f1..4176998 100644
--- a/pkg/compiler/test/inference/side_effects/string_interpolation.dart
+++ b/pkg/compiler/test/inference/side_effects/string_interpolation.dart
@@ -5,9 +5,9 @@
// @dart = 2.7
/*member: stringInterpolation:SideEffects(reads nothing; writes anything)*/
-stringInterpolation() => '${null}';
+stringInterpolation(o) => '${o}';
/*member: main:SideEffects(reads nothing; writes anything)*/
main() {
- stringInterpolation();
+ stringInterpolation(null);
}
diff --git a/pkg/compiler/test/rti/data/runtime_type_equals3.dart b/pkg/compiler/test/rti/data/runtime_type_equals3.dart
index 3b3ab44..ca06e3e 100644
--- a/pkg/compiler/test/rti/data/runtime_type_equals3.dart
+++ b/pkg/compiler/test/rti/data/runtime_type_equals3.dart
@@ -8,8 +8,10 @@
/*class: Class1a:needsArgs*/
class Class1a<T> {
+ /*member: Class1a.:*/
Class1a();
+ /*member: Class1a.==:*/
bool operator ==(other) {
if (identical(this, other)) return true;
return runtimeType == other?.runtimeType;
@@ -18,6 +20,7 @@
/*class: Class1b:needsArgs*/
class Class1b<T> extends Class1a<T> {
+ /*member: Class1b.:*/
Class1b();
}
@@ -25,13 +28,17 @@
// this class.
/*class: Class1c:needsArgs*/
class Class1c<T> implements Class1a<T> {
+ /*member: Class1c.:*/
Class1c();
}
+/*class: Class2:*/
class Class2<T> {
+ /*member: Class2.:*/
Class2();
}
+/*member: main:*/
main() {
Class1a<int> cls1a = new Class1a<int>();
Class1a<int> cls1b1 = new Class1b<int>();
diff --git a/pkg/compiler/test/rti/data/runtime_type_equals4.dart b/pkg/compiler/test/rti/data/runtime_type_equals4.dart
index a975295..220d033 100644
--- a/pkg/compiler/test/rti/data/runtime_type_equals4.dart
+++ b/pkg/compiler/test/rti/data/runtime_type_equals4.dart
@@ -8,8 +8,10 @@
/*class: Class1a:needsArgs*/
class Class1a<T> {
+ /*member: Class1a.:*/
Class1a();
+ /*member: Class1a.==:*/
bool operator ==(other) {
if (identical(this, other)) return true;
return other?.runtimeType == runtimeType;
@@ -18,6 +20,7 @@
/*class: Class1b:needsArgs*/
class Class1b<T> extends Class1a<T> {
+ /*member: Class1b.:*/
Class1b();
}
@@ -25,13 +28,17 @@
// this class.
/*class: Class1c:needsArgs*/
class Class1c<T> implements Class1a<T> {
+ /*member: Class1c.:*/
Class1c();
}
+/*class: Class2:*/
class Class2<T> {
+ /*member: Class2.:*/
Class2();
}
+/*member: main:*/
main() {
Class1a<int> cls1a = new Class1a<int>();
Class1a<int> cls1b1 = new Class1b<int>();
diff --git a/tests/language/nnbd/subtyping/function_type_bounds_weak_test.dart b/tests/language/nnbd/subtyping/function_type_bounds_weak_test.dart
index cfcf46e..976fdce 100644
--- a/tests/language/nnbd/subtyping/function_type_bounds_weak_test.dart
+++ b/tests/language/nnbd/subtyping/function_type_bounds_weak_test.dart
@@ -13,9 +13,13 @@
// Should pass with weak checking because when the nullability information on
// Object and Object? are erased the type bounds are equivalent.
Expect.isTrue(fnWithNonNullObjectBound is fnTypeWithNullableObjectBound);
+ const test1 = fnWithNonNullObjectBound is fnTypeWithNullableObjectBound;
+ Expect.isTrue(test1);
// void fn<T extends Null>() is void Function<T extends Never>()
// Should pass with weak checking because because Null becomes equivalent to
// the bottom type.
Expect.isTrue(fnWithNullBound is fnTypeWithNeverBound);
+ const test2 = fnWithNullBound is fnTypeWithNeverBound;
+ Expect.isTrue(test2);
}