Chromium Code Reviews| 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); |