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 * [InvokeDynamicSpecializer] and its subclasses are helpers to | 8 * [InvokeDynamicSpecializer] and its subclasses are helpers to |
9 * optimize intercepted dynamic calls. It knows what input types | 9 * optimize intercepted dynamic calls. It knows what input types |
10 * would be beneficial for performance, and how to change a invoke | 10 * would be beneficial for performance, and how to change a invoke |
(...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
222 | 222 |
223 bool inputsArePositiveIntegers(HInstruction instruction, Compiler compiler) { | 223 bool inputsArePositiveIntegers(HInstruction instruction, Compiler compiler) { |
224 HInstruction left = instruction.inputs[1]; | 224 HInstruction left = instruction.inputs[1]; |
225 HInstruction right = instruction.inputs[2]; | 225 HInstruction right = instruction.inputs[2]; |
226 JavaScriptBackend backend = compiler.backend; | 226 JavaScriptBackend backend = compiler.backend; |
227 return left.isPositiveIntegerOrNull(compiler) | 227 return left.isPositiveIntegerOrNull(compiler) |
228 && right.isPositiveIntegerOrNull(compiler); | 228 && right.isPositiveIntegerOrNull(compiler); |
229 } | 229 } |
230 | 230 |
231 HInstruction newBuiltinVariant(HInvokeDynamic instruction, Compiler compiler); | 231 HInstruction newBuiltinVariant(HInvokeDynamic instruction, Compiler compiler); |
| 232 |
| 233 Selector renameToOptimizedSelector(String name, |
| 234 Selector selector, |
| 235 Compiler compiler) { |
| 236 if (selector.name == name) return selector; |
| 237 return new TypedSelector( |
| 238 selector.mask, |
| 239 new Selector(SelectorKind.CALL, |
| 240 name, |
| 241 compiler.interceptorsLibrary, |
| 242 selector.argumentCount)); |
| 243 } |
232 } | 244 } |
233 | 245 |
234 class AddSpecializer extends BinaryArithmeticSpecializer { | 246 class AddSpecializer extends BinaryArithmeticSpecializer { |
235 const AddSpecializer(); | 247 const AddSpecializer(); |
236 | 248 |
237 TypeMask computeTypeFromInputTypes(HInvokeDynamic instruction, | 249 TypeMask computeTypeFromInputTypes(HInvokeDynamic instruction, |
238 Compiler compiler) { | 250 Compiler compiler) { |
239 if (inputsArePositiveIntegers(instruction, compiler)) { | 251 if (inputsArePositiveIntegers(instruction, compiler)) { |
240 JavaScriptBackend backend = compiler.backend; | 252 JavaScriptBackend backend = compiler.backend; |
241 return backend.positiveIntType; | 253 return backend.positiveIntType; |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
352 | 364 |
353 TypeMask computeTypeFromInputTypes(HInvokeDynamic instruction, | 365 TypeMask computeTypeFromInputTypes(HInvokeDynamic instruction, |
354 Compiler compiler) { | 366 Compiler compiler) { |
355 if (inputsArePositiveIntegers(instruction, compiler)) { | 367 if (inputsArePositiveIntegers(instruction, compiler)) { |
356 JavaScriptBackend backend = compiler.backend; | 368 JavaScriptBackend backend = compiler.backend; |
357 return backend.positiveIntType; | 369 return backend.positiveIntType; |
358 } | 370 } |
359 return super.computeTypeFromInputTypes(instruction, compiler); | 371 return super.computeTypeFromInputTypes(instruction, compiler); |
360 } | 372 } |
361 | 373 |
| 374 bool isNotZero(HInstruction instruction, Compiler compiler) { |
| 375 if (!instruction.isConstantInteger()) return false; |
| 376 HConstant rightConstant = instruction; |
| 377 IntConstant intConstant = rightConstant.constant; |
| 378 int count = intConstant.value; |
| 379 return count != 0; |
| 380 } |
| 381 |
| 382 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction, |
| 383 Compiler compiler) { |
| 384 HInstruction left = instruction.inputs[1]; |
| 385 HInstruction right = instruction.inputs[2]; |
| 386 if (isBuiltin(instruction, compiler)) { |
| 387 if (right.isPositiveInteger(compiler) && isNotZero(right, compiler)) { |
| 388 if (left.isUInt31(compiler)) { |
| 389 return newBuiltinVariant(instruction, compiler); |
| 390 } |
| 391 clearAllSideEffects(instruction); |
| 392 // We can call _tdivFast because the rhs is a 32bit integer |
| 393 // and not 0, nor -1. |
| 394 instruction.selector = renameToOptimizedSelector( |
| 395 '_tdivFast', instruction.selector, compiler); |
| 396 } |
| 397 } |
| 398 return null; |
| 399 } |
| 400 |
362 HInstruction newBuiltinVariant(HInvokeDynamic instruction, | 401 HInstruction newBuiltinVariant(HInvokeDynamic instruction, |
363 Compiler compiler) { | 402 Compiler compiler) { |
364 // Truncating divide does not have a JS equivalent. | 403 return new HTruncatingDivide( |
365 return null; | 404 instruction.inputs[1], instruction.inputs[2], |
| 405 instruction.selector, computeTypeFromInputTypes(instruction, compiler)); |
366 } | 406 } |
367 } | 407 } |
368 | 408 |
369 abstract class BinaryBitOpSpecializer extends BinaryArithmeticSpecializer { | 409 abstract class BinaryBitOpSpecializer extends BinaryArithmeticSpecializer { |
370 const BinaryBitOpSpecializer(); | 410 const BinaryBitOpSpecializer(); |
371 | 411 |
372 TypeMask computeTypeFromInputTypes(HInvokeDynamic instruction, | 412 TypeMask computeTypeFromInputTypes(HInvokeDynamic instruction, |
373 Compiler compiler) { | 413 Compiler compiler) { |
374 // All bitwise operations on primitive types either produce an | 414 // All bitwise operations on primitive types either produce an |
375 // integer or throw an error. | 415 // integer or throw an error. |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
408 HInstruction left = instruction.inputs[1]; | 448 HInstruction left = instruction.inputs[1]; |
409 HInstruction right = instruction.inputs[2]; | 449 HInstruction right = instruction.inputs[2]; |
410 if (left.isNumber(compiler)) { | 450 if (left.isNumber(compiler)) { |
411 if (argumentLessThan32(right)) { | 451 if (argumentLessThan32(right)) { |
412 return newBuiltinVariant(instruction, compiler); | 452 return newBuiltinVariant(instruction, compiler); |
413 } | 453 } |
414 // Even if there is no builtin equivalent instruction, we know | 454 // Even if there is no builtin equivalent instruction, we know |
415 // the instruction does not have any side effect, and that it | 455 // the instruction does not have any side effect, and that it |
416 // can be GVN'ed. | 456 // can be GVN'ed. |
417 clearAllSideEffects(instruction); | 457 clearAllSideEffects(instruction); |
| 458 Selector selector = instruction.selector; |
| 459 if (isPositive(right, compiler)) { |
| 460 instruction.selector = renameToOptimizedSelector( |
| 461 '_shlPositive', instruction.selector, compiler); |
| 462 } |
418 } | 463 } |
419 return null; | 464 return null; |
420 } | 465 } |
421 | 466 |
422 HInstruction newBuiltinVariant(HInvokeDynamic instruction, | 467 HInstruction newBuiltinVariant(HInvokeDynamic instruction, |
423 Compiler compiler) { | 468 Compiler compiler) { |
424 JavaScriptBackend backend = compiler.backend; | 469 JavaScriptBackend backend = compiler.backend; |
425 return new HShiftLeft( | 470 return new HShiftLeft( |
426 instruction.inputs[1], instruction.inputs[2], | 471 instruction.inputs[1], instruction.inputs[2], |
427 instruction.selector, computeTypeFromInputTypes(instruction, compiler)); | 472 instruction.selector, computeTypeFromInputTypes(instruction, compiler)); |
(...skipping 17 matching lines...) Expand all Loading... |
445 HInstruction left = instruction.inputs[1]; | 490 HInstruction left = instruction.inputs[1]; |
446 HInstruction right = instruction.inputs[2]; | 491 HInstruction right = instruction.inputs[2]; |
447 if (left.isNumber(compiler)) { | 492 if (left.isNumber(compiler)) { |
448 if (argumentLessThan32(right) && isPositive(left, compiler)) { | 493 if (argumentLessThan32(right) && isPositive(left, compiler)) { |
449 return newBuiltinVariant(instruction, compiler); | 494 return newBuiltinVariant(instruction, compiler); |
450 } | 495 } |
451 // Even if there is no builtin equivalent instruction, we know | 496 // Even if there is no builtin equivalent instruction, we know |
452 // the instruction does not have any side effect, and that it | 497 // the instruction does not have any side effect, and that it |
453 // can be GVN'ed. | 498 // can be GVN'ed. |
454 clearAllSideEffects(instruction); | 499 clearAllSideEffects(instruction); |
| 500 if (isPositive(right, compiler) && isPositive(left, compiler)) { |
| 501 instruction.selector = renameToOptimizedSelector( |
| 502 '_shrBothPositive', instruction.selector, compiler); |
| 503 } else if (isPositive(left, compiler) && right.isNumber(compiler)) { |
| 504 instruction.selector = renameToOptimizedSelector( |
| 505 '_shrReceiverPositive', instruction.selector, compiler); |
| 506 } else if (isPositive(right, compiler)) { |
| 507 instruction.selector = renameToOptimizedSelector( |
| 508 '_shrOtherPositive', instruction.selector, compiler); |
| 509 } |
455 } | 510 } |
456 return null; | 511 return null; |
457 } | 512 } |
458 | 513 |
459 HInstruction newBuiltinVariant(HInvokeDynamic instruction, | 514 HInstruction newBuiltinVariant(HInvokeDynamic instruction, |
460 Compiler compiler) { | 515 Compiler compiler) { |
461 JavaScriptBackend backend = compiler.backend; | 516 JavaScriptBackend backend = compiler.backend; |
462 return new HShiftRight( | 517 return new HShiftRight( |
463 instruction.inputs[1], instruction.inputs[2], | 518 instruction.inputs[1], instruction.inputs[2], |
464 instruction.selector, computeTypeFromInputTypes(instruction, compiler)); | 519 instruction.selector, computeTypeFromInputTypes(instruction, compiler)); |
(...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
669 } | 724 } |
670 | 725 |
671 HInstruction newBuiltinVariant(HInvokeDynamic instruction, | 726 HInstruction newBuiltinVariant(HInvokeDynamic instruction, |
672 Compiler compiler) { | 727 Compiler compiler) { |
673 JavaScriptBackend backend = compiler.backend; | 728 JavaScriptBackend backend = compiler.backend; |
674 return new HLessEqual( | 729 return new HLessEqual( |
675 instruction.inputs[1], instruction.inputs[2], | 730 instruction.inputs[1], instruction.inputs[2], |
676 instruction.selector, backend.boolType); | 731 instruction.selector, backend.boolType); |
677 } | 732 } |
678 } | 733 } |
OLD | NEW |