Porting r9456 to arm (Optimize KeyedStoreGeneric for Smi arrays).
Review URL: http://codereview.chromium.org/8065004 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@9531 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
42b9eaa91c
commit
b1e83c54c5
@ -1272,13 +1272,17 @@ void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm,
|
|||||||
// -- r2 : receiver
|
// -- r2 : receiver
|
||||||
// -- lr : return address
|
// -- lr : return address
|
||||||
// -----------------------------------
|
// -----------------------------------
|
||||||
Label slow, fast, array, extra;
|
Label slow, array, extra, check_if_double_array;
|
||||||
|
Label fast_object_with_map_check, fast_object_without_map_check;
|
||||||
|
Label fast_double_with_map_check, fast_double_without_map_check;
|
||||||
|
|
||||||
// Register usage.
|
// Register usage.
|
||||||
Register value = r0;
|
Register value = r0;
|
||||||
Register key = r1;
|
Register key = r1;
|
||||||
Register receiver = r2;
|
Register receiver = r2;
|
||||||
Register elements = r3; // Elements array of the receiver.
|
Register elements = r3; // Elements array of the receiver.
|
||||||
|
Register elements_map = r6;
|
||||||
|
Register receiver_map = r7;
|
||||||
// r4 and r5 are used as general scratch registers.
|
// r4 and r5 are used as general scratch registers.
|
||||||
|
|
||||||
// Check that the key is a smi.
|
// Check that the key is a smi.
|
||||||
@ -1286,14 +1290,14 @@ void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm,
|
|||||||
// Check that the object isn't a smi.
|
// Check that the object isn't a smi.
|
||||||
__ JumpIfSmi(receiver, &slow);
|
__ JumpIfSmi(receiver, &slow);
|
||||||
// Get the map of the object.
|
// Get the map of the object.
|
||||||
__ ldr(r4, FieldMemOperand(receiver, HeapObject::kMapOffset));
|
__ ldr(receiver_map, FieldMemOperand(receiver, HeapObject::kMapOffset));
|
||||||
// Check that the receiver does not require access checks. We need
|
// Check that the receiver does not require access checks. We need
|
||||||
// to do this because this generic stub does not perform map checks.
|
// to do this because this generic stub does not perform map checks.
|
||||||
__ ldrb(ip, FieldMemOperand(r4, Map::kBitFieldOffset));
|
__ ldrb(ip, FieldMemOperand(receiver_map, Map::kBitFieldOffset));
|
||||||
__ tst(ip, Operand(1 << Map::kIsAccessCheckNeeded));
|
__ tst(ip, Operand(1 << Map::kIsAccessCheckNeeded));
|
||||||
__ b(ne, &slow);
|
__ b(ne, &slow);
|
||||||
// Check if the object is a JS array or not.
|
// Check if the object is a JS array or not.
|
||||||
__ ldrb(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset));
|
__ ldrb(r4, FieldMemOperand(receiver_map, Map::kInstanceTypeOffset));
|
||||||
__ cmp(r4, Operand(JS_ARRAY_TYPE));
|
__ cmp(r4, Operand(JS_ARRAY_TYPE));
|
||||||
__ b(eq, &array);
|
__ b(eq, &array);
|
||||||
// Check that the object is some kind of JSObject.
|
// Check that the object is some kind of JSObject.
|
||||||
@ -1302,15 +1306,10 @@ void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm,
|
|||||||
|
|
||||||
// Object case: Check key against length in the elements array.
|
// Object case: Check key against length in the elements array.
|
||||||
__ ldr(elements, FieldMemOperand(receiver, JSObject::kElementsOffset));
|
__ ldr(elements, FieldMemOperand(receiver, JSObject::kElementsOffset));
|
||||||
// Check that the object is in fast mode and writable.
|
|
||||||
__ ldr(r4, FieldMemOperand(elements, HeapObject::kMapOffset));
|
|
||||||
__ LoadRoot(ip, Heap::kFixedArrayMapRootIndex);
|
|
||||||
__ cmp(r4, ip);
|
|
||||||
__ b(ne, &slow);
|
|
||||||
// Check array bounds. Both the key and the length of FixedArray are smis.
|
// Check array bounds. Both the key and the length of FixedArray are smis.
|
||||||
__ ldr(ip, FieldMemOperand(elements, FixedArray::kLengthOffset));
|
__ ldr(ip, FieldMemOperand(elements, FixedArray::kLengthOffset));
|
||||||
__ cmp(key, Operand(ip));
|
__ cmp(key, Operand(ip));
|
||||||
__ b(lo, &fast);
|
__ b(lo, &fast_object_with_map_check);
|
||||||
|
|
||||||
// Slow case, handle jump to runtime.
|
// Slow case, handle jump to runtime.
|
||||||
__ bind(&slow);
|
__ bind(&slow);
|
||||||
@ -1331,21 +1330,31 @@ void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm,
|
|||||||
__ ldr(ip, FieldMemOperand(elements, FixedArray::kLengthOffset));
|
__ ldr(ip, FieldMemOperand(elements, FixedArray::kLengthOffset));
|
||||||
__ cmp(key, Operand(ip));
|
__ cmp(key, Operand(ip));
|
||||||
__ b(hs, &slow);
|
__ b(hs, &slow);
|
||||||
|
__ ldr(elements_map, FieldMemOperand(elements, HeapObject::kMapOffset));
|
||||||
|
__ cmp(elements_map,
|
||||||
|
Operand(masm->isolate()->factory()->fixed_array_map()));
|
||||||
|
__ b(ne, &check_if_double_array);
|
||||||
// Calculate key + 1 as smi.
|
// Calculate key + 1 as smi.
|
||||||
STATIC_ASSERT(kSmiTag == 0);
|
STATIC_ASSERT(kSmiTag == 0);
|
||||||
__ add(r4, key, Operand(Smi::FromInt(1)));
|
__ add(r4, key, Operand(Smi::FromInt(1)));
|
||||||
__ str(r4, FieldMemOperand(receiver, JSArray::kLengthOffset));
|
__ str(r4, FieldMemOperand(receiver, JSArray::kLengthOffset));
|
||||||
__ b(&fast);
|
__ b(&fast_object_without_map_check);
|
||||||
|
|
||||||
|
__ bind(&check_if_double_array);
|
||||||
|
__ cmp(elements_map,
|
||||||
|
Operand(masm->isolate()->factory()->fixed_double_array_map()));
|
||||||
|
__ b(ne, &slow);
|
||||||
|
// Add 1 to key, and go to common element store code for doubles.
|
||||||
|
STATIC_ASSERT(kSmiTag == 0);
|
||||||
|
__ add(r4, key, Operand(Smi::FromInt(1)));
|
||||||
|
__ str(r4, FieldMemOperand(receiver, JSArray::kLengthOffset));
|
||||||
|
__ jmp(&fast_double_without_map_check);
|
||||||
|
|
||||||
// Array case: Get the length and the elements array from the JS
|
// Array case: Get the length and the elements array from the JS
|
||||||
// array. Check that the array is in fast mode (and writable); if it
|
// array. Check that the array is in fast mode (and writable); if it
|
||||||
// is the length is always a smi.
|
// is the length is always a smi.
|
||||||
__ bind(&array);
|
__ bind(&array);
|
||||||
__ ldr(elements, FieldMemOperand(receiver, JSObject::kElementsOffset));
|
__ ldr(elements, FieldMemOperand(receiver, JSObject::kElementsOffset));
|
||||||
__ ldr(r4, FieldMemOperand(elements, HeapObject::kMapOffset));
|
|
||||||
__ LoadRoot(ip, Heap::kFixedArrayMapRootIndex);
|
|
||||||
__ cmp(r4, ip);
|
|
||||||
__ b(ne, &slow);
|
|
||||||
|
|
||||||
// Check the key against the length in the array.
|
// Check the key against the length in the array.
|
||||||
__ ldr(ip, FieldMemOperand(receiver, JSArray::kLengthOffset));
|
__ ldr(ip, FieldMemOperand(receiver, JSArray::kLengthOffset));
|
||||||
@ -1353,10 +1362,15 @@ void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm,
|
|||||||
__ b(hs, &extra);
|
__ b(hs, &extra);
|
||||||
// Fall through to fast case.
|
// Fall through to fast case.
|
||||||
|
|
||||||
__ bind(&fast);
|
__ bind(&fast_object_with_map_check);
|
||||||
Register scratch_value = r4;
|
Register scratch_value = r4;
|
||||||
Register address = r5;
|
Register address = r5;
|
||||||
|
__ ldr(elements_map, FieldMemOperand(elements, HeapObject::kMapOffset));
|
||||||
|
__ cmp(elements_map,
|
||||||
|
Operand(masm->isolate()->factory()->fixed_array_map()));
|
||||||
|
__ b(ne, &fast_double_with_map_check);
|
||||||
|
__ bind(&fast_object_without_map_check);
|
||||||
|
// Smi stores don't require further checks.
|
||||||
Label non_smi_value;
|
Label non_smi_value;
|
||||||
__ JumpIfNotSmi(value, &non_smi_value);
|
__ JumpIfNotSmi(value, &non_smi_value);
|
||||||
// It's irrelevant whether array is smi-only or not when writing a smi.
|
// It's irrelevant whether array is smi-only or not when writing a smi.
|
||||||
@ -1368,8 +1382,7 @@ void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm,
|
|||||||
__ bind(&non_smi_value);
|
__ bind(&non_smi_value);
|
||||||
if (FLAG_smi_only_arrays) {
|
if (FLAG_smi_only_arrays) {
|
||||||
// Escape to slow case when writing non-smi into smi-only array.
|
// Escape to slow case when writing non-smi into smi-only array.
|
||||||
__ ldr(scratch_value, FieldMemOperand(receiver, HeapObject::kMapOffset));
|
__ CheckFastObjectElements(receiver_map, scratch_value, &slow);
|
||||||
__ CheckFastObjectElements(scratch_value, scratch_value, &slow);
|
|
||||||
}
|
}
|
||||||
// Fast elements array, store the value to the elements backing store.
|
// Fast elements array, store the value to the elements backing store.
|
||||||
__ add(address, elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
|
__ add(address, elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
|
||||||
@ -1385,6 +1398,24 @@ void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm,
|
|||||||
EMIT_REMEMBERED_SET,
|
EMIT_REMEMBERED_SET,
|
||||||
OMIT_SMI_CHECK);
|
OMIT_SMI_CHECK);
|
||||||
__ Ret();
|
__ Ret();
|
||||||
|
|
||||||
|
__ bind(&fast_double_with_map_check);
|
||||||
|
// Check for fast double array case. If this fails, call through to the
|
||||||
|
// runtime.
|
||||||
|
__ cmp(elements_map,
|
||||||
|
Operand(masm->isolate()->factory()->fixed_double_array_map()));
|
||||||
|
__ b(ne, &slow);
|
||||||
|
__ bind(&fast_double_without_map_check);
|
||||||
|
__ StoreNumberToDoubleElements(value,
|
||||||
|
key,
|
||||||
|
receiver,
|
||||||
|
elements,
|
||||||
|
r4,
|
||||||
|
r5,
|
||||||
|
r6,
|
||||||
|
r7,
|
||||||
|
&slow);
|
||||||
|
__ Ret();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1890,6 +1890,96 @@ void MacroAssembler::CheckFastSmiOnlyElements(Register map,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MacroAssembler::StoreNumberToDoubleElements(Register value_reg,
|
||||||
|
Register key_reg,
|
||||||
|
Register receiver_reg,
|
||||||
|
Register elements_reg,
|
||||||
|
Register scratch1,
|
||||||
|
Register scratch2,
|
||||||
|
Register scratch3,
|
||||||
|
Register scratch4,
|
||||||
|
Label* fail) {
|
||||||
|
Label smi_value, maybe_nan, have_double_value, is_nan, done;
|
||||||
|
Register mantissa_reg = scratch2;
|
||||||
|
Register exponent_reg = scratch3;
|
||||||
|
|
||||||
|
// Handle smi values specially.
|
||||||
|
JumpIfSmi(value_reg, &smi_value);
|
||||||
|
|
||||||
|
// Ensure that the object is a heap number
|
||||||
|
CheckMap(value_reg,
|
||||||
|
scratch1,
|
||||||
|
isolate()->factory()->heap_number_map(),
|
||||||
|
fail,
|
||||||
|
DONT_DO_SMI_CHECK);
|
||||||
|
|
||||||
|
// Check for nan: all NaN values have a value greater (signed) than 0x7ff00000
|
||||||
|
// in the exponent.
|
||||||
|
mov(scratch1, Operand(kNaNOrInfinityLowerBoundUpper32));
|
||||||
|
ldr(exponent_reg, FieldMemOperand(value_reg, HeapNumber::kExponentOffset));
|
||||||
|
cmp(exponent_reg, scratch1);
|
||||||
|
b(ge, &maybe_nan);
|
||||||
|
|
||||||
|
ldr(mantissa_reg, FieldMemOperand(value_reg, HeapNumber::kMantissaOffset));
|
||||||
|
|
||||||
|
bind(&have_double_value);
|
||||||
|
add(scratch1, elements_reg,
|
||||||
|
Operand(key_reg, LSL, kDoubleSizeLog2 - kSmiTagSize));
|
||||||
|
str(mantissa_reg, FieldMemOperand(scratch1, FixedDoubleArray::kHeaderSize));
|
||||||
|
uint32_t offset = FixedDoubleArray::kHeaderSize + sizeof(kHoleNanLower32);
|
||||||
|
str(exponent_reg, FieldMemOperand(scratch1, offset));
|
||||||
|
jmp(&done);
|
||||||
|
|
||||||
|
bind(&maybe_nan);
|
||||||
|
// Could be NaN or Infinity. If fraction is not zero, it's NaN, otherwise
|
||||||
|
// it's an Infinity, and the non-NaN code path applies.
|
||||||
|
b(gt, &is_nan);
|
||||||
|
ldr(mantissa_reg, FieldMemOperand(value_reg, HeapNumber::kMantissaOffset));
|
||||||
|
cmp(mantissa_reg, Operand(0));
|
||||||
|
b(eq, &have_double_value);
|
||||||
|
bind(&is_nan);
|
||||||
|
// Load canonical NaN for storing into the double array.
|
||||||
|
uint64_t nan_int64 = BitCast<uint64_t>(
|
||||||
|
FixedDoubleArray::canonical_not_the_hole_nan_as_double());
|
||||||
|
mov(mantissa_reg, Operand(static_cast<uint32_t>(nan_int64)));
|
||||||
|
mov(exponent_reg, Operand(static_cast<uint32_t>(nan_int64 >> 32)));
|
||||||
|
jmp(&have_double_value);
|
||||||
|
|
||||||
|
bind(&smi_value);
|
||||||
|
add(scratch1, elements_reg,
|
||||||
|
Operand(FixedDoubleArray::kHeaderSize - kHeapObjectTag));
|
||||||
|
add(scratch1, scratch1,
|
||||||
|
Operand(key_reg, LSL, kDoubleSizeLog2 - kSmiTagSize));
|
||||||
|
// scratch1 is now effective address of the double element
|
||||||
|
|
||||||
|
FloatingPointHelper::Destination destination;
|
||||||
|
if (CpuFeatures::IsSupported(VFP3)) {
|
||||||
|
destination = FloatingPointHelper::kVFPRegisters;
|
||||||
|
} else {
|
||||||
|
destination = FloatingPointHelper::kCoreRegisters;
|
||||||
|
}
|
||||||
|
|
||||||
|
Register untagged_value = receiver_reg;
|
||||||
|
SmiUntag(untagged_value, value_reg);
|
||||||
|
FloatingPointHelper::ConvertIntToDouble(this,
|
||||||
|
untagged_value,
|
||||||
|
destination,
|
||||||
|
d0,
|
||||||
|
mantissa_reg,
|
||||||
|
exponent_reg,
|
||||||
|
scratch4,
|
||||||
|
s2);
|
||||||
|
if (destination == FloatingPointHelper::kVFPRegisters) {
|
||||||
|
CpuFeatures::Scope scope(VFP3);
|
||||||
|
vstr(d0, scratch1, 0);
|
||||||
|
} else {
|
||||||
|
str(mantissa_reg, MemOperand(scratch1, 0));
|
||||||
|
str(exponent_reg, MemOperand(scratch1, Register::kSizeInBytes));
|
||||||
|
}
|
||||||
|
bind(&done);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void MacroAssembler::CheckMap(Register obj,
|
void MacroAssembler::CheckMap(Register obj,
|
||||||
Register scratch,
|
Register scratch,
|
||||||
Handle<Map> map,
|
Handle<Map> map,
|
||||||
|
@ -712,6 +712,19 @@ class MacroAssembler: public Assembler {
|
|||||||
Register scratch,
|
Register scratch,
|
||||||
Label* fail);
|
Label* fail);
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
void StoreNumberToDoubleElements(Register value_reg,
|
||||||
|
Register key_reg,
|
||||||
|
Register receiver_reg,
|
||||||
|
Register elements_reg,
|
||||||
|
Register scratch1,
|
||||||
|
Register scratch2,
|
||||||
|
Register scratch3,
|
||||||
|
Register scratch4,
|
||||||
|
Label* fail);
|
||||||
|
|
||||||
// Check if the map of an object is equal to a specified map (either
|
// Check if the map of an object is equal to a specified map (either
|
||||||
// given directly or as an index into the root list) and branch to
|
// given directly or as an index into the root list) and branch to
|
||||||
// label if not. Skip the smi check if not required (object is known
|
// label if not. Skip the smi check if not required (object is known
|
||||||
|
@ -4400,15 +4400,15 @@ void KeyedStoreStubCompiler::GenerateStoreFastDoubleElement(
|
|||||||
// -- r4 : scratch
|
// -- r4 : scratch
|
||||||
// -- r5 : scratch
|
// -- r5 : scratch
|
||||||
// -----------------------------------
|
// -----------------------------------
|
||||||
Label miss_force_generic, smi_value, is_nan, maybe_nan, have_double_value;
|
Label miss_force_generic;
|
||||||
|
|
||||||
Register value_reg = r0;
|
Register value_reg = r0;
|
||||||
Register key_reg = r1;
|
Register key_reg = r1;
|
||||||
Register receiver_reg = r2;
|
Register receiver_reg = r2;
|
||||||
Register scratch = r3;
|
Register elements_reg = r3;
|
||||||
Register elements_reg = r4;
|
Register scratch1 = r4;
|
||||||
Register mantissa_reg = r5;
|
Register scratch2 = r5;
|
||||||
Register exponent_reg = r6;
|
Register scratch3 = r6;
|
||||||
Register scratch4 = r7;
|
Register scratch4 = r7;
|
||||||
|
|
||||||
// This stub is meant to be tail-jumped to, the receiver must already
|
// This stub is meant to be tail-jumped to, the receiver must already
|
||||||
@ -4420,90 +4420,25 @@ void KeyedStoreStubCompiler::GenerateStoreFastDoubleElement(
|
|||||||
|
|
||||||
// Check that the key is within bounds.
|
// Check that the key is within bounds.
|
||||||
if (is_js_array) {
|
if (is_js_array) {
|
||||||
__ ldr(scratch, FieldMemOperand(receiver_reg, JSArray::kLengthOffset));
|
__ ldr(scratch1, FieldMemOperand(receiver_reg, JSArray::kLengthOffset));
|
||||||
} else {
|
} else {
|
||||||
__ ldr(scratch,
|
__ ldr(scratch1,
|
||||||
FieldMemOperand(elements_reg, FixedArray::kLengthOffset));
|
FieldMemOperand(elements_reg, FixedArray::kLengthOffset));
|
||||||
}
|
}
|
||||||
// Compare smis, unsigned compare catches both negative and out-of-bound
|
// Compare smis, unsigned compare catches both negative and out-of-bound
|
||||||
// indexes.
|
// indexes.
|
||||||
__ cmp(key_reg, scratch);
|
__ cmp(key_reg, scratch1);
|
||||||
__ b(hs, &miss_force_generic);
|
__ b(hs, &miss_force_generic);
|
||||||
|
|
||||||
// Handle smi values specially.
|
__ StoreNumberToDoubleElements(value_reg,
|
||||||
__ JumpIfSmi(value_reg, &smi_value);
|
key_reg,
|
||||||
|
receiver_reg,
|
||||||
// Ensure that the object is a heap number
|
elements_reg,
|
||||||
__ CheckMap(value_reg,
|
scratch1,
|
||||||
scratch,
|
scratch2,
|
||||||
masm->isolate()->factory()->heap_number_map(),
|
scratch3,
|
||||||
&miss_force_generic,
|
scratch4,
|
||||||
DONT_DO_SMI_CHECK);
|
&miss_force_generic);
|
||||||
|
|
||||||
// Check for nan: all NaN values have a value greater (signed) than 0x7ff00000
|
|
||||||
// in the exponent.
|
|
||||||
__ mov(scratch, Operand(kNaNOrInfinityLowerBoundUpper32));
|
|
||||||
__ ldr(exponent_reg, FieldMemOperand(value_reg, HeapNumber::kExponentOffset));
|
|
||||||
__ cmp(exponent_reg, scratch);
|
|
||||||
__ b(ge, &maybe_nan);
|
|
||||||
|
|
||||||
__ ldr(mantissa_reg, FieldMemOperand(value_reg, HeapNumber::kMantissaOffset));
|
|
||||||
|
|
||||||
__ bind(&have_double_value);
|
|
||||||
__ add(scratch, elements_reg,
|
|
||||||
Operand(key_reg, LSL, kDoubleSizeLog2 - kSmiTagSize));
|
|
||||||
__ str(mantissa_reg, FieldMemOperand(scratch, FixedDoubleArray::kHeaderSize));
|
|
||||||
uint32_t offset = FixedDoubleArray::kHeaderSize + sizeof(kHoleNanLower32);
|
|
||||||
__ str(exponent_reg, FieldMemOperand(scratch, offset));
|
|
||||||
__ Ret();
|
|
||||||
|
|
||||||
__ bind(&maybe_nan);
|
|
||||||
// Could be NaN or Infinity. If fraction is not zero, it's NaN, otherwise
|
|
||||||
// it's an Infinity, and the non-NaN code path applies.
|
|
||||||
__ b(gt, &is_nan);
|
|
||||||
__ ldr(mantissa_reg, FieldMemOperand(value_reg, HeapNumber::kMantissaOffset));
|
|
||||||
__ cmp(mantissa_reg, Operand(0));
|
|
||||||
__ b(eq, &have_double_value);
|
|
||||||
__ bind(&is_nan);
|
|
||||||
// Load canonical NaN for storing into the double array.
|
|
||||||
uint64_t nan_int64 = BitCast<uint64_t>(
|
|
||||||
FixedDoubleArray::canonical_not_the_hole_nan_as_double());
|
|
||||||
__ mov(mantissa_reg, Operand(static_cast<uint32_t>(nan_int64)));
|
|
||||||
__ mov(exponent_reg, Operand(static_cast<uint32_t>(nan_int64 >> 32)));
|
|
||||||
__ jmp(&have_double_value);
|
|
||||||
|
|
||||||
__ bind(&smi_value);
|
|
||||||
__ add(scratch, elements_reg,
|
|
||||||
Operand(FixedDoubleArray::kHeaderSize - kHeapObjectTag));
|
|
||||||
__ add(scratch, scratch,
|
|
||||||
Operand(key_reg, LSL, kDoubleSizeLog2 - kSmiTagSize));
|
|
||||||
// scratch is now effective address of the double element
|
|
||||||
|
|
||||||
FloatingPointHelper::Destination destination;
|
|
||||||
if (CpuFeatures::IsSupported(VFP3)) {
|
|
||||||
destination = FloatingPointHelper::kVFPRegisters;
|
|
||||||
} else {
|
|
||||||
destination = FloatingPointHelper::kCoreRegisters;
|
|
||||||
}
|
|
||||||
|
|
||||||
Register untagged_value = receiver_reg;
|
|
||||||
__ SmiUntag(untagged_value, value_reg);
|
|
||||||
FloatingPointHelper::ConvertIntToDouble(
|
|
||||||
masm,
|
|
||||||
untagged_value,
|
|
||||||
destination,
|
|
||||||
d0,
|
|
||||||
mantissa_reg,
|
|
||||||
exponent_reg,
|
|
||||||
scratch4,
|
|
||||||
s2);
|
|
||||||
if (destination == FloatingPointHelper::kVFPRegisters) {
|
|
||||||
CpuFeatures::Scope scope(VFP3);
|
|
||||||
__ vstr(d0, scratch, 0);
|
|
||||||
} else {
|
|
||||||
__ str(mantissa_reg, MemOperand(scratch, 0));
|
|
||||||
__ str(exponent_reg, MemOperand(scratch, Register::kSizeInBytes));
|
|
||||||
}
|
|
||||||
__ Ret();
|
__ Ret();
|
||||||
|
|
||||||
// Handle store cache miss, replacing the ic with the generic stub.
|
// Handle store cache miss, replacing the ic with the generic stub.
|
||||||
|
Loading…
Reference in New Issue
Block a user