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
parent 0c634a1d
......@@ -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();
}
......
......@@ -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 };
......
......@@ -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.
......
......@@ -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).
......
......@@ -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 {
......
......@@ -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);
......
......@@ -1620,9 +1620,8 @@ Handle<Code> 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));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment