Revision: 9655
Author: [email protected]
Date: Mon Oct 17 03:44:47 2011
Log: Porting r9605 to x64 (elements kind conversion in generated code).
Review URL: http://codereview.chromium.org/8271007
http://code.google.com/p/v8/source/detail?r=9655
Modified:
/branches/bleeding_edge/src/code-stubs.cc
/branches/bleeding_edge/src/ia32/code-stubs-ia32.cc
/branches/bleeding_edge/src/x64/code-stubs-x64.cc
/branches/bleeding_edge/src/x64/ic-x64.cc
/branches/bleeding_edge/src/x64/macro-assembler-x64.cc
/branches/bleeding_edge/src/x64/macro-assembler-x64.h
/branches/bleeding_edge/test/mjsunit/elements-transition.js
=======================================
--- /branches/bleeding_edge/src/code-stubs.cc Thu Oct 13 03:53:31 2011
+++ /branches/bleeding_edge/src/code-stubs.cc Mon Oct 17 03:44:47 2011
@@ -416,7 +416,7 @@
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 (from_ == FAST_SMI_ONLY_ELEMENTS) {
GenerateSmiOnlyToObject(masm);
@@ -436,7 +436,7 @@
}
#else
KeyedStoreIC::GenerateRuntimeSetProperty(masm, strict_mode_);
-#endif // V8_TARGET_ARCH_IA32
+#endif // V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_X64
}
} } // namespace v8::internal
=======================================
--- /branches/bleeding_edge/src/ia32/code-stubs-ia32.cc Thu Oct 13 03:53:31
2011
+++ /branches/bleeding_edge/src/ia32/code-stubs-ia32.cc Mon Oct 17 03:44:47
2011
@@ -7061,9 +7061,8 @@
OMIT_SMI_CHECK);
__ mov(edi, FieldOperand(esi, FixedArray::kLengthOffset));
- // Convert and copy elements
- // esi: source FixedArray
- // edi: number of elements to convert/copy
+
+ // Prepare for conversion loop.
ExternalReference canonical_the_hole_nan_reference =
ExternalReference::address_of_the_hole_nan();
XMMRegister the_hole_nan = xmm1;
@@ -7073,6 +7072,18 @@
Operand::StaticVariable(canonical_the_hole_nan_reference));
}
__ 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);
__ sub(edi, Immediate(Smi::FromInt(1)));
__ mov(ebx, FieldOperand(esi, edi, times_2, FixedArray::kHeaderSize));
@@ -7110,7 +7121,6 @@
__ test(edi, edi);
__ j(not_zero, &loop);
- Label done;
__ pop(ebx);
__ pop(eax);
// eax: value
@@ -7126,15 +7136,6 @@
OMIT_SMI_CHECK);
// Restore esi.
__ 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 @@
__ mov(FieldOperand(eax, FixedArray::kLengthOffset), ebx);
__ 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.
// edi: source FixedDoubleArray
// eax: destination FixedArray
- __ jmp(&entry);
__ bind(&loop);
__ sub(ebx, Immediate(Smi::FromInt(1)));
// ebx: index of current element (smi-tagged)
@@ -7200,9 +7210,9 @@
kDontSaveFPRegs,
EMIT_REMEMBERED_SET,
OMIT_SMI_CHECK);
- __ jmp(&entry);
-
- // Replace the-hole nan with the-hole pointer.
+ __ jmp(&entry, Label::kNear);
+
+ // Replace the-hole NaN with the-hole pointer.
__ bind(&convert_hole);
__ mov(FieldOperand(eax, ebx, times_2, FixedArray::kHeaderSize),
masm->isolate()->factory()->the_hole_value());
@@ -7235,18 +7245,8 @@
OMIT_SMI_CHECK);
// Restore registers.
- Label done;
__ pop(eax);
__ 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 __
=======================================
--- /branches/bleeding_edge/src/x64/code-stubs-x64.cc Tue Oct 11 02:28:06
2011
+++ /branches/bleeding_edge/src/x64/code-stubs-x64.cc Mon Oct 17 03:44:47
2011
@@ -5665,6 +5665,12 @@
{ rbx, rdx, rcx, EMIT_REMEMBERED_SET},
// KeyedStoreStubCompiler::GenerateStoreFastElement.
{ 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.
{ no_reg, no_reg, no_reg, EMIT_REMEMBERED_SET}
};
@@ -5913,6 +5919,181 @@
}
+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 __
} } // namespace v8::internal
=======================================
--- /branches/bleeding_edge/src/x64/ic-x64.cc Mon Oct 17 00:43:40 2011
+++ /branches/bleeding_edge/src/x64/ic-x64.cc Mon Oct 17 03:44:47 2011
@@ -712,12 +712,11 @@
// Writing a non-smi, check whether array allows non-smi elements.
// r9: receiver's map
__ CheckFastObjectElements(r9, &slow, Label::kNear);
- __ lea(rcx,
- FieldOperand(rbx, rcx, times_pointer_size,
FixedArray::kHeaderSize));
- __ movq(Operand(rcx, 0), rax);
- __ movq(rdx, rax);
- __ RecordWrite(
- rbx, rcx, rdx, kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
+ __ movq(FieldOperand(rbx, rcx, times_pointer_size,
FixedArray::kHeaderSize),
+ rax);
+ __ movq(rdx, rax); // Preserve the value which is returned.
+ __ RecordWriteArray(
+ rbx, rax, rcx, kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
__ ret(0);
__ bind(&fast_double_with_map_check);
=======================================
--- /branches/bleeding_edge/src/x64/macro-assembler-x64.cc Thu Sep 29
07:08:21 2011
+++ /branches/bleeding_edge/src/x64/macro-assembler-x64.cc Mon Oct 17
03:44:47 2011
@@ -324,6 +324,40 @@
movq(dst, BitCast<int64_t>(kZapValue), RelocInfo::NONE);
}
}
+
+
+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,
=======================================
--- /branches/bleeding_edge/src/x64/macro-assembler-x64.h Thu Sep 29
07:08:21 2011
+++ /branches/bleeding_edge/src/x64/macro-assembler-x64.h Mon Oct 17
03:44:47 2011
@@ -256,8 +256,8 @@
// Notify the garbage collector that we wrote a pointer into a fixed
array.
// |array| is the array being stored into, |value| is the
- // object being stored. |index| is the array index represented as a
- // Smi. All registers are clobbered by the operation RecordWriteArray
+ // object being stored. |index| is the array index represented as a
non-smi.
+ // All registers are clobbered by the operation RecordWriteArray
// filters out smis so it does not update the write barrier if the
// value is a smi.
void RecordWriteArray(
=======================================
--- /branches/bleeding_edge/test/mjsunit/elements-transition.js Thu Oct 13
03:53:31 2011
+++ /branches/bleeding_edge/test/mjsunit/elements-transition.js Mon Oct 17
03:44:47 2011
@@ -69,6 +69,9 @@
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);
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev