Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(133)

Side by Side Diff: pkg/compiler/lib/src/cps_ir/backward_null_check_remover.dart

Issue 1569593002: Improve null-check elimination and change backward traversal strategy. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Remove unrelated change Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 library dart2js.cps_ir.backward_null_check_remover; 1 library dart2js.cps_ir.backward_null_check_remover;
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 '../common/names.dart'; 5 import '../common/names.dart';
6 import '../universe/selector.dart'; 6 import '../universe/selector.dart';
7 import 'type_mask_system.dart'; 7 import 'type_mask_system.dart';
8 import 'cps_fragment.dart'; 8 import 'cps_fragment.dart';
9 9
10 /// Removes null checks that are follwed by another instruction that will 10 /// Removes null checks that are follwed by another instruction that will
(...skipping 13 matching lines...) Expand all
24 /// willing to accept this. 24 /// willing to accept this.
25 /// 25 ///
26 /// Note that code motion may not occur after this pass, since the [NullCheck] 26 /// Note that code motion may not occur after this pass, since the [NullCheck]
27 /// nodes are not there to restrict it. 27 /// nodes are not there to restrict it.
28 // 28 //
29 // TODO(asgerf): It would be nice with a clear specification of when we allow 29 // TODO(asgerf): It would be nice with a clear specification of when we allow
30 // the wording of error message to change. E.g. "toString" is already pretty 30 // the wording of error message to change. E.g. "toString" is already pretty
31 // bad so changing that should be ok, but changing a field access is not as 31 // bad so changing that should be ok, but changing a field access is not as
32 // clear. 32 // clear.
33 // 33 //
34 class BackwardNullCheckRemover extends TrampolineRecursiveVisitor 34 class BackwardNullCheckRemover extends BlockVisitor implements Pass {
35 implements Pass {
36 String get passName => 'Backward null-check remover'; 35 String get passName => 'Backward null-check remover';
37 36
38 final TypeMaskSystem typeSystem; 37 final TypeMaskSystem typeSystem;
39 38
40 /// When the analysis of an expression completes, [nullCheckValue] refers to 39 /// When the analysis of an expression completes, [nullCheckValue] refers to
41 /// a value that is checked in the beginning of that expression. 40 /// a value that is checked in the beginning of that expression.
42 Primitive nullCheckedValue; 41 Primitive nullCheckedValue;
43 42
43 /// The [nullCheckedValue] at the entry point of a continuation.
44 final Map<Continuation, Primitive> nullCheckedValueAt =
45 <Continuation, Primitive>{};
46
44 BackwardNullCheckRemover(this.typeSystem); 47 BackwardNullCheckRemover(this.typeSystem);
45 48
46 void rewrite(FunctionDefinition node) { 49 void rewrite(FunctionDefinition node) {
47 visit(node); 50 BlockVisitor.traverseInPostOrder(node, this);
48 } 51 }
49 52
50 /// Returns a reference to an operand of [prim], where [prim] throws if null 53 /// Returns a reference to an operand of [prim], where [prim] throws if null
51 /// is passed into that operand. 54 /// is passed into that operand.
52 Reference<Primitive> getNullCheckedOperand(Primitive prim) { 55 Reference<Primitive> getNullCheckedOperand(Primitive prim) {
53 if (prim is NullCheck) return prim.value; 56 if (prim is NullCheck) return prim.value;
54 if (prim is GetLength) return prim.object; 57 if (prim is GetLength) return prim.object;
55 if (prim is GetField) return prim.object; 58 if (prim is GetField) return prim.object;
56 if (prim is GetIndex) return prim.object; 59 if (prim is GetIndex) return prim.object;
57 if (prim is SetField) return prim.object; 60 if (prim is SetField) return prim.object;
(...skipping 30 matching lines...) Expand all
88 /// cannot throw or have side effects and does not carry any path-sensitive 91 /// cannot throw or have side effects and does not carry any path-sensitive
89 /// type information, such as [Refinement] nodes do. 92 /// type information, such as [Refinement] nodes do.
90 // 93 //
91 // TODO(asgerf): This prevents elimination of the .length created for a bounds 94 // TODO(asgerf): This prevents elimination of the .length created for a bounds
92 // check, because there is a refinement node below it. To handle this, we 95 // check, because there is a refinement node below it. To handle this, we
93 // would have to relocate the [Refinement] node below the new null check. 96 // would have to relocate the [Refinement] node below the new null check.
94 bool canMoveAboveNullCheck(Primitive prim) { 97 bool canMoveAboveNullCheck(Primitive prim) {
95 return prim.isSafeForReordering; 98 return prim.isSafeForReordering;
96 } 99 }
97 100
98 Expression traverseLetPrim(LetPrim node) { 101 void visitLetPrim(LetPrim node) {
99 Primitive prim = node.primitive; 102 Primitive prim = node.primitive;
100 Primitive receiver = getNullCheckedOperand(prim)?.definition; 103 Primitive receiver = getNullCheckedOperand(prim)?.definition;
101 if (receiver != null) { 104 if (receiver != null) {
102 pushAction(() { 105 if (nullCheckedValue != null && receiver.sameValue(nullCheckedValue)) {
103 Primitive successor = nullCheckedValue; 106 tryEliminateRedundantNullCheck(prim, nullCheckedValue);
104 if (successor != null && receiver.sameValue(successor)) { 107 }
105 tryEliminateRedundantNullCheck(prim, successor); 108 nullCheckedValue = receiver;
106 }
107 nullCheckedValue = receiver;
108 });
109 } else if (!canMoveAboveNullCheck(prim)) { 109 } else if (!canMoveAboveNullCheck(prim)) {
110 pushAction(() { 110 nullCheckedValue = null;
111 nullCheckedValue = null;
112 });
113 } 111 }
114 return node.body;
115 } 112 }
116 113
117 Expression traverseContinuation(Continuation cont) { 114 void visitContinuation(Continuation cont) {
118 pushAction(() { 115 if (nullCheckedValue != null) {
116 nullCheckedValueAt[cont] = nullCheckedValue;
119 nullCheckedValue = null; 117 nullCheckedValue = null;
120 }); 118 }
121 return cont.body;
122 } 119 }
123 120
124 Expression traverseLetHandler(LetHandler node) { 121 void visitLetHandler(LetHandler node) {
125 push(node.handler); 122 nullCheckedValue = null;
126 pushAction(() { 123 }
127 nullCheckedValue = null; 124
128 }); 125 visitInvokeContinuation(InvokeContinuation node) {
129 return node.body; 126 if (!node.isRecursive) {
127 nullCheckedValue = nullCheckedValueAt[node.continuation.definition];
128 }
130 } 129 }
131 } 130 }
OLDNEW
« no previous file with comments | « no previous file | pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698