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