OLD | NEW |
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 library dart2js.cps_ir.gvn; | 5 library dart2js.cps_ir.gvn; |
6 | 6 |
7 import 'cps_ir_nodes.dart'; | 7 import 'cps_ir_nodes.dart'; |
8 import '../universe/side_effects.dart'; | 8 import '../universe/side_effects.dart'; |
9 import '../elements/elements.dart'; | 9 import '../elements/elements.dart'; |
10 import 'optimizers.dart' show Pass; | 10 import 'optimizers.dart' show Pass; |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
97 | 97 |
98 // ------------------ GLOBAL VALUE NUMBERING --------------------- | 98 // ------------------ GLOBAL VALUE NUMBERING --------------------- |
99 | 99 |
100 /// True if [prim] can be eliminated if its value is already in scope. | 100 /// True if [prim] can be eliminated if its value is already in scope. |
101 bool canReplaceWithExistingValue(Primitive prim) { | 101 bool canReplaceWithExistingValue(Primitive prim) { |
102 // Primitives that have no side effects other than potentially throwing are | 102 // Primitives that have no side effects other than potentially throwing are |
103 // known not the throw if the value is already in scope. Handling those | 103 // known not the throw if the value is already in scope. Handling those |
104 // specially is equivalent to updating refinements during GVN. | 104 // specially is equivalent to updating refinements during GVN. |
105 // GetLazyStatic cannot have side effects because the field has already | 105 // GetLazyStatic cannot have side effects because the field has already |
106 // been initialized. | 106 // been initialized. |
107 // TODO(asgerf): Replace GetLazyStatic in an earlier pass so it does not | |
108 // confuse the LoopSideEffects pre-analysis. | |
109 return prim.isSafeForElimination || | 107 return prim.isSafeForElimination || |
110 prim is GetField || | 108 prim is GetField || |
111 prim is GetLength || | 109 prim is GetLength || |
112 prim is GetIndex || | 110 prim is GetIndex || |
113 prim is GetLazyStatic; | 111 prim is GetLazyStatic; |
114 } | 112 } |
115 | 113 |
116 @override | 114 @override |
117 Expression traverseLetPrim(LetPrim node) { | 115 Expression traverseLetPrim(LetPrim node) { |
118 Expression next = node.body; | 116 Expression next = node.body; |
119 Primitive prim = node.primitive; | 117 Primitive prim = node.primitive; |
120 | 118 |
121 loopHeaderFor[prim] = currentLoopHeader; | 119 loopHeaderFor[prim] = currentLoopHeader; |
122 | 120 |
123 if (prim is Refinement) { | 121 if (prim is Refinement) { |
124 // Do not share refinements (they have no runtime or code size cost), and | 122 // Do not share refinements (they have no runtime or code size cost), and |
125 // do not put them in the GVN table because GvnVectorBuilder unfolds | 123 // do not put them in the GVN table because GvnVectorBuilder unfolds |
126 // refinements by itself. | 124 // refinements by itself. |
127 return next; | 125 return next; |
128 } | 126 } |
129 | 127 |
| 128 // Update effect numbers due to side effects from a static initializer. |
| 129 // GetLazyStatic is GVN'ed like a GetStatic, but the effects of the static |
| 130 // initializer occur before reading the field. |
| 131 if (prim is GetLazyStatic) { |
| 132 visit(prim); |
| 133 } |
| 134 |
130 // Compute the GVN vector for this computation. | 135 // Compute the GVN vector for this computation. |
131 List vector = gvnVectorBuilder.make(prim, effectNumbers); | 136 List vector = gvnVectorBuilder.make(prim, effectNumbers); |
132 | 137 |
133 // Update effect numbers due to side effects. | 138 // Update effect numbers due to side effects. |
134 // Do this after computing the GVN vector so the primitive's GVN is not | 139 // Do this after computing the GVN vector so the primitive's GVN is not |
135 // influenced by its own side effects. | 140 // influenced by its own side effects, except in the case of GetLazyStatic. |
136 visit(prim); | 141 if (prim is! GetLazyStatic) { |
| 142 visit(prim); |
| 143 } |
137 | 144 |
138 if (vector == null) { | 145 if (vector == null) { |
139 // The primitive is not GVN'able. Move on. | 146 // The primitive is not GVN'able. Move on. |
140 return next; | 147 return next; |
141 } | 148 } |
142 | 149 |
143 // Compute the GVN for this primitive. | 150 // Compute the GVN for this primitive. |
144 int gvn = gvnTable.insert(vector); | 151 int gvn = gvnTable.insert(vector); |
145 gvnFor[prim] = gvn; | 152 gvnFor[prim] = gvn; |
146 | 153 |
(...skipping 521 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
668 vector = [GvnCode.GET_FIELD, node.field]; | 675 vector = [GvnCode.GET_FIELD, node.field]; |
669 } else { | 676 } else { |
670 vector = [GvnCode.GET_FIELD, node.field, effectNumbers.instanceField]; | 677 vector = [GvnCode.GET_FIELD, node.field, effectNumbers.instanceField]; |
671 } | 678 } |
672 } | 679 } |
673 | 680 |
674 processGetIndex(GetIndex node) { | 681 processGetIndex(GetIndex node) { |
675 vector = [GvnCode.GET_INDEX, effectNumbers.indexableContent]; | 682 vector = [GvnCode.GET_INDEX, effectNumbers.indexableContent]; |
676 } | 683 } |
677 | 684 |
678 processGetStatic(GetStatic node) { | 685 visitGetStatic(GetStatic node) { |
679 if (isImmutable(node.element)) { | 686 if (isImmutable(node.element)) { |
680 vector = [GvnCode.GET_STATIC, node.element]; | 687 vector = [GvnCode.GET_STATIC, node.element]; |
681 } else { | 688 } else { |
682 vector = [GvnCode.GET_STATIC, node.element, effectNumbers.staticField]; | 689 vector = [GvnCode.GET_STATIC, node.element, effectNumbers.staticField]; |
683 } | 690 } |
| 691 // Suppress visit to witness argument. |
684 } | 692 } |
685 | 693 |
686 processGetLazyStatic(GetLazyStatic node) { | 694 processGetLazyStatic(GetLazyStatic node) { |
687 if (isImmutable(node.element)) { | 695 if (isImmutable(node.element)) { |
688 vector = [GvnCode.GET_STATIC, node.element]; | 696 vector = [GvnCode.GET_STATIC, node.element]; |
689 } else { | 697 } else { |
690 vector = [GvnCode.GET_STATIC, node.element, effectNumbers.staticField]; | 698 vector = [GvnCode.GET_STATIC, node.element, effectNumbers.staticField]; |
691 } | 699 } |
692 } | 700 } |
693 | 701 |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
735 | 743 |
736 @override | 744 @override |
737 processReference(Reference ref) { | 745 processReference(Reference ref) { |
738 callback(ref); | 746 callback(ref); |
739 } | 747 } |
740 | 748 |
741 static void forEach(Primitive node, ReferenceCallback callback) { | 749 static void forEach(Primitive node, ReferenceCallback callback) { |
742 new InputVisitor(callback).visit(node); | 750 new InputVisitor(callback).visit(node); |
743 } | 751 } |
744 } | 752 } |
OLD | NEW |