From eed788a7bb94220330f2ad337738e48034aad6e5 Mon Sep 17 00:00:00 2001 From: "rodolph.perfetta@gmail.com" Date: Mon, 22 Apr 2013 21:30:57 +0000 Subject: [PATCH] ARM: VFP cleanup now that VFP2 is the baseline. BUG=none TEST=none Review URL: https://chromiumcodereview.appspot.com/14119008 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@14382 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/arm/code-stubs-arm.cc | 573 +++++++---------------------------------- src/arm/code-stubs-arm.h | 136 ---------- src/arm/ic-arm.cc | 8 +- src/arm/lithium-codegen-arm.cc | 8 +- src/arm/macro-assembler-arm.cc | 227 ++++++++++------ src/arm/macro-assembler-arm.h | 90 ++++--- src/arm/stub-cache-arm.cc | 43 +--- 7 files changed, 308 insertions(+), 777 deletions(-) diff --git a/src/arm/code-stubs-arm.cc b/src/arm/code-stubs-arm.cc index 73091fb..66bd6b5 100644 --- a/src/arm/code-stubs-arm.cc +++ b/src/arm/code-stubs-arm.cc @@ -530,318 +530,6 @@ void ConvertToDoubleStub::Generate(MacroAssembler* masm) { } -void FloatingPointHelper::LoadSmis(MacroAssembler* masm, - FloatingPointHelper::Destination destination, - Register scratch1, - Register scratch2) { - __ mov(scratch1, Operand(r0, ASR, kSmiTagSize)); - __ vmov(d7.high(), scratch1); - __ vcvt_f64_s32(d7, d7.high()); - __ mov(scratch1, Operand(r1, ASR, kSmiTagSize)); - __ vmov(d6.high(), scratch1); - __ vcvt_f64_s32(d6, d6.high()); - if (destination == kCoreRegisters) { - __ vmov(r2, r3, d7); - __ vmov(r0, r1, d6); - } -} - - -void FloatingPointHelper::LoadNumber(MacroAssembler* masm, - Destination destination, - Register object, - DwVfpRegister dst, - Register dst1, - Register dst2, - Register heap_number_map, - Register scratch1, - Register scratch2, - Label* not_number) { - __ AssertRootValue(heap_number_map, - Heap::kHeapNumberMapRootIndex, - "HeapNumberMap register clobbered."); - - Label is_smi, done; - - // Smi-check - __ UntagAndJumpIfSmi(scratch1, object, &is_smi); - // Heap number check - __ JumpIfNotHeapNumber(object, heap_number_map, scratch1, not_number); - - // Handle loading a double from a heap number. - if (destination == kVFPRegisters) { - // Load the double from tagged HeapNumber to double register. - __ sub(scratch1, object, Operand(kHeapObjectTag)); - __ vldr(dst, scratch1, HeapNumber::kValueOffset); - } else { - ASSERT(destination == kCoreRegisters); - // Load the double from heap number to dst1 and dst2 in double format. - __ Ldrd(dst1, dst2, FieldMemOperand(object, HeapNumber::kValueOffset)); - } - __ jmp(&done); - - // Handle loading a double from a smi. - __ bind(&is_smi); - // Convert smi to double using VFP instructions. - __ vmov(dst.high(), scratch1); - __ vcvt_f64_s32(dst, dst.high()); - if (destination == kCoreRegisters) { - // Load the converted smi to dst1 and dst2 in double format. - __ vmov(dst1, dst2, dst); - } - - __ bind(&done); -} - - -void FloatingPointHelper::ConvertNumberToInt32(MacroAssembler* masm, - Register object, - Register dst, - Register heap_number_map, - Register scratch1, - Register scratch2, - Register scratch3, - DwVfpRegister double_scratch1, - DwVfpRegister double_scratch2, - Label* not_number) { - Label done; - __ AssertRootValue(heap_number_map, - Heap::kHeapNumberMapRootIndex, - "HeapNumberMap register clobbered."); - - __ UntagAndJumpIfSmi(dst, object, &done); - __ ldr(scratch1, FieldMemOperand(object, HeapNumber::kMapOffset)); - __ cmp(scratch1, heap_number_map); - __ b(ne, not_number); - __ ECMAConvertNumberToInt32(object, dst, - scratch1, scratch2, scratch3, - double_scratch1, double_scratch2); - __ bind(&done); -} - - -void FloatingPointHelper::ConvertIntToDouble(MacroAssembler* masm, - Register int_scratch, - Destination destination, - DwVfpRegister double_dst, - Register dst_mantissa, - Register dst_exponent, - Register scratch2, - SwVfpRegister single_scratch) { - ASSERT(!int_scratch.is(scratch2)); - ASSERT(!int_scratch.is(dst_mantissa)); - ASSERT(!int_scratch.is(dst_exponent)); - - Label done; - - __ vmov(single_scratch, int_scratch); - __ vcvt_f64_s32(double_dst, single_scratch); - if (destination == kCoreRegisters) { - __ vmov(dst_mantissa, dst_exponent, double_dst); - } - __ bind(&done); -} - - -void FloatingPointHelper::LoadNumberAsInt32Double(MacroAssembler* masm, - Register object, - Destination destination, - DwVfpRegister double_dst, - DwVfpRegister double_scratch, - Register dst_mantissa, - Register dst_exponent, - Register heap_number_map, - Register scratch1, - Register scratch2, - SwVfpRegister single_scratch, - Label* not_int32) { - ASSERT(!scratch1.is(object) && !scratch2.is(object)); - ASSERT(!scratch1.is(scratch2)); - ASSERT(!heap_number_map.is(object) && - !heap_number_map.is(scratch1) && - !heap_number_map.is(scratch2)); - - Label done, obj_is_not_smi; - - __ JumpIfNotSmi(object, &obj_is_not_smi); - __ SmiUntag(scratch1, object); - ConvertIntToDouble(masm, scratch1, destination, double_dst, dst_mantissa, - dst_exponent, scratch2, single_scratch); - __ b(&done); - - __ bind(&obj_is_not_smi); - __ AssertRootValue(heap_number_map, - Heap::kHeapNumberMapRootIndex, - "HeapNumberMap register clobbered."); - __ JumpIfNotHeapNumber(object, heap_number_map, scratch1, not_int32); - - // Load the number. - // Load the double value. - __ sub(scratch1, object, Operand(kHeapObjectTag)); - __ vldr(double_dst, scratch1, HeapNumber::kValueOffset); - - __ TestDoubleIsInt32(double_dst, double_scratch); - // Jump to not_int32 if the operation did not succeed. - __ b(ne, not_int32); - - if (destination == kCoreRegisters) { - __ vmov(dst_mantissa, dst_exponent, double_dst); - } - __ bind(&done); -} - - -void FloatingPointHelper::LoadNumberAsInt32(MacroAssembler* masm, - Register object, - Register dst, - Register heap_number_map, - Register scratch1, - Register scratch2, - Register scratch3, - DwVfpRegister double_scratch0, - DwVfpRegister double_scratch1, - Label* not_int32) { - ASSERT(!dst.is(object)); - ASSERT(!scratch1.is(object) && !scratch2.is(object) && !scratch3.is(object)); - ASSERT(!scratch1.is(scratch2) && - !scratch1.is(scratch3) && - !scratch2.is(scratch3)); - - Label done, maybe_undefined; - - __ UntagAndJumpIfSmi(dst, object, &done); - - __ AssertRootValue(heap_number_map, - Heap::kHeapNumberMapRootIndex, - "HeapNumberMap register clobbered."); - - __ JumpIfNotHeapNumber(object, heap_number_map, scratch1, &maybe_undefined); - - // Object is a heap number. - // Convert the floating point value to a 32-bit integer. - // Load the double value. - __ sub(scratch1, object, Operand(kHeapObjectTag)); - __ vldr(double_scratch0, scratch1, HeapNumber::kValueOffset); - - __ TryDoubleToInt32Exact(dst, double_scratch0, double_scratch1); - // Jump to not_int32 if the operation did not succeed. - __ b(ne, not_int32); - __ b(&done); - - __ bind(&maybe_undefined); - __ CompareRoot(object, Heap::kUndefinedValueRootIndex); - __ b(ne, not_int32); - // |undefined| is truncated to 0. - __ mov(dst, Operand(Smi::FromInt(0))); - // Fall through. - - __ bind(&done); -} - - -void FloatingPointHelper::DoubleIs32BitInteger(MacroAssembler* masm, - Register src_exponent, - Register src_mantissa, - Register dst, - Register scratch, - Label* not_int32) { - // Get exponent alone in scratch. - __ Ubfx(scratch, - src_exponent, - HeapNumber::kExponentShift, - HeapNumber::kExponentBits); - - // Substract the bias from the exponent. - __ sub(scratch, scratch, Operand(HeapNumber::kExponentBias), SetCC); - - // src1: higher (exponent) part of the double value. - // src2: lower (mantissa) part of the double value. - // scratch: unbiased exponent. - - // Fast cases. Check for obvious non 32-bit integer values. - // Negative exponent cannot yield 32-bit integers. - __ b(mi, not_int32); - // Exponent greater than 31 cannot yield 32-bit integers. - // Also, a positive value with an exponent equal to 31 is outside of the - // signed 32-bit integer range. - // Another way to put it is that if (exponent - signbit) > 30 then the - // number cannot be represented as an int32. - Register tmp = dst; - __ sub(tmp, scratch, Operand(src_exponent, LSR, 31)); - __ cmp(tmp, Operand(30)); - __ b(gt, not_int32); - // - Bits [21:0] in the mantissa are not null. - __ tst(src_mantissa, Operand(0x3fffff)); - __ b(ne, not_int32); - - // Otherwise the exponent needs to be big enough to shift left all the - // non zero bits left. So we need the (30 - exponent) last bits of the - // 31 higher bits of the mantissa to be null. - // Because bits [21:0] are null, we can check instead that the - // (32 - exponent) last bits of the 32 higher bits of the mantissa are null. - - // Get the 32 higher bits of the mantissa in dst. - __ Ubfx(dst, - src_mantissa, - HeapNumber::kMantissaBitsInTopWord, - 32 - HeapNumber::kMantissaBitsInTopWord); - __ orr(dst, - dst, - Operand(src_exponent, LSL, HeapNumber::kNonMantissaBitsInTopWord)); - - // Create the mask and test the lower bits (of the higher bits). - __ rsb(scratch, scratch, Operand(32)); - __ mov(src_mantissa, Operand(1)); - __ mov(src_exponent, Operand(src_mantissa, LSL, scratch)); - __ sub(src_exponent, src_exponent, Operand(1)); - __ tst(dst, src_exponent); - __ b(ne, not_int32); -} - - -void FloatingPointHelper::CallCCodeForDoubleOperation( - MacroAssembler* masm, - Token::Value op, - Register heap_number_result, - Register scratch) { - // Using core registers: - // r0: Left value (least significant part of mantissa). - // r1: Left value (sign, exponent, top of mantissa). - // r2: Right value (least significant part of mantissa). - // r3: Right value (sign, exponent, top of mantissa). - - // Assert that heap_number_result is callee-saved. - // We currently always use r5 to pass it. - ASSERT(heap_number_result.is(r5)); - - // Push the current return address before the C call. Return will be - // through pop(pc) below. - __ push(lr); - __ PrepareCallCFunction(0, 2, scratch); - if (masm->use_eabi_hardfloat()) { - __ vmov(d0, r0, r1); - __ vmov(d1, r2, r3); - } - { - AllowExternalCallThatCantCauseGC scope(masm); - __ CallCFunction( - ExternalReference::double_fp_operation(op, masm->isolate()), 0, 2); - } - // Store answer in the overwritable heap number. Double returned in - // registers r0 and r1 or in d0. - if (masm->use_eabi_hardfloat()) { - __ vstr(d0, - FieldMemOperand(heap_number_result, HeapNumber::kValueOffset)); - } else { - __ Strd(r0, r1, FieldMemOperand(heap_number_result, - HeapNumber::kValueOffset)); - } - // Place heap_number_result in r0 and return to the pushed return address. - __ mov(r0, Operand(heap_number_result)); - __ pop(pc); -} - - bool WriteInt32ToHeapNumberStub::IsPregenerated() { // These variants are compiled ahead of time. See next method. if (the_int_.is(r1) && the_heap_number_.is(r0) && scratch_.is(r2)) { @@ -1079,57 +767,6 @@ static void EmitSmiNonsmiComparison(MacroAssembler* masm, } -void EmitNanCheck(MacroAssembler* masm, Label* lhs_not_nan, Condition cond) { - bool exp_first = (HeapNumber::kExponentOffset == HeapNumber::kValueOffset); - Register rhs_exponent = exp_first ? r0 : r1; - Register lhs_exponent = exp_first ? r2 : r3; - Register rhs_mantissa = exp_first ? r1 : r0; - Register lhs_mantissa = exp_first ? r3 : r2; - Label one_is_nan, neither_is_nan; - - __ Sbfx(r4, - lhs_exponent, - HeapNumber::kExponentShift, - HeapNumber::kExponentBits); - // NaNs have all-one exponents so they sign extend to -1. - __ cmp(r4, Operand(-1)); - __ b(ne, lhs_not_nan); - __ mov(r4, - Operand(lhs_exponent, LSL, HeapNumber::kNonMantissaBitsInTopWord), - SetCC); - __ b(ne, &one_is_nan); - __ cmp(lhs_mantissa, Operand::Zero()); - __ b(ne, &one_is_nan); - - __ bind(lhs_not_nan); - __ Sbfx(r4, - rhs_exponent, - HeapNumber::kExponentShift, - HeapNumber::kExponentBits); - // NaNs have all-one exponents so they sign extend to -1. - __ cmp(r4, Operand(-1)); - __ b(ne, &neither_is_nan); - __ mov(r4, - Operand(rhs_exponent, LSL, HeapNumber::kNonMantissaBitsInTopWord), - SetCC); - __ b(ne, &one_is_nan); - __ cmp(rhs_mantissa, Operand::Zero()); - __ b(eq, &neither_is_nan); - - __ bind(&one_is_nan); - // NaN comparisons always fail. - // Load whatever we need in r0 to make the comparison fail. - if (cond == lt || cond == le) { - __ mov(r0, Operand(GREATER)); - } else { - __ mov(r0, Operand(LESS)); - } - __ Ret(); - - __ bind(&neither_is_nan); -} - - // See comment at call site. static void EmitStrictTwoHeapObjectCompare(MacroAssembler* masm, Register lhs, @@ -1845,8 +1482,10 @@ void UnaryOpStub::GenerateHeapNumberCodeSub(MacroAssembler* masm, void UnaryOpStub::GenerateHeapNumberCodeBitNot(MacroAssembler* masm, Label* slow) { EmitCheckForHeapNumber(masm, r0, r1, r6, slow); + // Convert the heap number in r0 to an untagged integer in r1. - __ ECMAConvertNumberToInt32(r0, r1, r2, r3, r4, d0, d1); + __ vldr(d0, FieldMemOperand(r0, HeapNumber::kValueOffset)); + __ ECMAToInt32(r1, d0, r2, r3, r4, d1); // Do the bitwise operation and check if the result fits in a smi. Label try_float; @@ -1938,6 +1577,50 @@ void UnaryOpStub::GenerateGenericCodeFallback(MacroAssembler* masm) { } +// Generates code to call a C function to do a double operation. +// This code never falls through, but returns with a heap number containing +// the result in r0. +// Register heapnumber_result must be a heap number in which the +// result of the operation will be stored. +// Requires the following layout on entry: +// d0: Left value. +// d1: Right value. +// If soft float ABI, use also r0, r1, r2, r3. +static void CallCCodeForDoubleOperation(MacroAssembler* masm, + Token::Value op, + Register heap_number_result, + Register scratch) { + // Assert that heap_number_result is callee-saved. + // We currently always use r5 to pass it. + ASSERT(heap_number_result.is(r5)); + + // Push the current return address before the C call. Return will be + // through pop(pc) below. + __ push(lr); + __ PrepareCallCFunction(0, 2, scratch); + if (!masm->use_eabi_hardfloat()) { + __ vmov(r0, r1, d0); + __ vmov(r2, r3, d1); + } + { + AllowExternalCallThatCantCauseGC scope(masm); + __ CallCFunction( + ExternalReference::double_fp_operation(op, masm->isolate()), 0, 2); + } + // Store answer in the overwritable heap number. Double returned in + // registers r0 and r1 or in d0. + if (masm->use_eabi_hardfloat()) { + __ vstr(d0, FieldMemOperand(heap_number_result, HeapNumber::kValueOffset)); + } else { + __ Strd(r0, r1, + FieldMemOperand(heap_number_result, HeapNumber::kValueOffset)); + } + // Place heap_number_result in r0 and return to the pushed return address. + __ mov(r0, Operand(heap_number_result)); + __ pop(pc); +} + + void BinaryOpStub::Initialize() { platform_specific_bit_ = true; // VFP2 is a base requirement for V8 } @@ -2215,64 +1898,56 @@ void BinaryOpStub_GenerateFPOperation(MacroAssembler* masm, case Token::MUL: case Token::DIV: case Token::MOD: { - // Load left and right operands into d6 and d7 or r0/r1 and r2/r3 - // depending on whether VFP3 is available or not. - FloatingPointHelper::Destination destination = - op != Token::MOD ? - FloatingPointHelper::kVFPRegisters : - FloatingPointHelper::kCoreRegisters; - // Allocate new heap number for result. Register result = r5; BinaryOpStub_GenerateHeapResultAllocation( masm, result, heap_number_map, scratch1, scratch2, gc_required, mode); - // Load the operands. + // Load left and right operands into d0 and d1. if (smi_operands) { - FloatingPointHelper::LoadSmis(masm, destination, scratch1, scratch2); + __ SmiUntag(scratch1, right); + __ vmov(d1.high(), scratch1); + __ vcvt_f64_s32(d1, d1.high()); + __ SmiUntag(scratch1, left); + __ vmov(d0.high(), scratch1); + __ vcvt_f64_s32(d0, d0.high()); } else { - // Load right operand to d7 or r2/r3. + // Load right operand into d1. if (right_type == BinaryOpIC::INT32) { - FloatingPointHelper::LoadNumberAsInt32Double( - masm, right, destination, d7, d8, r2, r3, heap_number_map, - scratch1, scratch2, s0, miss); + __ LoadNumberAsInt32Double( + right, d1, heap_number_map, scratch1, d8, miss); } else { Label* fail = (right_type == BinaryOpIC::NUMBER) ? miss : not_numbers; - FloatingPointHelper::LoadNumber( - masm, destination, right, d7, r2, r3, heap_number_map, - scratch1, scratch2, fail); + __ LoadNumber(right, d1, heap_number_map, scratch1, fail); } - // Load left operand to d6 or r0/r1. This keeps r0/r1 intact if it - // jumps to |miss|. + // Load left operand into d0. if (left_type == BinaryOpIC::INT32) { - FloatingPointHelper::LoadNumberAsInt32Double( - masm, left, destination, d6, d8, r0, r1, heap_number_map, - scratch1, scratch2, s0, miss); + __ LoadNumberAsInt32Double( + left, d0, heap_number_map, scratch1, d8, miss); } else { Label* fail = (left_type == BinaryOpIC::NUMBER) ? miss : not_numbers; - FloatingPointHelper::LoadNumber( - masm, destination, left, d6, r0, r1, heap_number_map, - scratch1, scratch2, fail); + __ LoadNumber( + left, d0, heap_number_map, scratch1, fail); } } // Calculate the result. - if (destination == FloatingPointHelper::kVFPRegisters) { + if (op != Token::MOD) { // Using VFP registers: - // d6: Left value - // d7: Right value + // d0: Left value + // d1: Right value switch (op) { case Token::ADD: - __ vadd(d5, d6, d7); + __ vadd(d5, d0, d1); break; case Token::SUB: - __ vsub(d5, d6, d7); + __ vsub(d5, d0, d1); break; case Token::MUL: - __ vmul(d5, d6, d7); + __ vmul(d5, d0, d1); break; case Token::DIV: - __ vdiv(d5, d6, d7); + __ vdiv(d5, d0, d1); break; default: UNREACHABLE(); @@ -2284,10 +1959,7 @@ void BinaryOpStub_GenerateFPOperation(MacroAssembler* masm, __ Ret(); } else { // Call the C function to handle the double operation. - FloatingPointHelper::CallCCodeForDoubleOperation(masm, - op, - result, - scratch1); + CallCCodeForDoubleOperation(masm, op, result, scratch1); if (FLAG_debug_code) { __ stop("Unreachable code."); } @@ -2305,26 +1977,12 @@ void BinaryOpStub_GenerateFPOperation(MacroAssembler* masm, __ SmiUntag(r2, right); } else { // Convert operands to 32-bit integers. Right in r2 and left in r3. - FloatingPointHelper::ConvertNumberToInt32(masm, - left, - r3, - heap_number_map, - scratch1, - scratch2, - scratch3, - d0, - d1, - not_numbers); - FloatingPointHelper::ConvertNumberToInt32(masm, - right, - r2, - heap_number_map, - scratch1, - scratch2, - scratch3, - d0, - d1, - not_numbers); + __ ConvertNumberToInt32( + left, r3, heap_number_map, + scratch1, scratch2, scratch3, d0, d1, not_numbers); + __ ConvertNumberToInt32( + right, r2, heap_number_map, + scratch1, scratch2, scratch3, d0, d1, not_numbers); } Label result_not_a_smi; @@ -2543,49 +2201,25 @@ void BinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) { // Load both operands and check that they are 32-bit integer. // Jump to type transition if they are not. The registers r0 and r1 (right // and left) are preserved for the runtime call. - FloatingPointHelper::Destination destination = (op_ != Token::MOD) - ? FloatingPointHelper::kVFPRegisters - : FloatingPointHelper::kCoreRegisters; - - FloatingPointHelper::LoadNumberAsInt32Double(masm, - right, - destination, - d7, - d8, - r2, - r3, - heap_number_map, - scratch1, - scratch2, - s0, - &transition); - FloatingPointHelper::LoadNumberAsInt32Double(masm, - left, - destination, - d6, - d8, - r4, - r5, - heap_number_map, - scratch1, - scratch2, - s0, - &transition); - - if (destination == FloatingPointHelper::kVFPRegisters) { + __ LoadNumberAsInt32Double( + right, d1, heap_number_map, scratch1, d8, &transition); + __ LoadNumberAsInt32Double( + left, d0, heap_number_map, scratch1, d8, &transition); + + if (op_ != Token::MOD) { Label return_heap_number; switch (op_) { case Token::ADD: - __ vadd(d5, d6, d7); + __ vadd(d5, d0, d1); break; case Token::SUB: - __ vsub(d5, d6, d7); + __ vsub(d5, d0, d1); break; case Token::MUL: - __ vmul(d5, d6, d7); + __ vmul(d5, d0, d1); break; case Token::DIV: - __ vdiv(d5, d6, d7); + __ vdiv(d5, d0, d1); break; default: UNREACHABLE(); @@ -2670,8 +2304,7 @@ void BinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) { __ Pop(r1, r0); // Call the C function to handle the double operation. - FloatingPointHelper::CallCCodeForDoubleOperation( - masm, op_, heap_number_result, scratch1); + CallCCodeForDoubleOperation(masm, op_, heap_number_result, scratch1); if (FLAG_debug_code) { __ stop("Unreachable code."); } @@ -2691,30 +2324,13 @@ void BinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) { case Token::SHR: case Token::SHL: { Label return_heap_number; - Register scratch3 = r5; // Convert operands to 32-bit integers. Right in r2 and left in r3. The // registers r0 and r1 (right and left) are preserved for the runtime // call. - FloatingPointHelper::LoadNumberAsInt32(masm, - left, - r3, - heap_number_map, - scratch1, - scratch2, - scratch3, - d0, - d1, - &transition); - FloatingPointHelper::LoadNumberAsInt32(masm, - right, - r2, - heap_number_map, - scratch1, - scratch2, - scratch3, - d0, - d1, - &transition); + __ LoadNumberAsInt32(left, r3, heap_number_map, + scratch1, d0, d1, &transition); + __ LoadNumberAsInt32(right, r2, heap_number_map, + scratch1, d0, d1, &transition); // The ECMA-262 standard specifies that, for shift operations, only the // 5 least significant bits of the shift value should be used. @@ -7457,10 +7073,7 @@ void StoreArrayLiteralElementStub::Generate(MacroAssembler* masm) { // Array literal has ElementsKind of FAST_DOUBLE_ELEMENTS. __ bind(&double_elements); __ ldr(r5, FieldMemOperand(r1, JSObject::kElementsOffset)); - __ StoreNumberToDoubleElements(r0, r3, - // Overwrites all regs after this. - r5, r9, r6, r7, r2, - &slow_elements); + __ StoreNumberToDoubleElements(r0, r3, r5, r6, &slow_elements); __ Ret(); } diff --git a/src/arm/code-stubs-arm.h b/src/arm/code-stubs-arm.h index 794fb93..39a9fc8 100644 --- a/src/arm/code-stubs-arm.h +++ b/src/arm/code-stubs-arm.h @@ -588,142 +588,6 @@ class DirectCEntryStub: public PlatformCodeStub { }; -class FloatingPointHelper : public AllStatic { - public: - enum Destination { - kVFPRegisters, - kCoreRegisters - }; - - - // Loads smis from r0 and r1 (right and left in binary operations) into - // floating point registers. Depending on the destination the values ends up - // either d7 and d6 or in r2/r3 and r0/r1 respectively. If the destination is - // floating point registers VFP3 must be supported. If core registers are - // requested when VFP3 is supported d6 and d7 will be scratched. - static void LoadSmis(MacroAssembler* masm, - Destination destination, - Register scratch1, - Register scratch2); - - // Convert the smi or heap number in object to an int32 using the rules - // for ToInt32 as described in ECMAScript 9.5.: the value is truncated - // and brought into the range -2^31 .. +2^31 - 1. - static void ConvertNumberToInt32(MacroAssembler* masm, - Register object, - Register dst, - Register heap_number_map, - Register scratch1, - Register scratch2, - Register scratch3, - DwVfpRegister double_scratch1, - DwVfpRegister double_scratch2, - Label* not_int32); - - // Converts the integer (untagged smi) in |int_scratch| to a double, storing - // the result either in |double_dst| or |dst2:dst1|, depending on - // |destination|. - // Warning: The value in |int_scratch| will be changed in the process! - static void ConvertIntToDouble(MacroAssembler* masm, - Register int_scratch, - Destination destination, - DwVfpRegister double_dst, - Register dst1, - Register dst2, - Register scratch2, - SwVfpRegister single_scratch); - - // Load the number from object into double_dst in the double format. - // Control will jump to not_int32 if the value cannot be exactly represented - // by a 32-bit integer. - // Floating point value in the 32-bit integer range that are not exact integer - // won't be loaded. - static void LoadNumberAsInt32Double(MacroAssembler* masm, - Register object, - Destination destination, - DwVfpRegister double_dst, - DwVfpRegister double_scratch, - Register dst1, - Register dst2, - Register heap_number_map, - Register scratch1, - Register scratch2, - SwVfpRegister single_scratch, - Label* not_int32); - - // Loads the number from object into dst as a 32-bit integer. - // Control will jump to not_int32 if the object cannot be exactly represented - // by a 32-bit integer. - // Floating point value in the 32-bit integer range that are not exact integer - // won't be converted. - // scratch3 is not used when VFP3 is supported. - static void LoadNumberAsInt32(MacroAssembler* masm, - Register object, - Register dst, - Register heap_number_map, - Register scratch1, - Register scratch2, - Register scratch3, - DwVfpRegister double_scratch0, - DwVfpRegister double_scratch1, - Label* not_int32); - - // Generate non VFP3 code to check if a double can be exactly represented by a - // 32-bit integer. This does not check for 0 or -0, which need - // to be checked for separately. - // Control jumps to not_int32 if the value is not a 32-bit integer, and falls - // through otherwise. - // src1 and src2 will be cloberred. - // - // Expected input: - // - src1: higher (exponent) part of the double value. - // - src2: lower (mantissa) part of the double value. - // Output status: - // - dst: 32 higher bits of the mantissa. (mantissa[51:20]) - // - src2: contains 1. - // - other registers are clobbered. - static void DoubleIs32BitInteger(MacroAssembler* masm, - Register src1, - Register src2, - Register dst, - Register scratch, - Label* not_int32); - - // Generates code to call a C function to do a double operation using core - // registers. (Used when VFP3 is not supported.) - // This code never falls through, but returns with a heap number containing - // the result in r0. - // Register heapnumber_result must be a heap number in which the - // result of the operation will be stored. - // Requires the following layout on entry: - // r0: Left value (least significant part of mantissa). - // r1: Left value (sign, exponent, top of mantissa). - // r2: Right value (least significant part of mantissa). - // r3: Right value (sign, exponent, top of mantissa). - static void CallCCodeForDoubleOperation(MacroAssembler* masm, - Token::Value op, - Register heap_number_result, - Register scratch); - - // Loads the objects from |object| into floating point registers. - // Depending on |destination| the value ends up either in |dst| or - // in |dst1|/|dst2|. If |destination| is kVFPRegisters, then VFP3 - // must be supported. If kCoreRegisters are requested and VFP3 is - // supported, |dst| will be scratched. If |object| is neither smi nor - // heap number, |not_number| is jumped to with |object| still intact. - static void LoadNumber(MacroAssembler* masm, - FloatingPointHelper::Destination destination, - Register object, - DwVfpRegister dst, - Register dst1, - Register dst2, - Register heap_number_map, - Register scratch1, - Register scratch2, - Label* not_number); -}; - - class NameDictionaryLookupStub: public PlatformCodeStub { public: enum LookupMode { POSITIVE_LOOKUP, NEGATIVE_LOOKUP }; diff --git a/src/arm/ic-arm.cc b/src/arm/ic-arm.cc index 84a11b6..893ac4e 100644 --- a/src/arm/ic-arm.cc +++ b/src/arm/ic-arm.cc @@ -1340,13 +1340,7 @@ static void KeyedStoreGenerateGenericHelper( __ b(ne, slow); } __ bind(&fast_double_without_map_check); - __ StoreNumberToDoubleElements(value, - key, - elements, // Overwritten. - r3, // Scratch regs... - r4, - r5, - r6, + __ StoreNumberToDoubleElements(value, key, elements, r3, &transition_double_elements); if (increment_length == kIncrementLength) { // Add 1 to receiver->length. diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc index 24231c5..940a156 100644 --- a/src/arm/lithium-codegen-arm.cc +++ b/src/arm/lithium-codegen-arm.cc @@ -5040,8 +5040,8 @@ void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) { __ sub(scratch1, input_reg, Operand(kHeapObjectTag)); __ vldr(double_scratch2, scratch1, HeapNumber::kValueOffset); - __ ECMAToInt32(input_reg, double_scratch2, double_scratch, - scratch1, scratch2, scratch3); + __ ECMAToInt32(input_reg, double_scratch2, + scratch1, scratch2, scratch3, double_scratch); } else { // Deoptimize if we don't have a heap number. @@ -5138,8 +5138,8 @@ void LCodeGen::DoDoubleToI(LDoubleToI* instr) { if (instr->truncating()) { Register scratch3 = ToRegister(instr->temp2()); - __ ECMAToInt32(result_reg, double_input, double_scratch, - scratch1, scratch2, scratch3); + __ ECMAToInt32(result_reg, double_input, + scratch1, scratch2, scratch3, double_scratch); } else { __ TryDoubleToInt32Exact(result_reg, double_input, double_scratch); // Deoptimize if the input wasn't a int32 (inside a double). diff --git a/src/arm/macro-assembler-arm.cc b/src/arm/macro-assembler-arm.cc index 3f8d922..dca9709 100644 --- a/src/arm/macro-assembler-arm.cc +++ b/src/arm/macro-assembler-arm.cc @@ -790,6 +790,116 @@ void MacroAssembler::Vmov(const DwVfpRegister dst, } +void MacroAssembler::ConvertNumberToInt32(Register object, + Register dst, + Register heap_number_map, + Register scratch1, + Register scratch2, + Register scratch3, + DwVfpRegister double_scratch1, + DwVfpRegister double_scratch2, + Label* not_number) { + Label done; + UntagAndJumpIfSmi(dst, object, &done); + JumpIfNotHeapNumber(object, heap_number_map, scratch1, not_number); + vldr(double_scratch1, FieldMemOperand(object, HeapNumber::kValueOffset)); + ECMAToInt32(dst, double_scratch1, + scratch1, scratch2, scratch3, double_scratch2); + + bind(&done); +} + + +void MacroAssembler::LoadNumber(Register object, + DwVfpRegister dst, + Register heap_number_map, + Register scratch, + Label* not_number) { + Label is_smi, done; + + UntagAndJumpIfSmi(scratch, object, &is_smi); + JumpIfNotHeapNumber(object, heap_number_map, scratch, not_number); + + vldr(dst, FieldMemOperand(object, HeapNumber::kValueOffset)); + b(&done); + + // Handle loading a double from a smi. + bind(&is_smi); + vmov(dst.high(), scratch); + vcvt_f64_s32(dst, dst.high()); + + bind(&done); +} + + +void MacroAssembler::LoadNumberAsInt32Double(Register object, + DwVfpRegister double_dst, + Register heap_number_map, + Register scratch, + DwVfpRegister double_scratch, + Label* not_int32) { + ASSERT(!scratch.is(object)); + ASSERT(!heap_number_map.is(object) && !heap_number_map.is(scratch)); + + Label done, obj_is_not_smi; + + UntagAndJumpIfNotSmi(scratch, object, &obj_is_not_smi); + vmov(double_scratch.low(), scratch); + vcvt_f64_s32(double_dst, double_scratch.low()); + b(&done); + + bind(&obj_is_not_smi); + JumpIfNotHeapNumber(object, heap_number_map, scratch, not_int32); + + // Load the number. + // Load the double value. + vldr(double_dst, FieldMemOperand(object, HeapNumber::kValueOffset)); + + TestDoubleIsInt32(double_dst, double_scratch); + // Jump to not_int32 if the operation did not succeed. + b(ne, not_int32); + + bind(&done); +} + + +void MacroAssembler::LoadNumberAsInt32(Register object, + Register dst, + Register heap_number_map, + Register scratch, + DwVfpRegister double_scratch0, + DwVfpRegister double_scratch1, + Label* not_int32) { + ASSERT(!dst.is(object)); + ASSERT(!scratch.is(object)); + + Label done, maybe_undefined; + + UntagAndJumpIfSmi(dst, object, &done); + + JumpIfNotHeapNumber(object, heap_number_map, scratch, &maybe_undefined); + + // Object is a heap number. + // Convert the floating point value to a 32-bit integer. + // Load the double value. + vldr(double_scratch0, FieldMemOperand(object, HeapNumber::kValueOffset)); + + TryDoubleToInt32Exact(dst, double_scratch0, double_scratch1); + // Jump to not_int32 if the operation did not succeed. + b(ne, not_int32); + b(&done); + + bind(&maybe_undefined); + CompareRoot(object, Heap::kUndefinedValueRootIndex); + b(ne, not_int32); + // |undefined| is truncated to 0. + mov(dst, Operand(Smi::FromInt(0))); + // Fall through. + + bind(&done); +} + + void MacroAssembler::EnterFrame(StackFrame::Type type) { // r0-r3: preserved stm(db_w, sp, cp.bit() | fp.bit() | lr.bit()); @@ -1930,14 +2040,9 @@ void MacroAssembler::StoreNumberToDoubleElements(Register value_reg, Register key_reg, Register elements_reg, Register scratch1, - Register scratch2, - Register scratch3, - Register scratch4, Label* fail, int elements_offset) { Label smi_value, store; - Register mantissa_reg = scratch2; - Register exponent_reg = scratch3; // Handle smi values specially. JumpIfSmi(value_reg, &smi_value); @@ -1962,9 +2067,8 @@ void MacroAssembler::StoreNumberToDoubleElements(Register value_reg, bind(&smi_value); Register untagged_value = scratch1; SmiUntag(untagged_value, value_reg); - FloatingPointHelper::ConvertIntToDouble( - this, untagged_value, FloatingPointHelper::kVFPRegisters, d0, - mantissa_reg, exponent_reg, scratch4, s2); + vmov(s2, untagged_value); + vcvt_f64_s32(d0, s2); bind(&store); add(scratch1, elements_reg, @@ -2386,34 +2490,21 @@ void MacroAssembler::TryInt32Floor(Register result, } -void MacroAssembler::ECMAConvertNumberToInt32(Register source, - Register result, - Register input_low, - Register input_high, - Register scratch, - DwVfpRegister double_scratch1, - DwVfpRegister double_scratch2) { - vldr(double_scratch1, FieldMemOperand(source, HeapNumber::kValueOffset)); - ECMAToInt32(result, double_scratch1, double_scratch2, - scratch, input_high, input_low); -} - - void MacroAssembler::ECMAToInt32(Register result, DwVfpRegister double_input, - DwVfpRegister double_scratch, Register scratch, - Register input_high, - Register input_low) { - ASSERT(!input_high.is(result)); - ASSERT(!input_low.is(result)); - ASSERT(!input_low.is(input_high)); + Register scratch_high, + Register scratch_low, + DwVfpRegister double_scratch) { + ASSERT(!scratch_high.is(result)); + ASSERT(!scratch_low.is(result)); + ASSERT(!scratch_low.is(scratch_high)); ASSERT(!scratch.is(result) && - !scratch.is(input_high) && - !scratch.is(input_low)); + !scratch.is(scratch_high) && + !scratch.is(scratch_low)); ASSERT(!double_input.is(double_scratch)); - Label out_of_range, negate, done; + Label out_of_range, only_low, negate, done; vcvt_s32_f64(double_scratch.low(), double_input); vmov(result, double_scratch.low()); @@ -2423,8 +2514,8 @@ void MacroAssembler::ECMAToInt32(Register result, cmp(scratch, Operand(0x7ffffffe)); b(lt, &done); - vmov(input_low, input_high, double_input); - Ubfx(scratch, input_high, + vmov(scratch_low, scratch_high, double_input); + Ubfx(scratch, scratch_high, HeapNumber::kExponentShift, HeapNumber::kExponentBits); // Load scratch with exponent - 1. This is faster than loading // with exponent because Bias + 1 = 1024 which is an *ARM* immediate value. @@ -2439,59 +2530,45 @@ void MacroAssembler::ECMAToInt32(Register result, // If we reach this code, 31 <= exponent <= 83. // So, we don't have to handle cases where 0 <= exponent <= 20 for // which we would need to shift right the high part of the mantissa. - ECMAToInt32Tail(result, scratch, input_high, input_low, - &out_of_range, &negate, &done); -} - - -void MacroAssembler::ECMAToInt32Tail(Register result, - Register scratch, - Register input_high, - Register input_low, - Label* out_of_range, - Label* negate, - Label* done) { - Label only_low; - - // On entry, scratch contains exponent - 1. + // Scratch contains exponent - 1. // Load scratch with 52 - exponent (load with 51 - (exponent - 1)). rsb(scratch, scratch, Operand(51), SetCC); b(ls, &only_low); - // 21 <= exponent <= 51, shift input_low and input_high + // 21 <= exponent <= 51, shift scratch_low and scratch_high // to generate the result. - mov(input_low, Operand(input_low, LSR, scratch)); + mov(scratch_low, Operand(scratch_low, LSR, scratch)); // Scratch contains: 52 - exponent. // We needs: exponent - 20. // So we use: 32 - scratch = 32 - 52 + exponent = exponent - 20. rsb(scratch, scratch, Operand(32)); - Ubfx(result, input_high, + Ubfx(result, scratch_high, 0, HeapNumber::kMantissaBitsInTopWord); - // Set the implicit 1 before the mantissa part in input_high. + // Set the implicit 1 before the mantissa part in scratch_high. orr(result, result, Operand(1 << HeapNumber::kMantissaBitsInTopWord)); - orr(result, input_low, Operand(result, LSL, scratch)); - b(negate); + orr(result, scratch_low, Operand(result, LSL, scratch)); + b(&negate); - bind(out_of_range); + bind(&out_of_range); mov(result, Operand::Zero()); - b(done); + b(&done); bind(&only_low); - // 52 <= exponent <= 83, shift only input_low. + // 52 <= exponent <= 83, shift only scratch_low. // On entry, scratch contains: 52 - exponent. rsb(scratch, scratch, Operand::Zero()); - mov(result, Operand(input_low, LSL, scratch)); + mov(result, Operand(scratch_low, LSL, scratch)); - bind(negate); - // If input was positive, input_high ASR 31 equals 0 and - // input_high LSR 31 equals zero. + bind(&negate); + // If input was positive, scratch_high ASR 31 equals 0 and + // scratch_high LSR 31 equals zero. // New result = (result eor 0) + 0 = result. // If the input was negative, we have to negate the result. - // Input_high ASR 31 equals 0xffffffff and input_high LSR 31 equals 1. + // Input_high ASR 31 equals 0xffffffff and scratch_high LSR 31 equals 1. // New result = (result eor 0xffffffff) + 1 = 0 - result. - eor(result, result, Operand(input_high, ASR, 31)); - add(result, result, Operand(input_high, LSR, 31)); + eor(result, result, Operand(scratch_high, ASR, 31)); + add(result, result, Operand(scratch_high, LSR, 31)); - bind(done); + bind(&done); } @@ -2673,16 +2750,6 @@ void MacroAssembler::Assert(Condition cond, const char* msg) { } -void MacroAssembler::AssertRegisterIsRoot(Register reg, - Heap::RootListIndex index) { - if (emit_debug_code()) { - LoadRoot(ip, index); - cmp(reg, ip); - Check(eq, "Register did not match expected root"); - } -} - - void MacroAssembler::AssertFastElements(Register elements) { if (emit_debug_code()) { ASSERT(!elements.is(ip)); @@ -2976,12 +3043,10 @@ void MacroAssembler::AssertName(Register object) { -void MacroAssembler::AssertRootValue(Register src, - Heap::RootListIndex root_value_index, - const char* message) { +void MacroAssembler::AssertIsRoot(Register reg, Heap::RootListIndex index) { if (emit_debug_code()) { - CompareRoot(src, root_value_index); - Check(eq, message); + CompareRoot(reg, index); + Check(eq, "HeapNumberMap register clobbered."); } } @@ -2991,7 +3056,7 @@ void MacroAssembler::JumpIfNotHeapNumber(Register object, Register scratch, Label* on_not_heap_number) { ldr(scratch, FieldMemOperand(object, HeapObject::kMapOffset)); - AssertRegisterIsRoot(heap_number_map, Heap::kHeapNumberMapRootIndex); + AssertIsRoot(heap_number_map, Heap::kHeapNumberMapRootIndex); cmp(scratch, heap_number_map); b(ne, on_not_heap_number); } @@ -3048,7 +3113,7 @@ void MacroAssembler::AllocateHeapNumber(Register result, tagging_mode == TAG_RESULT ? TAG_OBJECT : NO_ALLOCATION_FLAGS); // Store heap number map in the allocated object. - AssertRegisterIsRoot(heap_number_map, Heap::kHeapNumberMapRootIndex); + AssertIsRoot(heap_number_map, Heap::kHeapNumberMapRootIndex); if (tagging_mode == TAG_RESULT) { str(heap_number_map, FieldMemOperand(result, HeapObject::kMapOffset)); } else { diff --git a/src/arm/macro-assembler-arm.h b/src/arm/macro-assembler-arm.h index 75194a8..2e601bd 100644 --- a/src/arm/macro-assembler-arm.h +++ b/src/arm/macro-assembler-arm.h @@ -495,6 +495,54 @@ class MacroAssembler: public Assembler { const double imm, const Register scratch = no_reg); + // Converts the smi or heap number in object to an int32 using the rules + // for ToInt32 as described in ECMAScript 9.5.: the value is truncated + // and brought into the range -2^31 .. +2^31 - 1. + void ConvertNumberToInt32(Register object, + Register dst, + Register heap_number_map, + Register scratch1, + Register scratch2, + Register scratch3, + DwVfpRegister double_scratch1, + DwVfpRegister double_scratch2, + Label* not_int32); + + // Loads the number from object into dst register. + // If |object| is neither smi nor heap number, |not_number| is jumped to + // with |object| still intact. + void LoadNumber(Register object, + DwVfpRegister dst, + Register heap_number_map, + Register scratch, + Label* not_number); + + // Loads the number from object into double_dst in the double format. + // Control will jump to not_int32 if the value cannot be exactly represented + // by a 32-bit integer. + // Floating point value in the 32-bit integer range that are not exact integer + // won't be loaded. + void LoadNumberAsInt32Double(Register object, + DwVfpRegister double_dst, + Register heap_number_map, + Register scratch, + DwVfpRegister double_scratch, + Label* not_int32); + + // Loads the number from object into dst as a 32-bit integer. + // Control will jump to not_int32 if the object cannot be exactly represented + // by a 32-bit integer. + // Floating point value in the 32-bit integer range that are not exact integer + // won't be converted. + void LoadNumberAsInt32(Register object, + Register dst, + Register heap_number_map, + Register scratch, + DwVfpRegister double_scratch0, + DwVfpRegister double_scratch1, + Label* not_int32); + + // Enter exit frame. // stack_space - extra stack space, used for alignment before call to C. void EnterExitFrame(bool save_doubles, int stack_space = 0); @@ -831,16 +879,11 @@ class MacroAssembler: public Assembler { // Check to see if maybe_number can be stored as a double in // FastDoubleElements. If it can, store it at the index specified by key in - // the FastDoubleElements array elements. Otherwise jump to fail, in which - // case scratch2, scratch3 and scratch4 are unmodified. + // the FastDoubleElements array elements. Otherwise jump to fail. void StoreNumberToDoubleElements(Register value_reg, Register key_reg, - // All regs below here overwritten. Register elements_reg, Register scratch1, - Register scratch2, - Register scratch3, - Register scratch4, Label* fail, int elements_offset = 0); @@ -972,26 +1015,16 @@ class MacroAssembler: public Assembler { Label* done, Label* exact); - // Performs a truncating conversion of a heap floating point number as used by - // the JS bitwise operations. See ECMA-262 9.5: ToInt32. - // Exits with 'result' holding the answer. - void ECMAConvertNumberToInt32(Register source, - Register result, - Register input_low, - Register input_high, - Register scratch, - DwVfpRegister double_scratch1, - DwVfpRegister double_scratch2); - // Performs a truncating conversion of a floating point number as used by // the JS bitwise operations. See ECMA-262 9.5: ToInt32. + // Double_scratch must be between d0 and d15. // Exits with 'result' holding the answer and all other registers clobbered. void ECMAToInt32(Register result, DwVfpRegister double_input, - DwVfpRegister double_scratch, Register scratch, - Register input_high, - Register input_low); + Register scratch_high, + Register scratch_low, + DwVfpRegister double_scratch); // Check whether d16-d31 are available on the CPU. The result is given by the // Z condition flag: Z==0 if d16-d31 available, Z==1 otherwise. @@ -1127,7 +1160,6 @@ class MacroAssembler: public Assembler { // Calls Abort(msg) if the condition cond is not satisfied. // Use --debug_code to enable. void Assert(Condition cond, const char* msg); - void AssertRegisterIsRoot(Register reg, Heap::RootListIndex index); void AssertFastElements(Register elements); // Like Assert(), but always enabled. @@ -1237,11 +1269,9 @@ class MacroAssembler: public Assembler { // Abort execution if argument is not a name, enabled via --debug-code. void AssertName(Register object); - // Abort execution if argument is not the root value with the given index, + // Abort execution if reg is not the root value with the given index, // enabled via --debug-code. - void AssertRootValue(Register src, - Heap::RootListIndex root_value_index, - const char* message); + void AssertIsRoot(Register reg, Heap::RootListIndex index); // --------------------------------------------------------------------------- // HeapNumber utilities @@ -1372,16 +1402,6 @@ class MacroAssembler: public Assembler { // it. See the implementation for register usage. void JumpToHandlerEntry(); - // Helper for ECMAToInt32VFP and ECMAToInt32NoVFP. - // It is expected that 31 <= exponent <= 83, and scratch is exponent - 1. - void ECMAToInt32Tail(Register result, - Register scratch, - Register input_high, - Register input_low, - Label* out_of_range, - Label* negate, - Label* done); - // Compute memory operands for safepoint stack slots. static int SafepointRegisterStackIndex(int reg_code); MemOperand SafepointRegisterSlot(Register reg); diff --git a/src/arm/stub-cache-arm.cc b/src/arm/stub-cache-arm.cc index f22acb4..b093faa 100644 --- a/src/arm/stub-cache-arm.cc +++ b/src/arm/stub-cache-arm.cc @@ -1620,9 +1620,8 @@ Handle CallStubCompiler::CompileArrayPushCall( __ b(gt, &call_builtin); __ ldr(r4, MemOperand(sp, (argc - 1) * kPointerSize)); - __ StoreNumberToDoubleElements( - r4, r0, elements, r5, r2, r3, r9, - &call_builtin, argc * kDoubleSize); + __ StoreNumberToDoubleElements(r4, r0, elements, r5, + &call_builtin, argc * kDoubleSize); // Save new length. __ str(r0, FieldMemOperand(receiver, JSArray::kLengthOffset)); @@ -3246,14 +3245,10 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray( StoreIntAsFloat(masm, r3, r4, r5, r7); break; case EXTERNAL_DOUBLE_ELEMENTS: + __ vmov(s2, r5); + __ vcvt_f64_s32(d0, s2); __ add(r3, r3, Operand(key, LSL, 2)); // r3: effective address of the double element - FloatingPointHelper::Destination destination; - destination = FloatingPointHelper::kVFPRegisters; - FloatingPointHelper::ConvertIntToDouble( - masm, r5, destination, - d0, r6, r7, // These are: double_dst, dst_mantissa, dst_exponent. - r4, s2); // These are: scratch2, single_scratch. __ vstr(d0, r3, 0); break; case FAST_ELEMENTS: @@ -3303,7 +3298,7 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray( // not include -kHeapObjectTag into it. __ sub(r5, value, Operand(kHeapObjectTag)); __ vldr(d0, r5, HeapNumber::kValueOffset); - __ ECMAToInt32(r5, d0, d1, r6, r7, r9); + __ ECMAToInt32(r5, d0, r6, r7, r9, d1); switch (elements_kind) { case EXTERNAL_BYTE_ELEMENTS: @@ -3537,9 +3532,6 @@ void KeyedStoreStubCompiler::GenerateStoreFastDoubleElement( // -- r3 : scratch (elements backing store) // -- r4 : scratch // -- r5 : scratch - // -- r6 : scratch - // -- r7 : scratch - // -- r9 : scratch // ----------------------------------- Label miss_force_generic, transition_elements_kind, grow, slow; Label finish_store, check_capacity; @@ -3550,9 +3542,6 @@ void KeyedStoreStubCompiler::GenerateStoreFastDoubleElement( Register elements_reg = r3; Register scratch1 = r4; Register scratch2 = r5; - Register scratch3 = r6; - Register scratch4 = r7; - Register scratch5 = r9; Register length_reg = r7; // This stub is meant to be tail-jumped to, the receiver must already @@ -3581,15 +3570,8 @@ void KeyedStoreStubCompiler::GenerateStoreFastDoubleElement( } __ bind(&finish_store); - __ StoreNumberToDoubleElements(value_reg, - key_reg, - // All registers after this are overwritten. - elements_reg, - scratch1, - scratch3, - scratch4, - scratch2, - &transition_elements_kind); + __ StoreNumberToDoubleElements(value_reg, key_reg, elements_reg, + scratch1, &transition_elements_kind); __ Ret(); // Handle store cache miss, replacing the ic with the generic stub. @@ -3636,15 +3618,8 @@ void KeyedStoreStubCompiler::GenerateStoreFastDoubleElement( FieldMemOperand(elements_reg, FixedDoubleArray::kLengthOffset)); __ mov(scratch1, elements_reg); - __ StoreNumberToDoubleElements(value_reg, - key_reg, - // All registers after this are overwritten. - scratch1, - scratch2, - scratch3, - scratch4, - scratch5, - &transition_elements_kind); + __ StoreNumberToDoubleElements(value_reg, key_reg, scratch1, + scratch2, &transition_elements_kind); __ mov(scratch1, Operand(kHoleNanLower32)); __ mov(scratch2, Operand(kHoleNanUpper32)); -- 2.7.4