diff --git a/src/mips64/lithium-codegen-mips64.cc b/src/mips64/lithium-codegen-mips64.cc index 8b5dca3ea0..39977a237c 100644 --- a/src/mips64/lithium-codegen-mips64.cc +++ b/src/mips64/lithium-codegen-mips64.cc @@ -3774,13 +3774,27 @@ void LCodeGen::EmitIntegerMathAbs(LMathAbs* instr) { Label done; __ Branch(USE_DELAY_SLOT, &done, ge, input, Operand(zero_reg)); __ mov(result, input); - __ dsubu(result, zero_reg, input); + __ subu(result, zero_reg, input); // Overflow if result is still negative, i.e. 0x80000000. DeoptimizeIf(lt, instr, Deoptimizer::kOverflow, result, Operand(zero_reg)); __ bind(&done); } +void LCodeGen::EmitSmiMathAbs(LMathAbs* instr) { + Register input = ToRegister(instr->value()); + Register result = ToRegister(instr->result()); + Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_); + Label done; + __ Branch(USE_DELAY_SLOT, &done, ge, input, Operand(zero_reg)); + __ mov(result, input); + __ dsubu(result, zero_reg, input); + // Overflow if result is still negative, i.e. 0x80000000 00000000. + DeoptimizeIf(lt, instr, Deoptimizer::kOverflow, result, Operand(zero_reg)); + __ bind(&done); +} + + void LCodeGen::DoMathAbs(LMathAbs* instr) { // Class for deferred case. class DeferredMathAbsTaggedHeapNumber final : public LDeferredCode { @@ -3801,8 +3815,10 @@ void LCodeGen::DoMathAbs(LMathAbs* instr) { FPURegister input = ToDoubleRegister(instr->value()); FPURegister result = ToDoubleRegister(instr->result()); __ abs_d(result, input); - } else if (r.IsSmiOrInteger32()) { + } else if (r.IsInteger32()) { EmitIntegerMathAbs(instr); + } else if (r.IsSmi()) { + EmitSmiMathAbs(instr); } else { // Representation is tagged. DeferredMathAbsTaggedHeapNumber* deferred = @@ -3811,7 +3827,7 @@ void LCodeGen::DoMathAbs(LMathAbs* instr) { // Smi check. __ JumpIfNotSmi(input, deferred->entry()); // If smi, handle it directly. - EmitIntegerMathAbs(instr); + EmitSmiMathAbs(instr); __ bind(deferred->exit()); } } diff --git a/src/mips64/lithium-codegen-mips64.h b/src/mips64/lithium-codegen-mips64.h index 904a62cea8..0afae2dd46 100644 --- a/src/mips64/lithium-codegen-mips64.h +++ b/src/mips64/lithium-codegen-mips64.h @@ -251,6 +251,7 @@ class LCodeGen: public LCodeGenBase { String::Encoding encoding); void EmitIntegerMathAbs(LMathAbs* instr); + void EmitSmiMathAbs(LMathAbs* instr); // Support for recording safepoint and position information. void RecordSafepoint(LPointerMap* pointers, diff --git a/test/mjsunit/math-abs.js b/test/mjsunit/math-abs.js index b90ae0917c..4fb72baaa9 100644 --- a/test/mjsunit/math-abs.js +++ b/test/mjsunit/math-abs.js @@ -120,3 +120,19 @@ assertEquals(1, foo2()); assertEquals(1, foo2()); %OptimizeFunctionOnNextCall(foo2); assertEquals(1, foo2()); + +// Regression test for Integer input of Math.abs on mips64. +function absHalf(bits) { + var x = 1 << (bits - 1); + var half = Math.abs(x); + return half; + +} + +// Create minimum integer input for abs() using bitwise operations +// that should overflow. +bits = 32; +assertEquals(2147483648, absHalf(bits)); +assertEquals(2147483648, absHalf(bits)); +%OptimizeFunctionOnNextCall(absHalf); +assertEquals(2147483648, absHalf(bits));