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