Commit 92fdeff1 authored by yangguo@chromium.org's avatar yangguo@chromium.org

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

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@9655 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 0706a98b
...@@ -416,7 +416,7 @@ bool ToBooleanStub::Types::CanBeUndetectable() const { ...@@ -416,7 +416,7 @@ bool ToBooleanStub::Types::CanBeUndetectable() const {
void FastElementsConversionStub::Generate(MacroAssembler* masm) { void FastElementsConversionStub::Generate(MacroAssembler* masm) {
#if defined(V8_TARGET_ARCH_IA32) #if defined(V8_TARGET_ARCH_IA32) || defined(V8_TARGET_ARCH_X64)
if (to_ == FAST_ELEMENTS) { if (to_ == FAST_ELEMENTS) {
if (from_ == FAST_SMI_ONLY_ELEMENTS) { if (from_ == FAST_SMI_ONLY_ELEMENTS) {
GenerateSmiOnlyToObject(masm); GenerateSmiOnlyToObject(masm);
...@@ -436,7 +436,7 @@ void FastElementsConversionStub::Generate(MacroAssembler* masm) { ...@@ -436,7 +436,7 @@ void FastElementsConversionStub::Generate(MacroAssembler* masm) {
} }
#else #else
KeyedStoreIC::GenerateRuntimeSetProperty(masm, strict_mode_); KeyedStoreIC::GenerateRuntimeSetProperty(masm, strict_mode_);
#endif // V8_TARGET_ARCH_IA32 #endif // V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_X64
} }
} } // namespace v8::internal } } // namespace v8::internal
...@@ -7061,9 +7061,8 @@ void FastElementsConversionStub::GenerateSmiOnlyToDouble( ...@@ -7061,9 +7061,8 @@ void FastElementsConversionStub::GenerateSmiOnlyToDouble(
OMIT_SMI_CHECK); OMIT_SMI_CHECK);
__ mov(edi, FieldOperand(esi, FixedArray::kLengthOffset)); __ mov(edi, FieldOperand(esi, FixedArray::kLengthOffset));
// Convert and copy elements
// esi: source FixedArray // Prepare for conversion loop.
// edi: number of elements to convert/copy
ExternalReference canonical_the_hole_nan_reference = ExternalReference canonical_the_hole_nan_reference =
ExternalReference::address_of_the_hole_nan(); ExternalReference::address_of_the_hole_nan();
XMMRegister the_hole_nan = xmm1; XMMRegister the_hole_nan = xmm1;
...@@ -7073,6 +7072,18 @@ void FastElementsConversionStub::GenerateSmiOnlyToDouble( ...@@ -7073,6 +7072,18 @@ void FastElementsConversionStub::GenerateSmiOnlyToDouble(
Operand::StaticVariable(canonical_the_hole_nan_reference)); Operand::StaticVariable(canonical_the_hole_nan_reference));
} }
__ jmp(&entry); __ jmp(&entry);
// Call into runtime if GC is required.
__ bind(&gc_required);
// Restore registers before jumping into runtime.
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
__ pop(ebx);
__ pop(eax);
KeyedStoreIC::GenerateRuntimeSetProperty(masm, strict_mode);
// Convert and copy elements
// esi: source FixedArray
// edi: number of elements to convert/copy
__ bind(&loop); __ bind(&loop);
__ sub(edi, Immediate(Smi::FromInt(1))); __ sub(edi, Immediate(Smi::FromInt(1)));
__ mov(ebx, FieldOperand(esi, edi, times_2, FixedArray::kHeaderSize)); __ mov(ebx, FieldOperand(esi, edi, times_2, FixedArray::kHeaderSize));
...@@ -7110,7 +7121,6 @@ void FastElementsConversionStub::GenerateSmiOnlyToDouble( ...@@ -7110,7 +7121,6 @@ void FastElementsConversionStub::GenerateSmiOnlyToDouble(
__ test(edi, edi); __ test(edi, edi);
__ j(not_zero, &loop); __ j(not_zero, &loop);
Label done;
__ pop(ebx); __ pop(ebx);
__ pop(eax); __ pop(eax);
// eax: value // eax: value
...@@ -7126,15 +7136,6 @@ void FastElementsConversionStub::GenerateSmiOnlyToDouble( ...@@ -7126,15 +7136,6 @@ void FastElementsConversionStub::GenerateSmiOnlyToDouble(
OMIT_SMI_CHECK); OMIT_SMI_CHECK);
// Restore esi. // Restore esi.
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
__ jmp(&done, Label::kNear);
__ bind(&gc_required);
// Restore registers before jumping into runtime.
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
__ pop(ebx);
__ pop(eax);
KeyedStoreIC::GenerateRuntimeSetProperty(masm, strict_mode);
__ bind(&done);
} }
...@@ -7167,10 +7168,19 @@ void FastElementsConversionStub::GenerateDoubleToObject( ...@@ -7167,10 +7168,19 @@ void FastElementsConversionStub::GenerateDoubleToObject(
__ mov(FieldOperand(eax, FixedArray::kLengthOffset), ebx); __ mov(FieldOperand(eax, FixedArray::kLengthOffset), ebx);
__ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset));
__ jmp(&entry);
// Call into runtime if GC is required.
__ bind(&gc_required);
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
__ pop(ebx);
__ pop(edx);
__ pop(eax);
KeyedStoreIC::GenerateRuntimeSetProperty(masm, strict_mode);
// Box doubles into heap numbers. // Box doubles into heap numbers.
// edi: source FixedDoubleArray // edi: source FixedDoubleArray
// eax: destination FixedArray // eax: destination FixedArray
__ jmp(&entry);
__ bind(&loop); __ bind(&loop);
__ sub(ebx, Immediate(Smi::FromInt(1))); __ sub(ebx, Immediate(Smi::FromInt(1)));
// ebx: index of current element (smi-tagged) // ebx: index of current element (smi-tagged)
...@@ -7200,9 +7210,9 @@ void FastElementsConversionStub::GenerateDoubleToObject( ...@@ -7200,9 +7210,9 @@ void FastElementsConversionStub::GenerateDoubleToObject(
kDontSaveFPRegs, kDontSaveFPRegs,
EMIT_REMEMBERED_SET, EMIT_REMEMBERED_SET,
OMIT_SMI_CHECK); OMIT_SMI_CHECK);
__ jmp(&entry); __ jmp(&entry, Label::kNear);
// Replace the-hole nan with the-hole pointer. // Replace the-hole NaN with the-hole pointer.
__ bind(&convert_hole); __ bind(&convert_hole);
__ mov(FieldOperand(eax, ebx, times_2, FixedArray::kHeaderSize), __ mov(FieldOperand(eax, ebx, times_2, FixedArray::kHeaderSize),
masm->isolate()->factory()->the_hole_value()); masm->isolate()->factory()->the_hole_value());
...@@ -7235,18 +7245,8 @@ void FastElementsConversionStub::GenerateDoubleToObject( ...@@ -7235,18 +7245,8 @@ void FastElementsConversionStub::GenerateDoubleToObject(
OMIT_SMI_CHECK); OMIT_SMI_CHECK);
// Restore registers. // Restore registers.
Label done;
__ pop(eax); __ pop(eax);
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
__ jmp(&done, Label::kNear);
__ bind(&gc_required);
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
__ pop(ebx);
__ pop(edx);
__ pop(eax);
KeyedStoreIC::GenerateRuntimeSetProperty(masm, strict_mode);
__ bind(&done);
} }
#undef __ #undef __
......
...@@ -5665,6 +5665,12 @@ struct AheadOfTimeWriteBarrierStubList kAheadOfTime[] = { ...@@ -5665,6 +5665,12 @@ struct AheadOfTimeWriteBarrierStubList kAheadOfTime[] = {
{ rbx, rdx, rcx, EMIT_REMEMBERED_SET}, { rbx, rdx, rcx, EMIT_REMEMBERED_SET},
// KeyedStoreStubCompiler::GenerateStoreFastElement. // KeyedStoreStubCompiler::GenerateStoreFastElement.
{ rdi, rdx, rcx, EMIT_REMEMBERED_SET}, { rdi, rdx, rcx, EMIT_REMEMBERED_SET},
// FastElementsConversionStub::GenerateSmiOnlyToObject
// and FastElementsConversionStub::GenerateDoubleToObject
{ rdx, rbx, rdi, EMIT_REMEMBERED_SET},
// FastElementsConversionStub::GenerateDoubleToObject
{ rax, r11, r15, EMIT_REMEMBERED_SET},
{ rdx, rax, rdi, EMIT_REMEMBERED_SET},
// Null termination. // Null termination.
{ no_reg, no_reg, no_reg, EMIT_REMEMBERED_SET} { no_reg, no_reg, no_reg, EMIT_REMEMBERED_SET}
}; };
...@@ -5913,6 +5919,181 @@ void RecordWriteStub::CheckNeedsToInformIncrementalMarker( ...@@ -5913,6 +5919,181 @@ void RecordWriteStub::CheckNeedsToInformIncrementalMarker(
} }
void FastElementsConversionStub::GenerateSmiOnlyToObject(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- rax : value
// -- rbx : target map
// -- rcx : key
// -- rdx : receiver
// -- rsp[0] : return address
// -----------------------------------
// Set transitioned map.
__ movq(FieldOperand(rdx, HeapObject::kMapOffset), rbx);
__ RecordWriteField(rdx,
HeapObject::kMapOffset,
rbx,
rdi,
kDontSaveFPRegs,
EMIT_REMEMBERED_SET,
OMIT_SMI_CHECK);
}
void FastElementsConversionStub::GenerateSmiOnlyToDouble(
MacroAssembler* masm, StrictModeFlag strict_mode) {
// ----------- S t a t e -------------
// -- rax : value
// -- rbx : target map
// -- rcx : key
// -- rdx : receiver
// -- rsp[0] : return address
// -----------------------------------
// Set transitioned map.
__ movq(FieldOperand(rdx, HeapObject::kMapOffset), rbx);
__ RecordWriteField(rdx,
HeapObject::kMapOffset,
rbx,
rdi,
kDontSaveFPRegs,
EMIT_REMEMBERED_SET,
OMIT_SMI_CHECK);
// Set backing store's map
__ movq(r8, FieldOperand(rdx, JSObject::kElementsOffset));
__ LoadRoot(rdi, Heap::kFixedDoubleArrayMapRootIndex);
__ movq(FieldOperand(r8, HeapObject::kMapOffset), rdi);
// Convert smis to doubles and holes to hole NaNs. Since FixedArray and
// FixedDoubleArray do not differ in size, we do not allocate a new array.
STATIC_ASSERT(FixedDoubleArray::kLengthOffset == FixedArray::kLengthOffset);
STATIC_ASSERT(FixedDoubleArray::kHeaderSize == FixedArray::kHeaderSize);
__ SmiToInteger32(r9, FieldOperand(r8, FixedDoubleArray::kLengthOffset));
// r8 : elements array
// r9 : elements array length
Label loop, entry, convert_hole;
__ movq(r15, BitCast<int64_t, uint64_t>(kHoleNanInt64), RelocInfo::NONE);
// r15: the-hole NaN
__ jmp(&entry);
__ bind(&loop);
__ decq(r9);
__ movq(rbx,
FieldOperand(r8, r9, times_8, FixedArray::kHeaderSize));
// r9 : current element's index
// rbx: current element (smi-tagged)
__ JumpIfNotSmi(rbx, &convert_hole);
__ SmiToInteger32(rbx, rbx);
__ cvtlsi2sd(xmm0, rbx);
__ movsd(FieldOperand(r8, r9, times_8, FixedDoubleArray::kHeaderSize),
xmm0);
__ jmp(&entry);
__ bind(&convert_hole);
__ movq(FieldOperand(r8, r9, times_8, FixedDoubleArray::kHeaderSize), r15);
__ bind(&entry);
__ testq(r9, r9);
__ j(not_zero, &loop);
}
void FastElementsConversionStub::GenerateDoubleToObject(
MacroAssembler* masm, StrictModeFlag strict_mode) {
// ----------- S t a t e -------------
// -- rax : value
// -- rbx : target map
// -- rcx : key
// -- rdx : receiver
// -- rsp[0] : return address
// -----------------------------------
Label loop, entry, convert_hole, gc_required;
__ push(rax);
__ movq(r8, FieldOperand(rdx, JSObject::kElementsOffset));
__ SmiToInteger32(r9, FieldOperand(r8, FixedDoubleArray::kLengthOffset));
// r8 : source FixedDoubleArray
// r9 : number of elements
__ lea(rdi, Operand(r9, times_pointer_size, FixedArray::kHeaderSize));
__ AllocateInNewSpace(rdi, rax, r14, r15, &gc_required, TAG_OBJECT);
// rax: destination FixedArray
__ LoadRoot(rdi, Heap::kFixedArrayMapRootIndex);
__ movq(FieldOperand(rax, HeapObject::kMapOffset), rdi);
__ Integer32ToSmi(r14, r9);
__ movq(FieldOperand(rax, FixedArray::kLengthOffset), r14);
// Prepare for conversion loop.
__ movq(rsi, BitCast<int64_t, uint64_t>(kHoleNanInt64), RelocInfo::NONE);
__ Move(rdi, masm->isolate()->factory()->the_hole_value());
// rsi: the-hole NaN
// rdi: pointer to the-hole
__ jmp(&entry);
// Call into runtime if GC is required.
__ bind(&gc_required);
__ pop(rax);
__ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
KeyedStoreIC::GenerateRuntimeSetProperty(masm, strict_mode);
// Box doubles into heap numbers.
__ bind(&loop);
__ decq(r9);
__ movq(r14, FieldOperand(r8,
r9,
times_pointer_size,
FixedDoubleArray::kHeaderSize));
// r9 : current element's index
// r14: current element
__ cmpq(r14, rsi);
__ j(equal, &convert_hole);
// Non-hole double, copy value into a heap number.
__ AllocateHeapNumber(r11, r15, &gc_required);
// r11: new heap number
__ movq(FieldOperand(r11, HeapNumber::kValueOffset), r14);
__ movq(FieldOperand(rax,
r9,
times_pointer_size,
FixedArray::kHeaderSize),
r11);
__ movq(r15, r9);
__ RecordWriteArray(rax,
r11,
r15,
kDontSaveFPRegs,
EMIT_REMEMBERED_SET,
OMIT_SMI_CHECK);
__ jmp(&entry, Label::kNear);
// Replace the-hole NaN with the-hole pointer.
__ bind(&convert_hole);
__ movq(FieldOperand(rax,
r9,
times_pointer_size,
FixedArray::kHeaderSize),
rdi);
__ bind(&entry);
__ testq(r9, r9);
__ j(not_zero, &loop);
// Set transitioned map.
__ movq(FieldOperand(rdx, HeapObject::kMapOffset), rbx);
__ RecordWriteField(rdx,
HeapObject::kMapOffset,
rbx,
rdi,
kDontSaveFPRegs,
EMIT_REMEMBERED_SET,
OMIT_SMI_CHECK);
// Replace receiver's backing store with newly created and filled FixedArray.
__ movq(FieldOperand(rdx, JSObject::kElementsOffset), rax);
__ RecordWriteField(rdx,
JSObject::kElementsOffset,
rax,
rdi,
kDontSaveFPRegs,
EMIT_REMEMBERED_SET,
OMIT_SMI_CHECK);
__ pop(rax);
__ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
}
#undef __ #undef __
} } // namespace v8::internal } } // namespace v8::internal
......
...@@ -712,12 +712,11 @@ void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm, ...@@ -712,12 +712,11 @@ void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm,
// Writing a non-smi, check whether array allows non-smi elements. // Writing a non-smi, check whether array allows non-smi elements.
// r9: receiver's map // r9: receiver's map
__ CheckFastObjectElements(r9, &slow, Label::kNear); __ CheckFastObjectElements(r9, &slow, Label::kNear);
__ lea(rcx, __ movq(FieldOperand(rbx, rcx, times_pointer_size, FixedArray::kHeaderSize),
FieldOperand(rbx, rcx, times_pointer_size, FixedArray::kHeaderSize)); rax);
__ movq(Operand(rcx, 0), rax); __ movq(rdx, rax); // Preserve the value which is returned.
__ movq(rdx, rax); __ RecordWriteArray(
__ RecordWrite( rbx, rax, rcx, kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
rbx, rcx, rdx, kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
__ ret(0); __ ret(0);
__ bind(&fast_double_with_map_check); __ bind(&fast_double_with_map_check);
......
...@@ -326,6 +326,40 @@ void MacroAssembler::RecordWriteField( ...@@ -326,6 +326,40 @@ void MacroAssembler::RecordWriteField(
} }
void MacroAssembler::RecordWriteArray(Register object,
Register value,
Register index,
SaveFPRegsMode save_fp,
RememberedSetAction remembered_set_action,
SmiCheck smi_check) {
// First, check if a write barrier is even needed. The tests below
// catch stores of Smis.
Label done;
// Skip barrier if writing a smi.
if (smi_check == INLINE_SMI_CHECK) {
JumpIfSmi(value, &done);
}
// Array access: calculate the destination address. Index is not a smi.
Register dst = index;
lea(dst, Operand(object, index, times_pointer_size,
FixedArray::kHeaderSize - kHeapObjectTag));
RecordWrite(
object, dst, value, save_fp, remembered_set_action, OMIT_SMI_CHECK);
bind(&done);
// Clobber clobbered input registers when running with the debug-code flag
// turned on to provoke errors.
if (emit_debug_code()) {
movq(value, Immediate(BitCast<int64_t>(kZapValue)));
movq(index, Immediate(BitCast<int64_t>(kZapValue)));
}
}
void MacroAssembler::RecordWrite(Register object, void MacroAssembler::RecordWrite(Register object,
Register address, Register address,
Register value, Register value,
......
...@@ -256,8 +256,8 @@ class MacroAssembler: public Assembler { ...@@ -256,8 +256,8 @@ class MacroAssembler: public Assembler {
// Notify the garbage collector that we wrote a pointer into a fixed array. // Notify the garbage collector that we wrote a pointer into a fixed array.
// |array| is the array being stored into, |value| is the // |array| is the array being stored into, |value| is the
// object being stored. |index| is the array index represented as a // object being stored. |index| is the array index represented as a non-smi.
// Smi. All registers are clobbered by the operation RecordWriteArray // All registers are clobbered by the operation RecordWriteArray
// filters out smis so it does not update the write barrier if the // filters out smis so it does not update the write barrier if the
// value is a smi. // value is a smi.
void RecordWriteArray( void RecordWriteArray(
......
...@@ -69,6 +69,9 @@ if (support_smi_only_arrays) { ...@@ -69,6 +69,9 @@ if (support_smi_only_arrays) {
assertEquals(2*i+1, array_2[i]); assertEquals(2*i+1, array_2[i]);
} }
} }
assertEquals(length, array_1.length);
assertEquals(length, array_2.length);
} }
test(false, false, function(a,i,v){ a[i] = v; }, 100); test(false, false, function(a,i,v){ a[i] = v; }, 100);
......
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