| 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.share_final_fields; | 5 library dart2js.cps_ir.share_final_fields; |
| 6 | 6 |
| 7 import 'optimizers.dart'; | 7 import 'optimizers.dart'; |
| 8 import 'cps_ir_nodes.dart'; | 8 import 'cps_ir_nodes.dart'; |
| 9 import 'loop_hierarchy.dart'; | 9 import 'loop_hierarchy.dart'; |
| 10 import '../elements/elements.dart'; | 10 import '../elements/elements.dart'; |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 115 | 115 |
| 116 if (primitive.objectIsNotNull) { | 116 if (primitive.objectIsNotNull) { |
| 117 // Determine how far the GetField can be lifted. The outermost loop that | 117 // Determine how far the GetField can be lifted. The outermost loop that |
| 118 // contains the input binding should also contain the load. | 118 // contains the input binding should also contain the load. |
| 119 // Don't move above a refinement guard since that might be unsafe. | 119 // Don't move above a refinement guard since that might be unsafe. |
| 120 | 120 |
| 121 // TODO(sra): We can move above a refinement guard provided the input is | 121 // TODO(sra): We can move above a refinement guard provided the input is |
| 122 // still in scope and safe (non-null). We will have to replace | 122 // still in scope and safe (non-null). We will have to replace |
| 123 // primitive.object with the most constrained refinement still in scope. | 123 // primitive.object with the most constrained refinement still in scope. |
| 124 Continuation referencedLoop = | 124 Continuation referencedLoop = |
| 125 lowestCommonAncestor(loopHeaderFor[refinedReceiver], | 125 loopHierarchy.lowestCommonAncestor(loopHeaderFor[refinedReceiver], |
| 126 currentLoopHeader); | 126 currentLoopHeader); |
| 127 if (referencedLoop != currentLoopHeader) { | 127 if (referencedLoop != currentLoopHeader) { |
| 128 Continuation hoistTarget = getCurrentOuterLoop(scope: referencedLoop); | 128 Continuation hoistTarget = getCurrentOuterLoop(scope: referencedLoop); |
| 129 LetCont loopBinding = hoistTarget.parent; | 129 LetCont loopBinding = hoistTarget.parent; |
| 130 node.remove(); | 130 node.remove(); |
| 131 node.insertAbove(loopBinding); | 131 node.insertAbove(loopBinding); |
| 132 // Remove the hoisted operations from the environment after processing | 132 // Remove the hoisted operations from the environment after processing |
| 133 // the loop. | 133 // the loop. |
| 134 loopHoistedGetters | 134 loopHoistedGetters |
| 135 .putIfAbsent(hoistTarget, () => <GetField>[]) | 135 .putIfAbsent(hoistTarget, () => <GetField>[]) |
| 136 .add(primitive); | 136 .add(primitive); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 150 // TODO(24781): This query is incorrect for fields assigned only via | 150 // TODO(24781): This query is incorrect for fields assigned only via |
| 151 // | 151 // |
| 152 // super.field = ... | 152 // super.field = ... |
| 153 // | 153 // |
| 154 // return backend.compiler.world.fieldNeverChanges(field); | 154 // return backend.compiler.world.fieldNeverChanges(field); |
| 155 | 155 |
| 156 // Native fields are getters with side effects (e.g. layout). | 156 // Native fields are getters with side effects (e.g. layout). |
| 157 if (backend.isNative(field)) return false; | 157 if (backend.isNative(field)) return false; |
| 158 return field.isFinal || field.isConst; | 158 return field.isFinal || field.isConst; |
| 159 } | 159 } |
| 160 | |
| 161 /// Returns the the innermost loop that effectively encloses both | |
| 162 /// c1 and c2 (or `null` if there is no such loop). | |
| 163 Continuation lowestCommonAncestor(Continuation c1, Continuation c2) { | |
| 164 int d1 = getDepth(c1), d2 = getDepth(c2); | |
| 165 while (c1 != c2) { | |
| 166 if (d1 <= d2) { | |
| 167 c2 = loopHierarchy.getEnclosingLoop(c2); | |
| 168 d2 = getDepth(c2); | |
| 169 } else { | |
| 170 c1 = loopHierarchy.getEnclosingLoop(c1); | |
| 171 d1 = getDepth(c1); | |
| 172 } | |
| 173 } | |
| 174 return c1; | |
| 175 } | |
| 176 | |
| 177 int getDepth(Continuation loop) { | |
| 178 if (loop == null) return -1; | |
| 179 return loopHierarchy.loopDepth[loop]; | |
| 180 } | |
| 181 } | 160 } |
| OLD | NEW |