| 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_interceptors; | 5 library dart2js.cps_ir.share_interceptors; |
| 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 '../constants/values.dart'; | 10 import '../constants/values.dart'; |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 87 Interceptor interceptor = node.primitive; | 87 Interceptor interceptor = node.primitive; |
| 88 Primitive input = interceptor.input.definition; | 88 Primitive input = interceptor.input.definition; |
| 89 | 89 |
| 90 // Try to reuse an existing interceptor for the same input. | 90 // Try to reuse an existing interceptor for the same input. |
| 91 Primitive existing = interceptorFor[input]; | 91 Primitive existing = interceptorFor[input]; |
| 92 if (existing != null) { | 92 if (existing != null) { |
| 93 if (existing is Interceptor) { | 93 if (existing is Interceptor) { |
| 94 existing.interceptedClasses.addAll(interceptor.interceptedClasses); | 94 existing.interceptedClasses.addAll(interceptor.interceptedClasses); |
| 95 } | 95 } |
| 96 existing.substituteFor(interceptor); | 96 existing.substituteFor(interceptor); |
| 97 interceptor.destroy(); | 97 InteriorNode parent = node.parent; |
| 98 node.remove(); | 98 parent.body = node.body; |
| 99 node.body.parent = parent; |
| 100 interceptor.input.unlink(); |
| 99 return next; | 101 return next; |
| 100 } | 102 } |
| 101 | 103 |
| 102 // There is no interceptor obtained from this particular input, but | 104 // There is no interceptor obtained from this particular input, but |
| 103 // there might one obtained from another input that is known to | 105 // there might one obtained from another input that is known to |
| 104 // have the same result, so try to reuse that. | 106 // have the same result, so try to reuse that. |
| 105 InterceptorConstantValue constant = interceptor.constantValue; | 107 InterceptorConstantValue constant = interceptor.constantValue; |
| 106 if (constant != null) { | 108 if (constant != null) { |
| 107 existing = sharedConstantFor[constant]; | 109 existing = sharedConstantFor[constant]; |
| 108 if (existing != null) { | 110 if (existing != null) { |
| 109 existing.substituteFor(interceptor); | 111 existing.substituteFor(interceptor); |
| 110 interceptor.destroy(); | 112 InteriorNode parent = node.parent; |
| 111 node.remove(); | 113 parent.body = node.body; |
| 114 node.body.parent = parent; |
| 115 interceptor.input.unlink(); |
| 112 return next; | 116 return next; |
| 113 } | 117 } |
| 114 | 118 |
| 115 // The interceptor could not be shared. Replace it with a constant. | 119 // The interceptor could not be shared. Replace it with a constant. |
| 116 Constant constantPrim = new Constant(constant); | 120 Constant constantPrim = new Constant(constant); |
| 117 node.primitive = constantPrim; | 121 node.primitive = constantPrim; |
| 118 constantPrim.hint = interceptor.hint; | 122 constantPrim.hint = interceptor.hint; |
| 119 constantPrim.type = interceptor.type; | 123 constantPrim.type = interceptor.type; |
| 120 constantPrim.substituteFor(interceptor); | 124 constantPrim.substituteFor(interceptor); |
| 121 interceptor.destroy(); | 125 interceptor.input.unlink(); |
| 122 sharedConstantFor[constant] = constantPrim; | 126 sharedConstantFor[constant] = constantPrim; |
| 123 } else { | 127 } else { |
| 124 interceptorFor[input] = interceptor; | 128 interceptorFor[input] = interceptor; |
| 125 } | 129 } |
| 126 | 130 |
| 127 // Determine the outermost loop where the input to the interceptor call | 131 // Determine the outermost loop where the input to the interceptor call |
| 128 // is available. Constant interceptors take no input and can thus be | 132 // is available. Constant interceptors take no input and can thus be |
| 129 // hoisted all way to the top-level. | 133 // hoisted all way to the top-level. |
| 130 Continuation referencedLoop = constant != null | 134 Continuation referencedLoop = constant != null |
| 131 ? null | 135 ? null |
| 132 : lowestCommonAncestor(loopHeaderFor[input], currentLoopHeader); | 136 : lowestCommonAncestor(loopHeaderFor[input], currentLoopHeader); |
| 133 if (referencedLoop != currentLoopHeader) { | 137 if (referencedLoop != currentLoopHeader) { |
| 134 // [referencedLoop] contains the binding for [input], so we cannot hoist | 138 // [referencedLoop] contains the binding for [input], so we cannot hoist |
| 135 // the interceptor outside that loop. Find the loop nested one level | 139 // the interceptor outside that loop. Find the loop nested one level |
| 136 // inside referencedLoop, and hoist the interceptor just outside that one. | 140 // inside referencedLoop, and hoist the interceptor just outside that one. |
| 137 Continuation loop = currentLoopHeader; | 141 Continuation loop = currentLoopHeader; |
| 138 Continuation enclosing = loopHierarchy.getEnclosingLoop(loop); | 142 Continuation enclosing = loopHierarchy.getEnclosingLoop(loop); |
| 139 while (enclosing != referencedLoop) { | 143 while (enclosing != referencedLoop) { |
| 140 assert(loop != null); | 144 assert(loop != null); |
| 141 loop = enclosing; | 145 loop = enclosing; |
| 142 enclosing = loopHierarchy.getEnclosingLoop(loop); | 146 enclosing = loopHierarchy.getEnclosingLoop(loop); |
| 143 } | 147 } |
| 144 assert(loop != null); | 148 assert(loop != null); |
| 145 | 149 |
| 146 // Move the LetPrim above the loop binding. | 150 // Remove LetPrim from its current position. |
| 151 InteriorNode parent = node.parent; |
| 152 parent.body = node.body; |
| 153 node.body.parent = parent; |
| 154 |
| 155 // Insert the LetPrim immediately before the loop. |
| 147 LetCont loopBinding = loop.parent; | 156 LetCont loopBinding = loop.parent; |
| 148 node.remove(); | 157 InteriorNode newParent = loopBinding.parent; |
| 149 node.insertAbove(loopBinding); | 158 newParent.body = node; |
| 159 node.body = loopBinding; |
| 160 loopBinding.parent = node; |
| 161 node.parent = newParent; |
| 150 | 162 |
| 151 // A different loop now contains the interceptor. | 163 // A different loop now contains the interceptor. |
| 152 loopHeaderFor[node.primitive] = enclosing; | 164 loopHeaderFor[node.primitive] = enclosing; |
| 153 | 165 |
| 154 // Register the interceptor as hoisted to that loop, so it will be | 166 // Register the interceptor as hoisted to that loop, so it will be |
| 155 // removed from the environment when it falls out of scope. | 167 // removed from the environment when it falls out of scope. |
| 156 loopHoistedInterceptors | 168 loopHoistedInterceptors |
| 157 .putIfAbsent(loop, () => <Primitive>[]) | 169 .putIfAbsent(loop, () => <Primitive>[]) |
| 158 .add(node.primitive); | 170 .add(node.primitive); |
| 159 } else if (constant != null) { | 171 } else if (constant != null) { |
| (...skipping 26 matching lines...) Expand all Loading... |
| 186 } | 198 } |
| 187 } | 199 } |
| 188 return c1; | 200 return c1; |
| 189 } | 201 } |
| 190 | 202 |
| 191 int getDepth(Continuation loop) { | 203 int getDepth(Continuation loop) { |
| 192 if (loop == null) return -1; | 204 if (loop == null) return -1; |
| 193 return loopHierarchy.loopDepth[loop]; | 205 return loopHierarchy.loopDepth[loop]; |
| 194 } | 206 } |
| 195 } | 207 } |
| OLD | NEW |