| Index: pkg/compiler/lib/src/cps_ir/insert_refinements.dart
|
| diff --git a/pkg/compiler/lib/src/cps_ir/insert_refinements.dart b/pkg/compiler/lib/src/cps_ir/insert_refinements.dart
|
| index 3b545c6968d1305afc378107e211f3efd92ee109..6c5ec7014720e6f5417b1d4887f9ed15070c3df8 100644
|
| --- a/pkg/compiler/lib/src/cps_ir/insert_refinements.dart
|
| +++ b/pkg/compiler/lib/src/cps_ir/insert_refinements.dart
|
| @@ -9,6 +9,7 @@ import 'cps_ir_nodes.dart';
|
| import '../common/names.dart';
|
| import '../types/types.dart' show TypeMask;
|
| import 'type_mask_system.dart';
|
| +import 'cps_fragment.dart';
|
|
|
| /// Inserts [Refinement] nodes in the IR to allow for sparse path-sensitive
|
| /// type analysis in the [TypePropagator] pass.
|
| @@ -34,9 +35,13 @@ class InsertRefinements extends TrampolineRecursiveVisitor implements Pass {
|
|
|
| /// Updates references to refer to the refinement currently in scope.
|
| void processReference(Reference node) {
|
| - Refinement refined = refinementFor[node.definition];
|
| - if (refined != null) {
|
| - node.changeTo(refined);
|
| + Definition definition = node.definition;
|
| + if (definition is Primitive) {
|
| + Primitive prim = definition.effectiveDefinition;
|
| + Refinement refined = refinementFor[prim];
|
| + if (refined != null && refined != definition) {
|
| + node.changeTo(refined);
|
| + }
|
| }
|
| }
|
|
|
| @@ -118,6 +123,34 @@ class InsertRefinements extends TrampolineRecursiveVisitor implements Pass {
|
| }
|
| }
|
|
|
| + void visitTypeCast(TypeCast node) {
|
| + Continuation cont = node.continuation.definition;
|
| + Primitive value = node.value.definition;
|
| +
|
| + processReference(node.value);
|
| + node.typeArguments.forEach(processReference);
|
| +
|
| + // Refine the type of the input.
|
| + sinkContinuationToUse(cont, node);
|
| + TypeMask type = types.subtypesOf(node.dartType).nullable();
|
| + Refinement refinement = new Refinement(value, type);
|
| + pushRefinement(cont, refinement);
|
| + }
|
| +
|
| + void visitRefinement(Refinement node) {
|
| + // We found a pre-existing refinement node. These are generated by the
|
| + // IR builder to hold information from --trust-type-annotations.
|
| + // Update its input to use our own current refinement, then update the
|
| + // environment to use this refinement.
|
| + processReference(node.value);
|
| + Primitive value = node.value.definition.effectiveDefinition;
|
| + Primitive oldRefinement = refinementFor[value];
|
| + refinementFor[value] = node;
|
| + pushAction(() {
|
| + refinementFor[value] = oldRefinement;
|
| + });
|
| + }
|
| +
|
| CallExpression getCallWithResult(Primitive prim) {
|
| if (prim is Parameter && prim.parent is Continuation) {
|
| Continuation cont = prim.parent;
|
| @@ -205,9 +238,10 @@ class InsertRefinements extends TrampolineRecursiveVisitor implements Pass {
|
| for (Continuation cont in node.continuations) {
|
| if (cont.hasExactlyOneUse &&
|
| (cont.firstRef.parent is InvokeMethod ||
|
| + cont.firstRef.parent is TypeCast ||
|
| cont.firstRef.parent is Branch)) {
|
| // Do not push the continuation here.
|
| - // visitInvokeMethod and visitBranch will do that.
|
| + // visitInvokeMethod, visitBranch, and visitTypeCast will do that.
|
| } else {
|
| push(cont);
|
| }
|
|
|