| Index: pkg/compiler/lib/src/ssa/invoke_dynamic_specializers.dart
|
| diff --git a/pkg/compiler/lib/src/ssa/invoke_dynamic_specializers.dart b/pkg/compiler/lib/src/ssa/invoke_dynamic_specializers.dart
|
| index 7f5ff1d584fcc09a01da15778c627a2e97d30d11..c8cfebc91b45293457c033c1b59d729945acb2be 100644
|
| --- a/pkg/compiler/lib/src/ssa/invoke_dynamic_specializers.dart
|
| +++ b/pkg/compiler/lib/src/ssa/invoke_dynamic_specializers.dart
|
| @@ -223,11 +223,16 @@ abstract class BinaryArithmeticSpecializer extends InvokeDynamicSpecializer {
|
| bool inputsArePositiveIntegers(HInstruction instruction, Compiler compiler) {
|
| HInstruction left = instruction.inputs[1];
|
| HInstruction right = instruction.inputs[2];
|
| - JavaScriptBackend backend = compiler.backend;
|
| return left.isPositiveIntegerOrNull(compiler)
|
| && right.isPositiveIntegerOrNull(compiler);
|
| }
|
|
|
| + bool inputsAreUInt31(HInstruction instruction, Compiler compiler) {
|
| + HInstruction left = instruction.inputs[1];
|
| + HInstruction right = instruction.inputs[2];
|
| + return left.isUInt31(compiler) && right.isUInt31(compiler);
|
| + }
|
| +
|
| HInstruction newBuiltinVariant(HInvokeDynamic instruction, Compiler compiler);
|
|
|
| Selector renameToOptimizedSelector(String name,
|
| @@ -249,6 +254,10 @@ class AddSpecializer extends BinaryArithmeticSpecializer {
|
|
|
| TypeMask computeTypeFromInputTypes(HInvokeDynamic instruction,
|
| Compiler compiler) {
|
| + if (inputsAreUInt31(instruction, compiler)) {
|
| + JavaScriptBackend backend = compiler.backend;
|
| + return backend.uint32Type;
|
| + }
|
| if (inputsArePositiveIntegers(instruction, compiler)) {
|
| JavaScriptBackend backend = compiler.backend;
|
| return backend.positiveIntType;
|
| @@ -313,6 +322,7 @@ class ModuloSpecializer extends BinaryArithmeticSpecializer {
|
| HInstruction newBuiltinVariant(HInvokeDynamic instruction,
|
| Compiler compiler) {
|
| // Modulo cannot be mapped to the native operator (different semantics).
|
| + // TODO(sra): For non-negative values we can use JavaScript's %.
|
| return null;
|
| }
|
| }
|
| @@ -365,8 +375,11 @@ class TruncatingDivideSpecializer extends BinaryArithmeticSpecializer {
|
|
|
| TypeMask computeTypeFromInputTypes(HInvokeDynamic instruction,
|
| Compiler compiler) {
|
| + JavaScriptBackend backend = compiler.backend;
|
| + if (hasUint31Result(instruction, compiler)) {
|
| + return backend.uint31Type;
|
| + }
|
| if (inputsArePositiveIntegers(instruction, compiler)) {
|
| - JavaScriptBackend backend = compiler.backend;
|
| return backend.positiveIntType;
|
| }
|
| return super.computeTypeFromInputTypes(instruction, compiler);
|
| @@ -380,13 +393,35 @@ class TruncatingDivideSpecializer extends BinaryArithmeticSpecializer {
|
| return count != 0;
|
| }
|
|
|
| + bool isTwoOrGreater(HInstruction instruction, Compiler compiler) {
|
| + if (!instruction.isConstantInteger()) return false;
|
| + HConstant rightConstant = instruction;
|
| + IntConstantValue intConstant = rightConstant.constant;
|
| + int count = intConstant.primitiveValue;
|
| + return count >= 2;
|
| + }
|
| +
|
| + bool hasUint31Result(HInstruction instruction, Compiler compiler) {
|
| + HInstruction left = instruction.inputs[1];
|
| + HInstruction right = instruction.inputs[2];
|
| + if (right.isPositiveInteger(compiler)) {
|
| + if (left.isUInt31(compiler) && isNotZero(right, compiler)) {
|
| + return true;
|
| + }
|
| + if (left.isUInt32(compiler) && isTwoOrGreater(right, compiler)) {
|
| + return true;
|
| + }
|
| + }
|
| + return false;
|
| + }
|
| +
|
| 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)) {
|
| + if (hasUint31Result(instruction, compiler)) {
|
| return newBuiltinVariant(instruction, compiler);
|
| }
|
| // We can call _tdivFast because the rhs is a 32bit integer
|
|
|