Index: src/x64/codegen-x64.cc |
diff --git a/src/x64/codegen-x64.cc b/src/x64/codegen-x64.cc |
index ee40c6ef254ca124c689502cdd3c6cf40e9334ac..10eda7606e2a92f164e9a62f5a964618af3ef6de 100644 |
--- a/src/x64/codegen-x64.cc |
+++ b/src/x64/codegen-x64.cc |
@@ -182,6 +182,25 @@ void ElementsTransitionGenerator::GenerateSmiOnlyToDouble( |
// -- rsp[0] : return address |
// ----------------------------------- |
// The fail label is not actually used since we do not allocate. |
+ Label allocated, cow_array; |
+ |
+ // Check backing store for COW-ness. If the negative case, we do not have to |
+ // allocate a new array, since FixedArray and FixedDoubleArray do not differ |
+ // in size. |
+ __ movq(r8, FieldOperand(rdx, JSObject::kElementsOffset)); |
+ __ SmiToInteger32(r9, FieldOperand(r8, FixedDoubleArray::kLengthOffset)); |
+ __ CompareRoot(FieldOperand(r8, HeapObject::kMapOffset), |
+ Heap::kFixedCOWArrayMapRootIndex); |
+ __ j(equal, &cow_array); |
+ __ movq(r14, r8); // Destination array equals source array. |
+ |
+ __ bind(&allocated); |
+ // r8 : source FixedArray |
+ // r9 : elements array length |
+ // r14: destination FixedDoubleArray |
+ // Set backing store's map |
+ __ LoadRoot(rdi, Heap::kFixedDoubleArrayMapRootIndex); |
+ __ movq(FieldOperand(r14, HeapObject::kMapOffset), rdi); |
// Set transitioned map. |
__ movq(FieldOperand(rdx, HeapObject::kMapOffset), rbx); |
@@ -192,22 +211,38 @@ void ElementsTransitionGenerator::GenerateSmiOnlyToDouble( |
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. |
+ // Convert smis to doubles and holes to hole NaNs. In the non-COW case the |
+ // length does not have to be set since we still use the exact same field |
danno
2011/10/24 15:01:47
Or even simpler:
NaNs. The Array's length remains
|
+ // for length. |
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); |
+ |
+ // Allocate new array if the source array is a COW array. |
+ __ bind(&cow_array); |
+ __ lea(rdi, Operand(r9, times_pointer_size, FixedArray::kHeaderSize)); |
+ __ AllocateInNewSpace(rdi, r14, r11, r15, fail, TAG_OBJECT); |
+ // Set receiver's backing store. |
+ __ movq(FieldOperand(rdx, JSObject::kElementsOffset), r14); |
+ __ movq(r11, r14); |
+ __ RecordWriteField(rdx, |
+ JSObject::kElementsOffset, |
+ r11, |
+ r15, |
+ kDontSaveFPRegs, |
+ EMIT_REMEMBERED_SET, |
+ OMIT_SMI_CHECK); |
+ // Set backing store's length. |
+ __ Integer32ToSmi(r11, r9); |
+ __ movq(FieldOperand(r14, FixedDoubleArray::kLengthOffset), r11); |
+ __ jmp(&allocated); |
+ |
+ // Conversion loop. |
__ bind(&loop); |
__ decq(r9); |
__ movq(rbx, |
@@ -217,11 +252,11 @@ void ElementsTransitionGenerator::GenerateSmiOnlyToDouble( |
__ JumpIfNotSmi(rbx, &convert_hole); |
__ SmiToInteger32(rbx, rbx); |
__ cvtlsi2sd(xmm0, rbx); |
- __ movsd(FieldOperand(r8, r9, times_8, FixedDoubleArray::kHeaderSize), |
+ __ movsd(FieldOperand(r14, r9, times_8, FixedDoubleArray::kHeaderSize), |
xmm0); |
__ jmp(&entry); |
__ bind(&convert_hole); |
- __ movq(FieldOperand(r8, r9, times_8, FixedDoubleArray::kHeaderSize), r15); |
+ __ movq(FieldOperand(r14, r9, times_8, FixedDoubleArray::kHeaderSize), r15); |
__ bind(&entry); |
__ testq(r9, r9); |
__ j(not_zero, &loop); |
@@ -245,12 +280,12 @@ void ElementsTransitionGenerator::GenerateDoubleToObject( |
// 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 |
+ __ AllocateInNewSpace(rdi, r11, r14, r15, &gc_required, TAG_OBJECT); |
+ // r11: destination FixedArray |
__ LoadRoot(rdi, Heap::kFixedArrayMapRootIndex); |
- __ movq(FieldOperand(rax, HeapObject::kMapOffset), rdi); |
+ __ movq(FieldOperand(r11, HeapObject::kMapOffset), rdi); |
__ Integer32ToSmi(r14, r9); |
- __ movq(FieldOperand(rax, FixedArray::kLengthOffset), r14); |
+ __ movq(FieldOperand(r11, FixedArray::kLengthOffset), r14); |
// Prepare for conversion loop. |
__ movq(rsi, BitCast<int64_t, uint64_t>(kHoleNanInt64), RelocInfo::NONE); |
@@ -278,17 +313,17 @@ void ElementsTransitionGenerator::GenerateDoubleToObject( |
__ 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, |
+ __ AllocateHeapNumber(rax, r15, &gc_required); |
+ // rax: new heap number |
+ __ movq(FieldOperand(rax, HeapNumber::kValueOffset), r14); |
+ __ movq(FieldOperand(r11, |
r9, |
times_pointer_size, |
FixedArray::kHeaderSize), |
- r11); |
+ rax); |
__ movq(r15, r9); |
- __ RecordWriteArray(rax, |
- r11, |
+ __ RecordWriteArray(r11, |
+ rax, |
r15, |
kDontSaveFPRegs, |
EMIT_REMEMBERED_SET, |
@@ -297,7 +332,7 @@ void ElementsTransitionGenerator::GenerateDoubleToObject( |
// Replace the-hole NaN with the-hole pointer. |
__ bind(&convert_hole); |
- __ movq(FieldOperand(rax, |
+ __ movq(FieldOperand(r11, |
r9, |
times_pointer_size, |
FixedArray::kHeaderSize), |
@@ -317,11 +352,11 @@ void ElementsTransitionGenerator::GenerateDoubleToObject( |
EMIT_REMEMBERED_SET, |
OMIT_SMI_CHECK); |
// Replace receiver's backing store with newly created and filled FixedArray. |
- __ movq(FieldOperand(rdx, JSObject::kElementsOffset), rax); |
+ __ movq(FieldOperand(rdx, JSObject::kElementsOffset), r11); |
__ RecordWriteField(rdx, |
JSObject::kElementsOffset, |
- rax, |
- rdi, |
+ r11, |
+ r15, |
kDontSaveFPRegs, |
EMIT_REMEMBERED_SET, |
OMIT_SMI_CHECK); |