| OLD | NEW |
| 1 library dart2js.cps_ir.update_refinements; | 1 library dart2js.cps_ir.update_refinements; |
| 2 | 2 |
| 3 import 'cps_ir_nodes.dart'; | 3 import 'cps_ir_nodes.dart'; |
| 4 import 'optimizers.dart' show Pass; | 4 import 'optimizers.dart' show Pass; |
| 5 import 'type_mask_system.dart'; | 5 import 'type_mask_system.dart'; |
| 6 import '../world.dart'; |
| 6 | 7 |
| 7 /// Updates all references to use the most refined version in scope. | 8 /// Updates all references to use the most refined version in scope. |
| 8 /// | 9 /// |
| 9 /// [GVN] and [RedundantJoinElimination], and possibly other passes, can create | 10 /// [GVN] and [RedundantJoinElimination], and possibly other passes, can create |
| 10 /// references that don't use the best refinement in scope. This pass improves | 11 /// references that don't use the best refinement in scope. This pass improves |
| 11 /// the refinement information. | 12 /// the refinement information. |
| 12 /// | 13 /// |
| 13 // | 14 // |
| 14 // TODO(asgerf): Could be done during GVN for another adjacent pass. | 15 // TODO(asgerf): Could be done during GVN for another adjacent pass. |
| 15 // It is easier to measure performance and rearrange passes when it has its | 16 // It is easier to measure performance and rearrange passes when it has its |
| 16 // own pass, but we can merge it with an adjacent pass later. | 17 // own pass, but we can merge it with an adjacent pass later. |
| 17 // | 18 // |
| 18 class UpdateRefinements extends TrampolineRecursiveVisitor implements Pass { | 19 class UpdateRefinements extends TrampolineRecursiveVisitor implements Pass { |
| 19 String get passName => 'Update refinements'; | 20 String get passName => 'Update refinements'; |
| 20 | 21 |
| 21 final TypeMaskSystem typeSystem; | 22 final TypeMaskSystem typeSystem; |
| 23 World get classWorld => typeSystem.classWorld; |
| 22 | 24 |
| 23 Map<Primitive, Primitive> refinementFor = <Primitive, Primitive>{}; | 25 Map<Primitive, Primitive> refinementFor = <Primitive, Primitive>{}; |
| 24 | 26 |
| 25 UpdateRefinements(this.typeSystem); | 27 UpdateRefinements(this.typeSystem); |
| 26 | 28 |
| 27 void rewrite(FunctionDefinition node) { | 29 void rewrite(FunctionDefinition node) { |
| 28 visit(node); | 30 visit(node); |
| 29 } | 31 } |
| 30 | 32 |
| 31 Expression traverseLetPrim(LetPrim node) { | 33 Expression traverseLetPrim(LetPrim node) { |
| 32 Expression next = node.body; | 34 Expression next = node.body; |
| 33 visit(node.primitive); | 35 visit(node.primitive); |
| 34 return next; | 36 return next; |
| 35 } | 37 } |
| 36 | 38 |
| 37 visitNullCheck(NullCheck node) { | 39 visitReceiverCheck(ReceiverCheck node) { |
| 38 if (refine(node.value)) { | 40 if (refine(node.value)) { |
| 41 // Update the type if the input has changed. |
| 39 Primitive value = node.value.definition; | 42 Primitive value = node.value.definition; |
| 40 if (value.type.isNullable) { | 43 if (value.type.needsNoSuchMethodHandling(node.selector, classWorld)) { |
| 41 // Update the type if the input has changed. | 44 node.type = typeSystem.receiverTypeFor(node.selector, value.type); |
| 42 node.type = value.type.nonNullable(); | |
| 43 } else { | 45 } else { |
| 46 // Check is no longer needed. |
| 44 node..replaceUsesWith(value)..destroy(); | 47 node..replaceUsesWith(value)..destroy(); |
| 45 LetPrim letPrim = node.parent; | 48 LetPrim letPrim = node.parent; |
| 46 letPrim.remove(); | 49 letPrim.remove(); |
| 47 return; | 50 return; |
| 48 } | 51 } |
| 49 } | 52 } |
| 50 // Use the NullCheck as a refinement. | 53 // Use the ReceiverCheck as a refinement. |
| 51 Primitive value = node.effectiveDefinition; | 54 Primitive value = node.effectiveDefinition; |
| 52 Primitive old = refinementFor[value]; | 55 Primitive old = refinementFor[value]; |
| 53 refinementFor[value] = node; | 56 refinementFor[value] = node; |
| 54 pushAction(() { | 57 pushAction(() { |
| 55 refinementFor[value] = old; | 58 refinementFor[value] = old; |
| 56 }); | 59 }); |
| 57 } | 60 } |
| 58 | 61 |
| 59 visitRefinement(Refinement node) { | 62 visitRefinement(Refinement node) { |
| 60 if (refine(node.value)) { | 63 if (refine(node.value)) { |
| (...skipping 18 matching lines...) Expand all Loading... |
| 79 if (def is Primitive) { | 82 if (def is Primitive) { |
| 80 Primitive refinement = refinementFor[def.effectiveDefinition]; | 83 Primitive refinement = refinementFor[def.effectiveDefinition]; |
| 81 if (refinement != null && refinement != ref.definition) { | 84 if (refinement != null && refinement != ref.definition) { |
| 82 ref.changeTo(refinement); | 85 ref.changeTo(refinement); |
| 83 return true; | 86 return true; |
| 84 } | 87 } |
| 85 } | 88 } |
| 86 return false; | 89 return false; |
| 87 } | 90 } |
| 88 } | 91 } |
| OLD | NEW |