Index: sdk/lib/_internal/compiler/implementation/ssa/invoke_dynamic_specializers.dart |
=================================================================== |
--- sdk/lib/_internal/compiler/implementation/ssa/invoke_dynamic_specializers.dart (revision 31017) |
+++ sdk/lib/_internal/compiler/implementation/ssa/invoke_dynamic_specializers.dart (working copy) |
@@ -229,6 +229,18 @@ |
} |
HInstruction newBuiltinVariant(HInvokeDynamic instruction, Compiler compiler); |
+ |
+ Selector renameToOptimizedSelector(String name, |
+ Selector selector, |
+ Compiler compiler) { |
+ if (selector.name == name) return selector; |
+ return new TypedSelector( |
+ selector.mask, |
+ new Selector(SelectorKind.CALL, |
+ name, |
+ compiler.interceptorsLibrary, |
+ selector.argumentCount)); |
+ } |
} |
class AddSpecializer extends BinaryArithmeticSpecializer { |
@@ -359,10 +371,38 @@ |
return super.computeTypeFromInputTypes(instruction, compiler); |
} |
+ bool isNotZero(HInstruction instruction, Compiler compiler) { |
+ if (!instruction.isConstantInteger()) return false; |
+ HConstant rightConstant = instruction; |
+ IntConstant intConstant = rightConstant.constant; |
+ int count = intConstant.value; |
+ return count != 0; |
+ } |
+ |
+ HInstruction tryConvertToBuiltin(HInvokeDynamic instruction, |
+ Compiler compiler) { |
+ HInstruction left = instruction.inputs[1]; |
+ HInstruction right = instruction.inputs[2]; |
+ if (isBuiltin(instruction, compiler)) { |
+ if (right.isPositiveInteger(compiler) && isNotZero(right, compiler)) { |
+ if (left.isUInt31(compiler)) { |
+ return newBuiltinVariant(instruction, compiler); |
+ } |
+ clearAllSideEffects(instruction); |
+ // We can call _tdivFast because the rhs is a 32bit integer |
+ // and not 0, nor -1. |
+ instruction.selector = renameToOptimizedSelector( |
+ '_tdivFast', instruction.selector, compiler); |
+ } |
+ } |
+ return null; |
+ } |
+ |
HInstruction newBuiltinVariant(HInvokeDynamic instruction, |
Compiler compiler) { |
- // Truncating divide does not have a JS equivalent. |
- return null; |
+ return new HTruncatingDivide( |
+ instruction.inputs[1], instruction.inputs[2], |
+ instruction.selector, computeTypeFromInputTypes(instruction, compiler)); |
} |
} |
@@ -415,6 +455,11 @@ |
// the instruction does not have any side effect, and that it |
// can be GVN'ed. |
clearAllSideEffects(instruction); |
+ Selector selector = instruction.selector; |
+ if (isPositive(right, compiler)) { |
+ instruction.selector = renameToOptimizedSelector( |
+ '_shlPositive', instruction.selector, compiler); |
+ } |
} |
return null; |
} |
@@ -452,6 +497,16 @@ |
// the instruction does not have any side effect, and that it |
// can be GVN'ed. |
clearAllSideEffects(instruction); |
+ if (isPositive(right, compiler) && isPositive(left, compiler)) { |
+ instruction.selector = renameToOptimizedSelector( |
+ '_shrBothPositive', instruction.selector, compiler); |
+ } else if (isPositive(left, compiler) && right.isNumber(compiler)) { |
+ instruction.selector = renameToOptimizedSelector( |
+ '_shrReceiverPositive', instruction.selector, compiler); |
+ } else if (isPositive(right, compiler)) { |
+ instruction.selector = renameToOptimizedSelector( |
+ '_shrOtherPositive', instruction.selector, compiler); |
+ } |
} |
return null; |
} |