| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 part of ssa; | 5 part of ssa; |
| 6 | 6 |
| 7 /** | 7 /** |
| 8 * This phase simplifies interceptors in multiple ways: | 8 * This phase simplifies interceptors in multiple ways: |
| 9 * | 9 * |
| 10 * 1) If the interceptor is for an object whose type is known, it | 10 * 1) If the interceptor is for an object whose type is known, it |
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 166 return result; | 166 return result; |
| 167 } | 167 } |
| 168 | 168 |
| 169 bool visitInterceptor(HInterceptor node) { | 169 bool visitInterceptor(HInterceptor node) { |
| 170 if (node.isConstant()) return false; | 170 if (node.isConstant()) return false; |
| 171 | 171 |
| 172 // If the interceptor is used by multiple instructions, specialize | 172 // If the interceptor is used by multiple instructions, specialize |
| 173 // it with a set of classes it intercepts. | 173 // it with a set of classes it intercepts. |
| 174 Set<ClassElement> interceptedClasses; | 174 Set<ClassElement> interceptedClasses; |
| 175 JavaScriptBackend backend = compiler.backend; | 175 JavaScriptBackend backend = compiler.backend; |
| 176 HInstruction dominator = | 176 HInstruction dominator = findDominator(node.usedBy); |
| 177 findDominator(node.usedBy.where((i) => i is HInvokeDynamic)); | 177 // If there is a call that dominates all other uses, we can use just the |
| 178 // If there is an instruction that dominates all others, we can | 178 // selector of that instruction. |
| 179 // use only the selector of that instruction. | 179 if (dominator is HInvokeDynamic && |
| 180 if (dominator != null) { | 180 dominator.isCallOnInterceptor(compiler) && |
| 181 node == dominator.receiver) { |
| 181 interceptedClasses = | 182 interceptedClasses = |
| 182 backend.getInterceptedClassesOn(dominator.selector.name); | 183 backend.getInterceptedClassesOn(dominator.selector.name); |
| 183 | 184 |
| 184 // If we found that we need number, we must still go through all | 185 // If we found that we need number, we must still go through all |
| 185 // uses to check if they require int, or double. | 186 // uses to check if they require int, or double. |
| 186 if (interceptedClasses.contains(backend.jsNumberClass) | 187 if (interceptedClasses.contains(backend.jsNumberClass) |
| 187 && !(interceptedClasses.contains(backend.jsDoubleClass) | 188 && !(interceptedClasses.contains(backend.jsDoubleClass) |
| 188 || interceptedClasses.contains(backend.jsIntClass))) { | 189 || interceptedClasses.contains(backend.jsIntClass))) { |
| 189 for (HInstruction user in node.usedBy) { | 190 for (HInstruction user in node.usedBy) { |
| 190 if (user is! HInvoke) continue; | 191 if (user is! HInvoke) continue; |
| 191 Set<ClassElement> intercepted = | 192 Set<ClassElement> intercepted = |
| 192 backend.getInterceptedClassesOn(user.selector.name); | 193 backend.getInterceptedClassesOn(user.selector.name); |
| 193 if (intercepted.contains(backend.jsIntClass)) { | 194 if (intercepted.contains(backend.jsIntClass)) { |
| 194 interceptedClasses.add(backend.jsIntClass); | 195 interceptedClasses.add(backend.jsIntClass); |
| 195 } | 196 } |
| 196 if (intercepted.contains(backend.jsDoubleClass)) { | 197 if (intercepted.contains(backend.jsDoubleClass)) { |
| 197 interceptedClasses.add(backend.jsDoubleClass); | 198 interceptedClasses.add(backend.jsDoubleClass); |
| 198 } | 199 } |
| 199 } | 200 } |
| 200 } | 201 } |
| 201 } else { | 202 } else { |
| 202 interceptedClasses = new Set<ClassElement>(); | 203 interceptedClasses = new Set<ClassElement>(); |
| 203 for (HInstruction user in node.usedBy) { | 204 for (HInstruction user in node.usedBy) { |
| 204 if (user is HIs) { | 205 if (user is HInvokeDynamic && |
| 205 // Is-checks can be performed on any intercepted class. | 206 user.isCallOnInterceptor(compiler) && |
| 207 node == user.receiver) { |
| 208 interceptedClasses.addAll( |
| 209 backend.getInterceptedClassesOn(user.selector.name)); |
| 210 } else { |
| 211 // Use a most general interceptor for other instructions, example, |
| 212 // is-checks and escaping interceptors. |
| 206 interceptedClasses.addAll(backend.interceptedClasses); | 213 interceptedClasses.addAll(backend.interceptedClasses); |
| 207 break; | 214 break; |
| 208 } | 215 } |
| 209 if (user is! HInvoke) continue; | |
| 210 // We don't handle escaping interceptors yet. | |
| 211 interceptedClasses.addAll( | |
| 212 backend.getInterceptedClassesOn(user.selector.name)); | |
| 213 } | 216 } |
| 214 } | 217 } |
| 215 | 218 |
| 216 HInstruction receiver = node.receiver; | 219 HInstruction receiver = node.receiver; |
| 217 if (canUseSelfForInterceptor(receiver, interceptedClasses)) { | 220 if (canUseSelfForInterceptor(receiver, interceptedClasses)) { |
| 218 return rewriteToUseSelfAsInterceptor(node, receiver); | 221 return rewriteToUseSelfAsInterceptor(node, receiver); |
| 219 } | 222 } |
| 220 | 223 |
| 221 // Try computing a constant interceptor. | 224 // Try computing a constant interceptor. |
| 222 HInstruction constantInterceptor = | 225 HInstruction constantInterceptor = |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 328 instruction = new HInvokeDynamicMethod( | 331 instruction = new HInvokeDynamicMethod( |
| 329 selector, inputs, node.instructionType, true); | 332 selector, inputs, node.instructionType, true); |
| 330 } | 333 } |
| 331 | 334 |
| 332 HBasicBlock block = node.block; | 335 HBasicBlock block = node.block; |
| 333 block.addAfter(node, instruction); | 336 block.addAfter(node, instruction); |
| 334 block.rewrite(node, instruction); | 337 block.rewrite(node, instruction); |
| 335 return true; | 338 return true; |
| 336 } | 339 } |
| 337 } | 340 } |
| OLD | NEW |