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 |