// -- 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);
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. The Array's length
+ // remains unchanged.
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,
__ 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);
// 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);
__ 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,
// Replace the-hole NaN with the-hole pointer.
__ bind(&convert_hole);
- __ movq(FieldOperand(rax,
+ __ movq(FieldOperand(r11,
r9,
times_pointer_size,
FixedArray::kHeaderSize),
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);