Commit 8472de00 authored by yangguo@chromium.org's avatar yangguo@chromium.org

Porting r9605 to arm (elements kind conversion in generated code).

Review URL: http://codereview.chromium.org/8329022

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@9690 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent aa917605
......@@ -6927,6 +6927,13 @@ struct AheadOfTimeWriteBarrierStubList kAheadOfTime[] = {
{ r3, r1, r2, EMIT_REMEMBERED_SET },
// KeyedStoreStubCompiler::GenerateStoreFastElement.
{ r4, r2, r3, EMIT_REMEMBERED_SET },
// FastElementsConversionStub::GenerateSmiOnlyToObject
// and FastElementsConversionStub::GenerateSmiOnlyToDouble
// and FastElementsConversionStub::GenerateDoubleToObject
{ r2, r3, r9, EMIT_REMEMBERED_SET },
// FastElementsConversionStub::GenerateDoubleToObject
{ r6, r0, r3, EMIT_REMEMBERED_SET },
{ r2, r6, r9, EMIT_REMEMBERED_SET },
// Null termination.
{ no_reg, no_reg, no_reg, EMIT_REMEMBERED_SET}
};
......@@ -7164,6 +7171,248 @@ void RecordWriteStub::CheckNeedsToInformIncrementalMarker(
}
void FastElementsConversionStub::GenerateSmiOnlyToObject(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- r0 : value
// -- r1 : key
// -- r2 : receiver
// -- lr : return address
// -- r3 : target map, scratch for subsequent call
// -- r4 : scratch (elements)
// -----------------------------------
// Set transitioned map.
__ str(r3, FieldMemOperand(r2, HeapObject::kMapOffset));
__ RecordWriteField(r2,
HeapObject::kMapOffset,
r3,
r9,
kLRHasNotBeenSaved,
kDontSaveFPRegs,
EMIT_REMEMBERED_SET,
OMIT_SMI_CHECK);
}
void FastElementsConversionStub::GenerateSmiOnlyToDouble(
MacroAssembler* masm, StrictModeFlag strict_mode) {
// ----------- S t a t e -------------
// -- r0 : value
// -- r1 : key
// -- r2 : receiver
// -- lr : return address
// -- r3 : target map, scratch for subsequent call
// -- r4 : scratch (elements)
// -----------------------------------
Label loop, entry, convert_hole, gc_required, fail;
bool vfp3_supported = CpuFeatures::IsSupported(VFP3);
__ ldr(r4, FieldMemOperand(r2, JSObject::kElementsOffset));
__ ldr(r5, FieldMemOperand(r4, FixedArray::kLengthOffset));
// r4: source FixedArray
// r5: number of elements (smi-tagged)
// Allocate new FixedDoubleArray.
__ mov(ip, Operand(FixedDoubleArray::kHeaderSize));
__ add(ip, ip, Operand(r5, LSL, 2));
__ AllocateInNewSpace(ip, r6, r7, r9, &gc_required, NO_ALLOCATION_FLAGS);
// r6: destination FixedDoubleArray, not tagged as heap object
__ LoadRoot(r9, Heap::kFixedDoubleArrayMapRootIndex);
__ str(r9, MemOperand(r6, HeapObject::kMapOffset));
// Set destination FixedDoubleArray's length.
__ str(r5, MemOperand(r6, FixedDoubleArray::kLengthOffset));
// Update receiver's map.
__ push(lr);
__ str(r3, FieldMemOperand(r2, HeapObject::kMapOffset));
__ RecordWriteField(r2,
HeapObject::kMapOffset,
r3,
r9,
kLRHasBeenSaved,
kDontSaveFPRegs,
EMIT_REMEMBERED_SET,
OMIT_SMI_CHECK);
// Replace receiver's backing store with newly created FixedDoubleArray.
__ add(r3, r6, Operand(kHeapObjectTag));
__ str(r3, FieldMemOperand(r2, JSObject::kElementsOffset));
__ RecordWriteField(r2,
JSObject::kElementsOffset,
r3,
r9,
kLRHasBeenSaved,
kDontSaveFPRegs,
EMIT_REMEMBERED_SET,
OMIT_SMI_CHECK);
__ pop(lr);
// Prepare for conversion loop.
__ add(r3, r4, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
__ add(r6, r6, Operand(FixedDoubleArray::kHeaderSize));
__ add(r4, r6, Operand(r5, LSL, 2));
__ mov(r5, Operand(kHoleNanLower32));
__ mov(r7, Operand(kHoleNanUpper32));
// r3: begin of source FixedArray element fields, not tagged
// r4: end of destination FixedDoubleArray, not tagged
// r6: begin of FixedDoubleArray element fields, not tagged
// r5: kHoleNanLower32
// r7: kHoleNanUpper32
if (vfp3_supported) __ Push(r0, r1);
__ b(&entry);
// Call into runtime if GC is required.
__ bind(&gc_required);
KeyedStoreIC::GenerateRuntimeSetProperty(masm, strict_mode);
// Convert and copy elements.
__ bind(&loop);
__ ldr(r9, MemOperand(r3, 4, PostIndex));
// r9: current element
__ JumpIfNotSmi(r9, &convert_hole);
// Normal smi, convert to double and store.
__ SmiUntag(r9);
if (vfp3_supported) {
CpuFeatures::Scope scope(VFP3);
__ vmov(s0, r9);
__ vcvt_f64_s32(d0, s0);
__ vstr(d0, r6, 0);
__ add(r6, r6, Operand(8));
} else {
FloatingPointHelper::ConvertIntToDouble(masm,
r9,
FloatingPointHelper::kCoreRegisters,
d0,
r0,
r1,
ip,
s0);
__ str(r0, MemOperand(r6, 4, PostIndex)); // mantissa
__ str(r1, MemOperand(r6, 4, PostIndex)); // exponent
}
__ b(&entry);
// Hole found, store the-hole NaN.
__ bind(&convert_hole);
__ str(r5, MemOperand(r6, 4, PostIndex)); // mantissa
__ str(r7, MemOperand(r6, 4, PostIndex)); // exponent
__ bind(&entry);
__ cmp(r6, r4);
__ b(lt, &loop);
if (vfp3_supported) __ Pop(r0, r1);
}
void FastElementsConversionStub::GenerateDoubleToObject(
MacroAssembler* masm, StrictModeFlag strict_mode) {
// ----------- S t a t e -------------
// -- r0 : value
// -- r1 : key
// -- r2 : receiver
// -- lr : return address
// -- r3 : target map, scratch for subsequent call
// -- r4 : scratch (elements)
// -----------------------------------
Label entry, loop, convert_hole, gc_required;
__ push(lr);
__ Push(r0, r1, r2, r3);
__ ldr(r4, FieldMemOperand(r2, JSObject::kElementsOffset));
__ ldr(r5, FieldMemOperand(r4, FixedArray::kLengthOffset));
// r4: source FixedDoubleArray
// r5: number of elements (smi-tagged)
// Allocate new FixedArray.
__ mov(r0, Operand(FixedDoubleArray::kHeaderSize));
__ add(r0, r0, Operand(r5, LSL, 1));
__ AllocateInNewSpace(r0, r6, r7, r9, &gc_required, NO_ALLOCATION_FLAGS);
// r6: destination FixedArray, not tagged as heap object
__ LoadRoot(r9, Heap::kFixedArrayMapRootIndex);
__ str(r9, MemOperand(r6, HeapObject::kMapOffset));
// Set destination FixedDoubleArray's length.
__ str(r5, MemOperand(r6, FixedDoubleArray::kLengthOffset));
// Prepare for conversion loop.
__ add(r4, r4, Operand(FixedDoubleArray::kHeaderSize - kHeapObjectTag + 4));
__ add(r3, r6, Operand(FixedArray::kHeaderSize - 4));
__ add(r6, r6, Operand(kHeapObjectTag));
__ add(r5, r3, Operand(r5, LSL, 1));
__ LoadRoot(r7, Heap::kTheHoleValueRootIndex);
__ LoadRoot(r9, Heap::kHeapNumberMapRootIndex);
// Using offsetted addresses to fully take advantage of pre/post-indexing
// r3: begin of destination FixedArray element fields, not tagged, -4
// r4: begin of source FixedDoubleArray element fields, not tagged, +4
// r5: end of destination FixedArray, not tagged, -4
// r6: destination FixedArray
// r7: the-hole pointer
// r9: heap number map
__ b(&entry);
// Call into runtime if GC is required.
__ bind(&gc_required);
__ Pop(r2, r3);
__ Pop(r0, r1);
__ pop(lr);
KeyedStoreIC::GenerateRuntimeSetProperty(masm, strict_mode);
__ bind(&loop);
__ ldr(lr, MemOperand(r4, 8, PostIndex));
// lr: current element's upper 32 bit
// r4: address of next element's upper 32 bit
__ cmp(lr, Operand(kHoleNanUpper32));
__ b(eq, &convert_hole);
// Non-hole double, copy value into a heap number.
__ AllocateHeapNumber(r0, r1, r2, r9, &gc_required);
__ str(lr, FieldMemOperand(r0, HeapNumber::kExponentOffset));
__ ldr(lr, MemOperand(r4, 12, NegOffset));
__ str(lr, FieldMemOperand(r0, HeapNumber::kMantissaOffset));
__ str(r0, MemOperand(r3, 4, PreIndex));
__ RecordWrite(r6,
r3,
r0,
kLRHasBeenSaved,
kDontSaveFPRegs,
EMIT_REMEMBERED_SET,
OMIT_SMI_CHECK);
__ b(&entry);
// Replace the-hole NaN with the-hole pointer.
__ bind(&convert_hole);
__ str(r7, MemOperand(r3, 4, PreIndex));
__ bind(&entry);
__ cmp(r3, r5);
__ b(lt, &loop);
__ Pop(r2, r3);
__ Pop(r0, r1);
// Update receiver's map.
__ str(r3, FieldMemOperand(r2, HeapObject::kMapOffset));
__ RecordWriteField(r2,
HeapObject::kMapOffset,
r3,
r9,
kLRHasBeenSaved,
kDontSaveFPRegs,
EMIT_REMEMBERED_SET,
OMIT_SMI_CHECK);
// Replace receiver's backing store with newly created and filled FixedArray.
__ str(r6, FieldMemOperand(r2, JSObject::kElementsOffset));
__ RecordWriteField(r2,
JSObject::kElementsOffset,
r6,
r9,
kLRHasBeenSaved,
kDontSaveFPRegs,
EMIT_REMEMBERED_SET,
OMIT_SMI_CHECK);
__ pop(lr);
}
#undef __
} } // namespace v8::internal
......
......@@ -3299,8 +3299,8 @@ MaybeObject* KeyedStoreStubCompiler::CompileStorePolymorphic(
__ Jump(code, RelocInfo::CODE_TARGET, eq);
} else {
Label next_map;
__ b(eq, &next_map);
__ mov(r4, Operand(Handle<Map>(transitioned_maps->at(i))));
__ b(ne, &next_map);
__ mov(r3, Operand(Handle<Map>(transitioned_maps->at(i))));
__ Jump(code, RelocInfo::CODE_TARGET, al);
__ bind(&next_map);
}
......
......@@ -416,7 +416,6 @@ bool ToBooleanStub::Types::CanBeUndetectable() const {
void FastElementsConversionStub::Generate(MacroAssembler* masm) {
#if defined(V8_TARGET_ARCH_IA32) || defined(V8_TARGET_ARCH_X64)
if (to_ == FAST_ELEMENTS) {
if (from_ == FAST_SMI_ONLY_ELEMENTS) {
GenerateSmiOnlyToObject(masm);
......@@ -434,9 +433,6 @@ void FastElementsConversionStub::Generate(MacroAssembler* masm) {
} else {
UNREACHABLE();
}
#else
KeyedStoreIC::GenerateRuntimeSetProperty(masm, strict_mode_);
#endif // V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_X64
}
} } // namespace v8::internal
......@@ -6019,7 +6019,7 @@ void FastElementsConversionStub::GenerateDoubleToObject(
// Prepare for conversion loop.
__ movq(rsi, BitCast<int64_t, uint64_t>(kHoleNanInt64), RelocInfo::NONE);
__ Move(rdi, masm->isolate()->factory()->the_hole_value());
__ LoadRoot(rdi, Heap::kTheHoleValueRootIndex);
// rsi: the-hole NaN
// rdi: pointer to the-hole
__ jmp(&entry);
......
......@@ -41,32 +41,38 @@ if (support_smi_only_arrays) {
assertTrue(%HasFastSmiOnlyElements(array_1));
assertTrue(%HasFastSmiOnlyElements(array_2));
for (var i = 0; i < length; i++) {
if (i == length - 8 && test_double) {
if (i == length - 5 && test_double) {
// Trigger conversion to fast double elements at length-5.
set(array_1, i, 0.5);
set(array_2, i, 0.5);
assertTrue(%HasFastDoubleElements(array_1));
assertTrue(%HasFastDoubleElements(array_2));
} else if (i == length - 5 && test_object) {
} else if (i == length - 3 && test_object) {
// Trigger conversion to fast object elements at length-3.
set(array_1, i, 'object');
set(array_2, i, 'object');
assertTrue(%HasFastElements(array_1));
assertTrue(%HasFastElements(array_2));
} else {
} else if (i != length - 7) {
// Set the element to an integer but leave a hole at length-7.
set(array_1, i, 2*i+1);
set(array_2, i, 2*i+1);
}
}
for (var i = 0; i < length; i++) {
if (i == length - 8 && test_double) {
if (i == length - 5 && test_double) {
assertEquals(0.5, array_1[i]);
assertEquals(0.5, array_2[i]);
} else if (i == length - 5 && test_object) {
} else if (i == length - 3 && test_object) {
assertEquals('object', array_1[i]);
assertEquals('object', array_2[i]);
} else {
} else if (i != length - 7) {
assertEquals(2*i+1, array_1[i]);
assertEquals(2*i+1, array_2[i]);
} else {
assertEquals(undefined, array_1[i]);
assertEquals(undefined, array_2[i]);
}
}
......@@ -74,10 +80,10 @@ if (support_smi_only_arrays) {
assertEquals(length, array_2.length);
}
test(false, false, function(a,i,v){ a[i] = v; }, 100);
test(true, false, function(a,i,v){ a[i] = v; }, 100);
test(false, true, function(a,i,v){ a[i] = v; }, 100);
test(true, true, function(a,i,v){ a[i] = v; }, 100);
test(false, false, function(a,i,v){ a[i] = v; }, 20);
test(true, false, function(a,i,v){ a[i] = v; }, 20);
test(false, true, function(a,i,v){ a[i] = v; }, 20);
test(true, true, function(a,i,v){ a[i] = v; }, 10);
test(false, false, function(a,i,v){ a[i] = v; }, 10000);
test(true, false, function(a,i,v){ a[i] = v; }, 10000);
......
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