| 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 'cps_fragment.dart'; | 10 import 'cps_fragment.dart'; |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 135 InterceptorConstantValue constant = getInterceptorConstant(interceptor); | 135 InterceptorConstantValue constant = getInterceptorConstant(interceptor); |
| 136 | 136 |
| 137 if (constant == null) return; | 137 if (constant == null) return; |
| 138 | 138 |
| 139 if (interceptor.isAlwaysIntercepted) { | 139 if (interceptor.isAlwaysIntercepted) { |
| 140 Primitive constantPrim = makeConstantFor(constant, | 140 Primitive constantPrim = makeConstantFor(constant, |
| 141 useSite: let, | 141 useSite: let, |
| 142 type: interceptor.type, | 142 type: interceptor.type, |
| 143 sourceInformation: interceptor.sourceInformation); | 143 sourceInformation: interceptor.sourceInformation); |
| 144 constantPrim.useElementAsHint(interceptor.hint); | 144 constantPrim.useElementAsHint(interceptor.hint); |
| 145 constantPrim.substituteFor(interceptor); | 145 interceptor..replaceUsesWith(constantPrim)..destroy(); |
| 146 interceptor.destroy(); | |
| 147 let.remove(); | 146 let.remove(); |
| 148 } else if (interceptor.isAlwaysNullOrIntercepted) { | 147 } else if (interceptor.isAlwaysNullOrIntercepted) { |
| 149 Primitive input = interceptor.input.definition; | 148 Primitive input = interceptor.input.definition; |
| 150 Primitive constantPrim = makeConstantFor(constant, | 149 Primitive constantPrim = makeConstantFor(constant, |
| 151 useSite: let, | 150 useSite: let, |
| 152 type: interceptor.type.nonNullable(), | 151 type: interceptor.type.nonNullable(), |
| 153 sourceInformation: interceptor.sourceInformation); | 152 sourceInformation: interceptor.sourceInformation); |
| 154 CpsFragment cps = new CpsFragment(interceptor.sourceInformation); | 153 CpsFragment cps = new CpsFragment(interceptor.sourceInformation); |
| 155 Parameter param = new Parameter(interceptor.hint); | 154 Parameter param = new Parameter(interceptor.hint); |
| 156 Continuation cont = cps.letCont(<Parameter>[param]); | 155 Continuation cont = cps.letCont(<Parameter>[param]); |
| 157 if (interceptor.interceptedClasses.every(hasNoFalsyValues)) { | 156 if (interceptor.interceptedClasses.every(hasNoFalsyValues)) { |
| 158 // If null is the only falsy value, compile as "x && CONST". | 157 // If null is the only falsy value, compile as "x && CONST". |
| 159 cps.ifFalsy(input).invokeContinuation(cont, [input]); | 158 cps.ifFalsy(input).invokeContinuation(cont, [input]); |
| 160 } else { | 159 } else { |
| 161 // If there are other falsy values compile as "x == null ? x : CONST". | 160 // If there are other falsy values compile as "x == null ? x : CONST". |
| 162 Primitive condition = cps.applyBuiltin( | 161 Primitive condition = cps.applyBuiltin( |
| 163 BuiltinOperator.LooseEq, | 162 BuiltinOperator.LooseEq, |
| 164 [input, cps.makeNull()]); | 163 [input, cps.makeNull()]); |
| 165 cps.ifTruthy(condition).invokeContinuation(cont, [input]); | 164 cps.ifTruthy(condition).invokeContinuation(cont, [input]); |
| 166 } | 165 } |
| 167 cps.invokeContinuation(cont, [constantPrim]); | 166 cps.invokeContinuation(cont, [constantPrim]); |
| 168 cps.context = cont; | 167 cps.context = cont; |
| 169 cps.insertAbove(let); | 168 cps.insertAbove(let); |
| 170 param.substituteFor(interceptor); | 169 interceptor..replaceUsesWith(param)..destroy(); |
| 171 interceptor.destroy(); | |
| 172 let.remove(); | 170 let.remove(); |
| 173 } | 171 } |
| 174 } | 172 } |
| 175 | 173 |
| 176 @override | 174 @override |
| 177 Expression traverseLetPrim(LetPrim node) { | 175 Expression traverseLetPrim(LetPrim node) { |
| 178 loopHeaderFor[node.primitive] = currentLoopHeader; | 176 loopHeaderFor[node.primitive] = currentLoopHeader; |
| 179 Expression next = node.body; | 177 Expression next = node.body; |
| 180 if (node.primitive is! Interceptor) { | 178 if (node.primitive is! Interceptor) { |
| 181 return next; | 179 return next; |
| 182 } | 180 } |
| 183 Interceptor interceptor = node.primitive; | 181 Interceptor interceptor = node.primitive; |
| 184 Primitive input = interceptor.input.definition; | 182 Primitive input = interceptor.input.definition; |
| 185 | 183 |
| 186 // Try to reuse an existing interceptor for the same input. | 184 // Try to reuse an existing interceptor for the same input. |
| 187 Interceptor existing = interceptorFor[input]; | 185 Interceptor existing = interceptorFor[input]; |
| 188 if (existing != null) { | 186 if (existing != null) { |
| 189 existing.interceptedClasses.addAll(interceptor.interceptedClasses); | 187 existing.interceptedClasses.addAll(interceptor.interceptedClasses); |
| 190 existing.flags |= interceptor.flags; | 188 existing.flags |= interceptor.flags; |
| 191 existing.substituteFor(interceptor); | 189 interceptor..replaceUsesWith(existing)..destroy(); |
| 192 interceptor.destroy(); | |
| 193 node.remove(); | 190 node.remove(); |
| 194 return next; | 191 return next; |
| 195 } | 192 } |
| 196 | 193 |
| 197 // Put this interceptor in the environment. | 194 // Put this interceptor in the environment. |
| 198 interceptorFor[input] = interceptor; | 195 interceptorFor[input] = interceptor; |
| 199 | 196 |
| 200 // Determine how far the interceptor can be lifted. The outermost loop | 197 // Determine how far the interceptor can be lifted. The outermost loop |
| 201 // that contains the input binding should also contain the interceptor | 198 // that contains the input binding should also contain the interceptor |
| 202 // binding. | 199 // binding. |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 250 | 247 |
| 251 class ShareConstants extends TrampolineRecursiveVisitor { | 248 class ShareConstants extends TrampolineRecursiveVisitor { |
| 252 Map<ConstantValue, Constant> sharedConstantFor = <ConstantValue, Constant>{}; | 249 Map<ConstantValue, Constant> sharedConstantFor = <ConstantValue, Constant>{}; |
| 253 | 250 |
| 254 Expression traverseLetPrim(LetPrim node) { | 251 Expression traverseLetPrim(LetPrim node) { |
| 255 Expression next = node.body; | 252 Expression next = node.body; |
| 256 if (node.primitive is Constant && shouldShareConstant(node.primitive)) { | 253 if (node.primitive is Constant && shouldShareConstant(node.primitive)) { |
| 257 Constant prim = node.primitive; | 254 Constant prim = node.primitive; |
| 258 Constant existing = sharedConstantFor[prim.value]; | 255 Constant existing = sharedConstantFor[prim.value]; |
| 259 if (existing != null) { | 256 if (existing != null) { |
| 260 existing.substituteFor(prim); | |
| 261 existing.useElementAsHint(prim.hint); | 257 existing.useElementAsHint(prim.hint); |
| 262 prim.destroy(); | 258 prim..replaceUsesWith(existing)..destroy(); |
| 263 node.remove(); | 259 node.remove(); |
| 264 return next; | 260 return next; |
| 265 } | 261 } |
| 266 sharedConstantFor[prim.value] = prim; | 262 sharedConstantFor[prim.value] = prim; |
| 267 pushAction(() { | 263 pushAction(() { |
| 268 assert(sharedConstantFor[prim.value] == prim); | 264 assert(sharedConstantFor[prim.value] == prim); |
| 269 sharedConstantFor.remove(prim.value); | 265 sharedConstantFor.remove(prim.value); |
| 270 }); | 266 }); |
| 271 } | 267 } |
| 272 return next; | 268 return next; |
| 273 } | 269 } |
| 274 | 270 |
| 275 bool shouldShareConstant(Constant constant) { | 271 bool shouldShareConstant(Constant constant) { |
| 276 return constant.value.isInterceptor; | 272 return constant.value.isInterceptor; |
| 277 } | 273 } |
| 278 } | 274 } |
| OLD | NEW |