Index: src/mips/code-stubs-mips.cc |
diff --git a/src/mips/code-stubs-mips.cc b/src/mips/code-stubs-mips.cc |
index c9999949714127510e219802b767c3afae30b6d4..8867b19f0727a96f3f8aa9bd7f4921b0e256b49c 100644 |
--- a/src/mips/code-stubs-mips.cc |
+++ b/src/mips/code-stubs-mips.cc |
@@ -2002,6 +2002,8 @@ void UnaryOpStub::GenerateHeapNumberCodeSub(MacroAssembler* masm, |
void UnaryOpStub::GenerateHeapNumberCodeBitNot( |
MacroAssembler* masm, |
Label* slow) { |
+ Label impossible; |
+ |
EmitCheckForHeapNumber(masm, a0, a1, t2, slow); |
// Convert the heap number in a0 to an untagged integer in a1. |
__ ConvertToInt32(a0, a1, a2, a3, f0, slow); |
@@ -2020,17 +2022,28 @@ void UnaryOpStub::GenerateHeapNumberCodeBitNot( |
__ bind(&try_float); |
if (mode_ == UNARY_NO_OVERWRITE) { |
Label slow_allocate_heapnumber, heapnumber_allocated; |
- __ AllocateHeapNumber(v0, a2, a3, t2, &slow_allocate_heapnumber); |
+ // Allocate a new heap number without zapping v0, which we need if it fails. |
+ __ AllocateHeapNumber(a2, a3, t0, t2, &slow_allocate_heapnumber); |
__ jmp(&heapnumber_allocated); |
__ bind(&slow_allocate_heapnumber); |
__ EnterInternalFrame(); |
- __ push(a1); |
+ __ push(v0); // Push the heap number, not the untagged int32. |
__ CallRuntime(Runtime::kNumberAlloc, 0); |
- __ pop(a1); |
+ __ mov(a2, v0); // Move the new heap number into a2. |
+ // Get the heap number into v0, now that the new heap number is in a2. |
+ __ pop(v0); |
__ LeaveInternalFrame(); |
+ // Convert the heap number in v0 to an untagged integer in a1. |
+ // This can't go slow-case because it's the same number we already |
+ // converted once again. |
+ __ ConvertToInt32(v0, a1, a3, t0, f0, &impossible); |
+ // Negate the result. |
+ __ Xor(a1, a1, -1); |
+ |
__ bind(&heapnumber_allocated); |
+ __ mov(v0, a2); // Move newly allocated heap number to v0. |
} |
if (CpuFeatures::IsSupported(FPU)) { |
@@ -2046,6 +2059,11 @@ void UnaryOpStub::GenerateHeapNumberCodeBitNot( |
WriteInt32ToHeapNumberStub stub(a1, v0, a2, a3); |
__ Jump(stub.GetCode(), RelocInfo::CODE_TARGET); |
} |
+ |
+ __ bind(&impossible); |
+ if (FLAG_debug_code) { |
+ __ stop("Incorrect assumption in bit-not stub"); |
+ } |
} |