[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);
 }