| 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 import '../common_elements.dart' show CommonElements; | 5 import '../common_elements.dart' show CommonElements; |
| 6 import '../constants/constant_system.dart'; | 6 import '../constants/constant_system.dart'; |
| 7 import '../constants/values.dart'; | 7 import '../constants/values.dart'; |
| 8 import '../elements/entities.dart'; | 8 import '../elements/entities.dart'; |
| 9 import '../js_backend/interceptor_data.dart'; | 9 import '../js_backend/interceptor_data.dart'; |
| 10 import '../types/types.dart'; | 10 import '../types/types.dart'; |
| (...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 214 user.inputs.where((input) => input == used).length; | 214 user.inputs.where((input) => input == used).length; |
| 215 | 215 |
| 216 Set<ClassEntity> interceptedClasses; | 216 Set<ClassEntity> interceptedClasses; |
| 217 HInstruction dominator = findDominator(node.usedBy); | 217 HInstruction dominator = findDominator(node.usedBy); |
| 218 // If there is a call that dominates all other uses, we can use just the | 218 // If there is a call that dominates all other uses, we can use just the |
| 219 // selector of that instruction. | 219 // selector of that instruction. |
| 220 if (dominator is HInvokeDynamic && | 220 if (dominator is HInvokeDynamic && |
| 221 dominator.isCallOnInterceptor(closedWorld) && | 221 dominator.isCallOnInterceptor(closedWorld) && |
| 222 node == dominator.receiver && | 222 node == dominator.receiver && |
| 223 useCount(dominator, node) == 1) { | 223 useCount(dominator, node) == 1) { |
| 224 interceptedClasses = interceptorData.getInterceptedClassesOn( | 224 interceptedClasses = |
| 225 dominator.selector.name, closedWorld); | 225 interceptorData.getInterceptedClassesOn(dominator.selector.name); |
| 226 | 226 |
| 227 // If we found that we need number, we must still go through all | 227 // If we found that we need number, we must still go through all |
| 228 // uses to check if they require int, or double. | 228 // uses to check if they require int, or double. |
| 229 if (interceptedClasses.contains(_commonElements.jsNumberClass) && | 229 if (interceptedClasses.contains(_commonElements.jsNumberClass) && |
| 230 !(interceptedClasses.contains(_commonElements.jsDoubleClass) || | 230 !(interceptedClasses.contains(_commonElements.jsDoubleClass) || |
| 231 interceptedClasses.contains(_commonElements.jsIntClass))) { | 231 interceptedClasses.contains(_commonElements.jsIntClass))) { |
| 232 Set<ClassEntity> required; | 232 Set<ClassEntity> required; |
| 233 for (HInstruction user in node.usedBy) { | 233 for (HInstruction user in node.usedBy) { |
| 234 if (user is! HInvoke) continue; | 234 if (user is! HInvoke) continue; |
| 235 Set<ClassEntity> intercepted = interceptorData | 235 Set<ClassEntity> intercepted = |
| 236 .getInterceptedClassesOn(user.selector.name, closedWorld); | 236 interceptorData.getInterceptedClassesOn(user.selector.name); |
| 237 if (intercepted.contains(_commonElements.jsIntClass)) { | 237 if (intercepted.contains(_commonElements.jsIntClass)) { |
| 238 // TODO(johnniwinther): Use type argument when all uses of | 238 // TODO(johnniwinther): Use type argument when all uses of |
| 239 // intercepted classes expect entities instead of elements. | 239 // intercepted classes expect entities instead of elements. |
| 240 required ??= new Set/*<ClassEntity>*/(); | 240 required ??= new Set/*<ClassEntity>*/(); |
| 241 required.add(_commonElements.jsIntClass); | 241 required.add(_commonElements.jsIntClass); |
| 242 } | 242 } |
| 243 if (intercepted.contains(_commonElements.jsDoubleClass)) { | 243 if (intercepted.contains(_commonElements.jsDoubleClass)) { |
| 244 // TODO(johnniwinther): Use type argument when all uses of | 244 // TODO(johnniwinther): Use type argument when all uses of |
| 245 // intercepted classes expect entities instead of elements. | 245 // intercepted classes expect entities instead of elements. |
| 246 required ??= new Set/*<ClassEntity>*/(); | 246 required ??= new Set/*<ClassEntity>*/(); |
| 247 required.add(_commonElements.jsDoubleClass); | 247 required.add(_commonElements.jsDoubleClass); |
| 248 } | 248 } |
| 249 } | 249 } |
| 250 // Don't modify the result of [interceptorData.getInterceptedClassesOn]. | 250 // Don't modify the result of [interceptorData.getInterceptedClassesOn]. |
| 251 if (required != null) { | 251 if (required != null) { |
| 252 interceptedClasses = interceptedClasses.union(required); | 252 interceptedClasses = interceptedClasses.union(required); |
| 253 } | 253 } |
| 254 } | 254 } |
| 255 } else { | 255 } else { |
| 256 // TODO(johnniwinther): Use type argument when all uses of intercepted | 256 // TODO(johnniwinther): Use type argument when all uses of intercepted |
| 257 // classes expect entities instead of elements. | 257 // classes expect entities instead of elements. |
| 258 interceptedClasses = new Set/*<ClassEntity>*/(); | 258 interceptedClasses = new Set/*<ClassEntity>*/(); |
| 259 for (HInstruction user in node.usedBy) { | 259 for (HInstruction user in node.usedBy) { |
| 260 if (user is HInvokeDynamic && | 260 if (user is HInvokeDynamic && |
| 261 user.isCallOnInterceptor(closedWorld) && | 261 user.isCallOnInterceptor(closedWorld) && |
| 262 node == user.receiver && | 262 node == user.receiver && |
| 263 useCount(user, node) == 1) { | 263 useCount(user, node) == 1) { |
| 264 interceptedClasses.addAll(interceptorData.getInterceptedClassesOn( | 264 interceptedClasses.addAll( |
| 265 user.selector.name, closedWorld)); | 265 interceptorData.getInterceptedClassesOn(user.selector.name)); |
| 266 } else if (user is HInvokeSuper && | 266 } else if (user is HInvokeSuper && |
| 267 user.isCallOnInterceptor(closedWorld) && | 267 user.isCallOnInterceptor(closedWorld) && |
| 268 node == user.receiver && | 268 node == user.receiver && |
| 269 useCount(user, node) == 1) { | 269 useCount(user, node) == 1) { |
| 270 interceptedClasses.addAll(interceptorData.getInterceptedClassesOn( | 270 interceptedClasses.addAll( |
| 271 user.selector.name, closedWorld)); | 271 interceptorData.getInterceptedClassesOn(user.selector.name)); |
| 272 } else { | 272 } else { |
| 273 // Use a most general interceptor for other instructions, example, | 273 // Use a most general interceptor for other instructions, example, |
| 274 // is-checks and escaping interceptors. | 274 // is-checks and escaping interceptors. |
| 275 interceptedClasses.addAll(interceptorData.interceptedClasses); | 275 interceptedClasses.addAll(interceptorData.interceptedClasses); |
| 276 break; | 276 break; |
| 277 } | 277 } |
| 278 } | 278 } |
| 279 } | 279 } |
| 280 | 280 |
| 281 node.interceptedClasses = interceptedClasses; | 281 node.interceptedClasses = interceptedClasses; |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 342 block.addAfter(user, replacement); | 342 block.addAfter(user, replacement); |
| 343 block.rewrite(user, replacement); | 343 block.rewrite(user, replacement); |
| 344 block.remove(user); | 344 block.remove(user); |
| 345 return false; | 345 return false; |
| 346 } | 346 } |
| 347 | 347 |
| 348 if (user is HIs) { | 348 if (user is HIs) { |
| 349 // See if we can rewrite the is-check to use 'instanceof', i.e. rewrite | 349 // See if we can rewrite the is-check to use 'instanceof', i.e. rewrite |
| 350 // "getInterceptor(x).$isT" to "x instanceof T". | 350 // "getInterceptor(x).$isT" to "x instanceof T". |
| 351 if (node == user.interceptor) { | 351 if (node == user.interceptor) { |
| 352 if (interceptorData.mayGenerateInstanceofCheck( | 352 if (interceptorData.mayGenerateInstanceofCheck(user.typeExpression)) { |
| 353 user.typeExpression, closedWorld)) { | |
| 354 HInstruction instanceofCheck = new HIs.instanceOf( | 353 HInstruction instanceofCheck = new HIs.instanceOf( |
| 355 user.typeExpression, user.expression, user.instructionType); | 354 user.typeExpression, user.expression, user.instructionType); |
| 356 instanceofCheck.sourceInformation = user.sourceInformation; | 355 instanceofCheck.sourceInformation = user.sourceInformation; |
| 357 instanceofCheck.sourceElement = user.sourceElement; | 356 instanceofCheck.sourceElement = user.sourceElement; |
| 358 return replaceUserWith(instanceofCheck); | 357 return replaceUserWith(instanceofCheck); |
| 359 } | 358 } |
| 360 } | 359 } |
| 361 } else if (user is HInvokeDynamic) { | 360 } else if (user is HInvokeDynamic) { |
| 362 if (node == user.inputs[0]) { | 361 if (node == user.inputs[0]) { |
| 363 // Replace the user with a [HOneShotInterceptor]. | 362 // Replace the user with a [HOneShotInterceptor]. |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 420 instruction = new HInvokeDynamicMethod( | 419 instruction = new HInvokeDynamicMethod( |
| 421 selector, mask, inputs, node.instructionType, true); | 420 selector, mask, inputs, node.instructionType, true); |
| 422 } | 421 } |
| 423 | 422 |
| 424 HBasicBlock block = node.block; | 423 HBasicBlock block = node.block; |
| 425 block.addAfter(node, instruction); | 424 block.addAfter(node, instruction); |
| 426 block.rewrite(node, instruction); | 425 block.rewrite(node, instruction); |
| 427 return true; | 426 return true; |
| 428 } | 427 } |
| 429 } | 428 } |
| OLD | NEW |