OLD | NEW |
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, 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 library dart2js.cps_ir.use_field_initializers; | 4 library dart2js.cps_ir.use_field_initializers; |
5 | 5 |
6 import 'cps_ir_nodes.dart'; | 6 import 'cps_ir_nodes.dart'; |
7 import 'optimizers.dart'; | 7 import 'optimizers.dart'; |
8 import '../elements/elements.dart'; | 8 import '../elements/elements.dart'; |
9 import '../js_backend/js_backend.dart'; | 9 import '../js_backend/js_backend.dart'; |
10 | 10 |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
87 endBasicBlock(); | 87 endBasicBlock(); |
88 } | 88 } |
89 void visitThrow(Throw node) { | 89 void visitThrow(Throw node) { |
90 endBasicBlock(); | 90 endBasicBlock(); |
91 } | 91 } |
92 void visitUnreachable(Unreachable node) { | 92 void visitUnreachable(Unreachable node) { |
93 endBasicBlock(); | 93 endBasicBlock(); |
94 } | 94 } |
95 | 95 |
96 void visitLetMutable(LetMutable node) { | 96 void visitLetMutable(LetMutable node) { |
97 escape(node.value); | 97 escape(node.valueRef); |
98 } | 98 } |
99 | 99 |
100 void visitLetCont(LetCont node) { | 100 void visitLetCont(LetCont node) { |
101 if (unescaped.isNotEmpty) { | 101 if (unescaped.isNotEmpty) { |
102 // Ensure we do not lift a LetCont if there is a sink target set above | 102 // Ensure we do not lift a LetCont if there is a sink target set above |
103 // the current node. | 103 // the current node. |
104 sinkLetConts(); | 104 sinkLetConts(); |
105 letConts.add(node); | 105 letConts.add(node); |
106 } | 106 } |
107 } | 107 } |
(...skipping 10 matching lines...) Expand all Loading... |
118 void endBasicBlock() { | 118 void endBasicBlock() { |
119 sinkLetConts(); | 119 sinkLetConts(); |
120 letConts.clear(); | 120 letConts.clear(); |
121 unescaped.clear(); | 121 unescaped.clear(); |
122 } | 122 } |
123 | 123 |
124 void visitLetPrim(LetPrim node) { | 124 void visitLetPrim(LetPrim node) { |
125 Primitive prim = node.primitive; | 125 Primitive prim = node.primitive; |
126 if (prim is CreateInstance) { | 126 if (prim is CreateInstance) { |
127 unescaped.add(prim); | 127 unescaped.add(prim); |
128 prim.arguments.forEach(escape); | 128 prim.argumentRefs.forEach(escape); |
129 return; | 129 return; |
130 } | 130 } |
131 if (unescaped.isEmpty) return; | 131 if (unescaped.isEmpty) return; |
132 if (prim is SetField) { | 132 if (prim is SetField) { |
133 escape(prim.value); | 133 escape(prim.valueRef); |
134 Primitive object = prim.object.definition; | 134 Primitive object = prim.object; |
135 if (object is CreateInstance && unescaped.contains(object)) { | 135 if (object is CreateInstance && unescaped.contains(object)) { |
136 int index = getFieldIndex(object.classElement, prim.field); | 136 int index = getFieldIndex(object.classElement, prim.field); |
137 if (index == -1) { | 137 if (index == -1) { |
138 // This field is not initialized at creation time, so we cannot pull | 138 // This field is not initialized at creation time, so we cannot pull |
139 // set SetField into the CreateInstance instruction. We have to | 139 // set SetField into the CreateInstance instruction. We have to |
140 // leave the instruction here, and this counts as a use of the object. | 140 // leave the instruction here, and this counts as a use of the object. |
141 escape(prim.object); | 141 escape(prim.objectRef); |
142 } else { | 142 } else { |
143 // Replace the field initializer with the new value. There are no uses | 143 // Replace the field initializer with the new value. There are no uses |
144 // of the object before this, so the old value cannot have been seen. | 144 // of the object before this, so the old value cannot have been seen. |
145 object.arguments[index].changeTo(prim.value.definition); | 145 object.argumentRefs[index].changeTo(prim.value); |
146 prim.destroy(); | 146 prim.destroy(); |
147 // The right-hand side might not be in scope at the CreateInstance. | 147 // The right-hand side might not be in scope at the CreateInstance. |
148 // Sink the creation down to this point. | 148 // Sink the creation down to this point. |
149 rebindCreateInstanceAt(object, node); | 149 rebindCreateInstanceAt(object, node); |
150 letContSinkTarget = node; | 150 letContSinkTarget = node; |
151 } | 151 } |
152 } | 152 } |
153 return; | 153 return; |
154 } | 154 } |
155 if (prim is GetField) { | 155 if (prim is GetField) { |
156 // When reading the field of a newly created object, just use the initial | 156 // When reading the field of a newly created object, just use the initial |
157 // value and destroy the GetField. This can unblock the other optimization | 157 // value and destroy the GetField. This can unblock the other optimization |
158 // since we remove a use of the object. | 158 // since we remove a use of the object. |
159 Primitive object = prim.object.definition; | 159 Primitive object = prim.object; |
160 if (object is CreateInstance && unescaped.contains(object)) { | 160 if (object is CreateInstance && unescaped.contains(object)) { |
161 int index = getFieldIndex(object.classElement, prim.field); | 161 int index = getFieldIndex(object.classElement, prim.field); |
162 if (index == -1) { | 162 if (index == -1) { |
163 escape(prim.object); | 163 escape(prim.objectRef); |
164 } else { | 164 } else { |
165 prim.replaceUsesWith(object.arguments[index].definition); | 165 prim.replaceUsesWith(object.argument(index)); |
166 prim.destroy(); | 166 prim.destroy(); |
167 node.remove(); | 167 node.remove(); |
168 } | 168 } |
169 } | 169 } |
170 return; | 170 return; |
171 } | 171 } |
172 escapeVisitor.visit(node.primitive); | 172 escapeVisitor.visit(node.primitive); |
173 } | 173 } |
174 | 174 |
175 void rebindCreateInstanceAt(CreateInstance prim, LetPrim newBinding) { | 175 void rebindCreateInstanceAt(CreateInstance prim, LetPrim newBinding) { |
(...skipping 27 matching lines...) Expand all Loading... |
203 } | 203 } |
204 | 204 |
205 class EscapeVisitor extends DeepRecursiveVisitor { | 205 class EscapeVisitor extends DeepRecursiveVisitor { |
206 final UseFieldInitializers main; | 206 final UseFieldInitializers main; |
207 EscapeVisitor(this.main); | 207 EscapeVisitor(this.main); |
208 | 208 |
209 processReference(Reference ref) { | 209 processReference(Reference ref) { |
210 main.escape(ref); | 210 main.escape(ref); |
211 } | 211 } |
212 } | 212 } |
OLD | NEW |