| Index: src/arm/code-stubs-arm.cc
|
| diff --git a/src/arm/code-stubs-arm.cc b/src/arm/code-stubs-arm.cc
|
| index 3afa76c9bbeea22fb64ab1f29e02c74c249b4620..444d5cf98021cccc9c1c9c4b5037e48961931a20 100644
|
| --- a/src/arm/code-stubs-arm.cc
|
| +++ b/src/arm/code-stubs-arm.cc
|
| @@ -6927,6 +6927,13 @@ struct AheadOfTimeWriteBarrierStubList kAheadOfTime[] = {
|
| { r3, r1, r2, EMIT_REMEMBERED_SET },
|
| // KeyedStoreStubCompiler::GenerateStoreFastElement.
|
| { r4, r2, r3, EMIT_REMEMBERED_SET },
|
| + // FastElementsConversionStub::GenerateSmiOnlyToObject
|
| + // and FastElementsConversionStub::GenerateSmiOnlyToDouble
|
| + // and FastElementsConversionStub::GenerateDoubleToObject
|
| + { r2, r3, r9, EMIT_REMEMBERED_SET },
|
| + // FastElementsConversionStub::GenerateDoubleToObject
|
| + { r6, r0, r3, EMIT_REMEMBERED_SET },
|
| + { r2, r6, r9, EMIT_REMEMBERED_SET },
|
| // Null termination.
|
| { no_reg, no_reg, no_reg, EMIT_REMEMBERED_SET}
|
| };
|
| @@ -7164,6 +7171,248 @@ void RecordWriteStub::CheckNeedsToInformIncrementalMarker(
|
| }
|
|
|
|
|
| +void FastElementsConversionStub::GenerateSmiOnlyToObject(MacroAssembler* masm) {
|
| + // ----------- S t a t e -------------
|
| + // -- r0 : value
|
| + // -- r1 : key
|
| + // -- r2 : receiver
|
| + // -- lr : return address
|
| + // -- r3 : target map, scratch for subsequent call
|
| + // -- r4 : scratch (elements)
|
| + // -----------------------------------
|
| + // Set transitioned map.
|
| + __ str(r3, FieldMemOperand(r2, HeapObject::kMapOffset));
|
| + __ RecordWriteField(r2,
|
| + HeapObject::kMapOffset,
|
| + r3,
|
| + r9,
|
| + kLRHasNotBeenSaved,
|
| + kDontSaveFPRegs,
|
| + EMIT_REMEMBERED_SET,
|
| + OMIT_SMI_CHECK);
|
| +}
|
| +
|
| +
|
| +void FastElementsConversionStub::GenerateSmiOnlyToDouble(
|
| + MacroAssembler* masm, StrictModeFlag strict_mode) {
|
| + // ----------- S t a t e -------------
|
| + // -- r0 : value
|
| + // -- r1 : key
|
| + // -- r2 : receiver
|
| + // -- lr : return address
|
| + // -- r3 : target map, scratch for subsequent call
|
| + // -- r4 : scratch (elements)
|
| + // -----------------------------------
|
| + Label loop, entry, convert_hole, gc_required, fail;
|
| + bool vfp3_supported = CpuFeatures::IsSupported(VFP3);
|
| +
|
| + __ ldr(r4, FieldMemOperand(r2, JSObject::kElementsOffset));
|
| + __ ldr(r5, FieldMemOperand(r4, FixedArray::kLengthOffset));
|
| + // r4: source FixedArray
|
| + // r5: number of elements (smi-tagged)
|
| +
|
| + // Allocate new FixedDoubleArray.
|
| + __ mov(ip, Operand(FixedDoubleArray::kHeaderSize));
|
| + __ add(ip, ip, Operand(r5, LSL, 2));
|
| + __ AllocateInNewSpace(ip, r6, r7, r9, &gc_required, NO_ALLOCATION_FLAGS);
|
| + // r6: destination FixedDoubleArray, not tagged as heap object
|
| + __ LoadRoot(r9, Heap::kFixedDoubleArrayMapRootIndex);
|
| + __ str(r9, MemOperand(r6, HeapObject::kMapOffset));
|
| + // Set destination FixedDoubleArray's length.
|
| + __ str(r5, MemOperand(r6, FixedDoubleArray::kLengthOffset));
|
| + // Update receiver's map.
|
| + __ push(lr);
|
| + __ str(r3, FieldMemOperand(r2, HeapObject::kMapOffset));
|
| + __ RecordWriteField(r2,
|
| + HeapObject::kMapOffset,
|
| + r3,
|
| + r9,
|
| + kLRHasBeenSaved,
|
| + kDontSaveFPRegs,
|
| + EMIT_REMEMBERED_SET,
|
| + OMIT_SMI_CHECK);
|
| + // Replace receiver's backing store with newly created FixedDoubleArray.
|
| + __ add(r3, r6, Operand(kHeapObjectTag));
|
| + __ str(r3, FieldMemOperand(r2, JSObject::kElementsOffset));
|
| + __ RecordWriteField(r2,
|
| + JSObject::kElementsOffset,
|
| + r3,
|
| + r9,
|
| + kLRHasBeenSaved,
|
| + kDontSaveFPRegs,
|
| + EMIT_REMEMBERED_SET,
|
| + OMIT_SMI_CHECK);
|
| + __ pop(lr);
|
| +
|
| + // Prepare for conversion loop.
|
| + __ add(r3, r4, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
|
| + __ add(r6, r6, Operand(FixedDoubleArray::kHeaderSize));
|
| + __ add(r4, r6, Operand(r5, LSL, 2));
|
| + __ mov(r5, Operand(kHoleNanLower32));
|
| + __ mov(r7, Operand(kHoleNanUpper32));
|
| + // r3: begin of source FixedArray element fields, not tagged
|
| + // r4: end of destination FixedDoubleArray, not tagged
|
| + // r6: begin of FixedDoubleArray element fields, not tagged
|
| + // r5: kHoleNanLower32
|
| + // r7: kHoleNanUpper32
|
| + if (vfp3_supported) __ Push(r0, r1);
|
| +
|
| + __ b(&entry);
|
| +
|
| + // Call into runtime if GC is required.
|
| + __ bind(&gc_required);
|
| + KeyedStoreIC::GenerateRuntimeSetProperty(masm, strict_mode);
|
| +
|
| + // Convert and copy elements.
|
| + __ bind(&loop);
|
| + __ ldr(r9, MemOperand(r3, 4, PostIndex));
|
| + // r9: current element
|
| + __ JumpIfNotSmi(r9, &convert_hole);
|
| +
|
| + // Normal smi, convert to double and store.
|
| + __ SmiUntag(r9);
|
| + if (vfp3_supported) {
|
| + CpuFeatures::Scope scope(VFP3);
|
| + __ vmov(s0, r9);
|
| + __ vcvt_f64_s32(d0, s0);
|
| + __ vstr(d0, r6, 0);
|
| + __ add(r6, r6, Operand(8));
|
| + } else {
|
| + FloatingPointHelper::ConvertIntToDouble(masm,
|
| + r9,
|
| + FloatingPointHelper::kCoreRegisters,
|
| + d0,
|
| + r0,
|
| + r1,
|
| + ip,
|
| + s0);
|
| + __ str(r0, MemOperand(r6, 4, PostIndex)); // mantissa
|
| + __ str(r1, MemOperand(r6, 4, PostIndex)); // exponent
|
| + }
|
| + __ b(&entry);
|
| +
|
| + // Hole found, store the-hole NaN.
|
| + __ bind(&convert_hole);
|
| + __ str(r5, MemOperand(r6, 4, PostIndex)); // mantissa
|
| + __ str(r7, MemOperand(r6, 4, PostIndex)); // exponent
|
| +
|
| + __ bind(&entry);
|
| + __ cmp(r6, r4);
|
| + __ b(lt, &loop);
|
| +
|
| + if (vfp3_supported) __ Pop(r0, r1);
|
| +}
|
| +
|
| +
|
| +void FastElementsConversionStub::GenerateDoubleToObject(
|
| + MacroAssembler* masm, StrictModeFlag strict_mode) {
|
| + // ----------- S t a t e -------------
|
| + // -- r0 : value
|
| + // -- r1 : key
|
| + // -- r2 : receiver
|
| + // -- lr : return address
|
| + // -- r3 : target map, scratch for subsequent call
|
| + // -- r4 : scratch (elements)
|
| + // -----------------------------------
|
| + Label entry, loop, convert_hole, gc_required;
|
| + __ push(lr);
|
| + __ Push(r0, r1, r2, r3);
|
| +
|
| + __ ldr(r4, FieldMemOperand(r2, JSObject::kElementsOffset));
|
| + __ ldr(r5, FieldMemOperand(r4, FixedArray::kLengthOffset));
|
| + // r4: source FixedArray
|
| + // r5: number of elements (smi-tagged)
|
| +
|
| + // Allocate new FixedArray.
|
| + __ mov(r0, Operand(FixedDoubleArray::kHeaderSize));
|
| + __ add(r0, r0, Operand(r5, LSL, 1));
|
| + __ AllocateInNewSpace(r0, r6, r7, r9, &gc_required, NO_ALLOCATION_FLAGS);
|
| + // r6: destination FixedArray, not tagged as heap object
|
| + __ LoadRoot(r9, Heap::kFixedArrayMapRootIndex);
|
| + __ str(r9, MemOperand(r6, HeapObject::kMapOffset));
|
| + // Set destination FixedDoubleArray's length.
|
| + __ str(r5, MemOperand(r6, FixedDoubleArray::kLengthOffset));
|
| +
|
| + // Prepare for conversion loop.
|
| + __ add(r4, r4, Operand(FixedDoubleArray::kHeaderSize - kHeapObjectTag + 4));
|
| + __ add(r3, r6, Operand(FixedArray::kHeaderSize - 4));
|
| + __ add(r6, r6, Operand(kHeapObjectTag));
|
| + __ add(r5, r3, Operand(r5, LSL, 1));
|
| + __ LoadRoot(r7, Heap::kTheHoleValueRootIndex);
|
| + __ LoadRoot(r9, Heap::kHeapNumberMapRootIndex);
|
| + // Using offsetted addresses to fully take advantage of pre/post-indexing
|
| + // r3: begin of destination FixedArray element fields, not tagged, -4
|
| + // r4: begin of source FixedDoubleArray element fields, not tagged, +4
|
| + // r5: end of destination FixedArray, not tagged, -4
|
| + // r6: destination FixedArray
|
| + // r7: the-hole pointer
|
| + // r9: heap number map
|
| + __ b(&entry);
|
| +
|
| + // Call into runtime if GC is required.
|
| + __ bind(&gc_required);
|
| + __ Pop(r2, r3);
|
| + __ Pop(r0, r1);
|
| + __ pop(lr);
|
| + KeyedStoreIC::GenerateRuntimeSetProperty(masm, strict_mode);
|
| +
|
| + __ bind(&loop);
|
| + __ ldr(ip, MemOperand(r4, 8, PostIndex));
|
| + // ip: current element's upper 32 bit
|
| + // r4: address of next element's upper 32 bit
|
| + __ cmp(ip, Operand(kHoleNanUpper32));
|
| + __ b(eq, &convert_hole);
|
| +
|
| + // Non-hole double, copy value into a heap number.
|
| + __ AllocateHeapNumber(r0, r1, r2, r9, &gc_required);
|
| + __ ldr(ip, MemOperand(r4, 12, NegOffset));
|
| + __ str(ip, FieldMemOperand(r0, HeapNumber::kMantissaOffset));
|
| + __ ldr(ip, MemOperand(r4, 8, NegOffset));
|
| + __ str(ip, FieldMemOperand(r0, HeapNumber::kExponentOffset));
|
| + __ str(r0, MemOperand(r3, 4, PreIndex));
|
| + __ RecordWrite(r6,
|
| + r3,
|
| + r0,
|
| + kLRHasBeenSaved,
|
| + kDontSaveFPRegs,
|
| + EMIT_REMEMBERED_SET,
|
| + OMIT_SMI_CHECK);
|
| + __ b(&entry);
|
| +
|
| + // Replace the-hole NaN with the-hole pointer.
|
| + __ bind(&convert_hole);
|
| + __ str(r7, MemOperand(r3, 4, PreIndex));
|
| +
|
| + __ bind(&entry);
|
| + __ cmp(r3, r5);
|
| + __ b(lt, &loop);
|
| +
|
| + __ Pop(r2, r3);
|
| + __ Pop(r0, r1);
|
| + // Update receiver's map.
|
| + __ str(r3, FieldMemOperand(r2, HeapObject::kMapOffset));
|
| + __ RecordWriteField(r2,
|
| + HeapObject::kMapOffset,
|
| + r3,
|
| + r9,
|
| + kLRHasBeenSaved,
|
| + kDontSaveFPRegs,
|
| + EMIT_REMEMBERED_SET,
|
| + OMIT_SMI_CHECK);
|
| + // Replace receiver's backing store with newly created and filled FixedArray.
|
| + __ str(r6, FieldMemOperand(r2, JSObject::kElementsOffset));
|
| + __ RecordWriteField(r2,
|
| + JSObject::kElementsOffset,
|
| + r6,
|
| + r9,
|
| + kLRHasBeenSaved,
|
| + kDontSaveFPRegs,
|
| + EMIT_REMEMBERED_SET,
|
| + OMIT_SMI_CHECK);
|
| + __ pop(lr);
|
| +}
|
| +
|
| +
|
| #undef __
|
|
|
| } } // namespace v8::internal
|
|
|