| 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 |