| Index: src/x64/code-stubs-x64.cc
|
| diff --git a/src/x64/code-stubs-x64.cc b/src/x64/code-stubs-x64.cc
|
| index 7d41ffe53932610814debaf8e91b47bb7430e365..9dfd1692c20adcd443f1b807c1c83690ce5493aa 100644
|
| --- a/src/x64/code-stubs-x64.cc
|
| +++ b/src/x64/code-stubs-x64.cc
|
| @@ -5665,6 +5665,12 @@ struct AheadOfTimeWriteBarrierStubList kAheadOfTime[] = {
|
| { 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 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 __
|
|
|
| } } // namespace v8::internal
|
|
|