| Index: src/ia32/code-stubs-ia32.cc
|
| diff --git a/src/ia32/code-stubs-ia32.cc b/src/ia32/code-stubs-ia32.cc
|
| index 1e886e202b315f03ca34e28b7749ba8c9a81f834..0cc21c4351e3c9fe5124e8e37a149a3fb1d0624f 100644
|
| --- a/src/ia32/code-stubs-ia32.cc
|
| +++ b/src/ia32/code-stubs-ia32.cc
|
| @@ -34,6 +34,7 @@
|
| #include "isolate.h"
|
| #include "jsregexp.h"
|
| #include "regexp-macro-assembler.h"
|
| +#include "stub-cache.h"
|
|
|
| namespace v8 {
|
| namespace internal {
|
| @@ -6749,6 +6750,13 @@ struct AheadOfTimeWriteBarrierStubList kAheadOfTime[] = {
|
| { ebx, edx, ecx, EMIT_REMEMBERED_SET},
|
| // KeyedStoreStubCompiler::GenerateStoreFastElement.
|
| { edi, edx, ecx, EMIT_REMEMBERED_SET},
|
| + // FastElementConversionStub::GenerateSmiOnlyToObject
|
| + // and FastElementsConversionStub::GenerateSmiOnlyToDouble
|
| + // and FastElementsConversionStub::GenerateDoubleToObject
|
| + { edx, ebx, edi, EMIT_REMEMBERED_SET},
|
| + // FastElementConversionStub::GenerateDoubleToObject
|
| + { eax, edx, esi, EMIT_REMEMBERED_SET},
|
| + { edx, eax, edi, EMIT_REMEMBERED_SET},
|
| // Null termination.
|
| { no_reg, no_reg, no_reg, EMIT_REMEMBERED_SET}
|
| };
|
| @@ -6992,6 +7000,255 @@ void RecordWriteStub::CheckNeedsToInformIncrementalMarker(
|
| }
|
|
|
|
|
| +void FastElementsConversionStub::GenerateSmiOnlyToObject(MacroAssembler* masm) {
|
| + // ----------- S t a t e -------------
|
| + // -- eax : value
|
| + // -- ebx : target map
|
| + // -- ecx : key
|
| + // -- edx : receiver
|
| + // -- esp[0] : return address
|
| + // -----------------------------------
|
| + // Set transitioned map.
|
| + __ mov(FieldOperand(edx, HeapObject::kMapOffset), ebx);
|
| + __ RecordWriteField(edx,
|
| + HeapObject::kMapOffset,
|
| + ebx,
|
| + edi,
|
| + kDontSaveFPRegs,
|
| + EMIT_REMEMBERED_SET,
|
| + OMIT_SMI_CHECK);
|
| +}
|
| +
|
| +
|
| +void FastElementsConversionStub::GenerateSmiOnlyToDouble(
|
| + MacroAssembler* masm, StrictModeFlag strict_mode) {
|
| + // ----------- S t a t e -------------
|
| + // -- eax : value
|
| + // -- ebx : target map
|
| + // -- ecx : key
|
| + // -- edx : receiver
|
| + // -- esp[0] : return address
|
| + // -----------------------------------
|
| + Label loop, entry, convert_hole, gc_required;
|
| + __ push(eax);
|
| + __ push(ebx);
|
| +
|
| + __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset));
|
| + __ mov(edi, FieldOperand(edi, FixedArray::kLengthOffset));
|
| +
|
| + // Allocate new FixedDoubleArray.
|
| + // edx: receiver
|
| + // edi: length of source FixedArray (smi-tagged)
|
| + __ lea(esi, Operand(edi, times_4, FixedDoubleArray::kHeaderSize));
|
| + __ AllocateInNewSpace(esi, eax, ebx, no_reg, &gc_required, TAG_OBJECT);
|
| +
|
| + // eax: destination FixedDoubleArray
|
| + // edi: number of elements
|
| + // edx: receiver
|
| + __ mov(FieldOperand(eax, HeapObject::kMapOffset),
|
| + Immediate(masm->isolate()->factory()->fixed_double_array_map()));
|
| + __ mov(FieldOperand(eax, FixedDoubleArray::kLengthOffset), edi);
|
| + __ mov(esi, FieldOperand(edx, JSObject::kElementsOffset));
|
| + // Replace receiver's backing store with newly created FixedDoubleArray.
|
| + __ mov(FieldOperand(edx, JSObject::kElementsOffset), eax);
|
| + __ mov(ebx, eax);
|
| + __ RecordWriteField(edx,
|
| + JSObject::kElementsOffset,
|
| + ebx,
|
| + edi,
|
| + kDontSaveFPRegs,
|
| + EMIT_REMEMBERED_SET,
|
| + OMIT_SMI_CHECK);
|
| +
|
| + __ mov(edi, FieldOperand(esi, FixedArray::kLengthOffset));
|
| + // Convert and copy elements
|
| + // esi: source FixedArray
|
| + // edi: number of elements to convert/copy
|
| + ExternalReference canonical_the_hole_nan_reference =
|
| + ExternalReference::address_of_the_hole_nan();
|
| + XMMRegister the_hole_nan = xmm1;
|
| + if (CpuFeatures::IsSupported(SSE2)) {
|
| + CpuFeatures::Scope use_sse2(SSE2);
|
| + __ movdbl(the_hole_nan,
|
| + Operand::StaticVariable(canonical_the_hole_nan_reference));
|
| + }
|
| + __ jmp(&entry);
|
| + __ bind(&loop);
|
| + __ sub(edi, Immediate(Smi::FromInt(1)));
|
| + __ mov(ebx, FieldOperand(esi, edi, times_2, FixedArray::kHeaderSize));
|
| + // ebx: current element from source
|
| + // edi: index of current element
|
| + __ JumpIfNotSmi(ebx, &convert_hole);
|
| +
|
| + // Normal smi, convert it to double and store.
|
| + __ SmiUntag(ebx);
|
| + if (CpuFeatures::IsSupported(SSE2)) {
|
| + CpuFeatures::Scope fscope(SSE2);
|
| + __ cvtsi2sd(xmm0, ebx);
|
| + __ movdbl(FieldOperand(eax, edi, times_4, FixedDoubleArray::kHeaderSize),
|
| + xmm0);
|
| + } else {
|
| + __ push(ebx);
|
| + __ fild_s(Operand(esp, 0));
|
| + __ pop(ebx);
|
| + __ fstp_d(FieldOperand(eax, edi, times_4, FixedDoubleArray::kHeaderSize));
|
| + }
|
| + __ jmp(&entry);
|
| +
|
| + // Found hole, store hole_nan_as_double instead.
|
| + __ bind(&convert_hole);
|
| + if (CpuFeatures::IsSupported(SSE2)) {
|
| + CpuFeatures::Scope use_sse2(SSE2);
|
| + __ movdbl(FieldOperand(eax, edi, times_4, FixedDoubleArray::kHeaderSize),
|
| + the_hole_nan);
|
| + } else {
|
| + __ fld_d(Operand::StaticVariable(canonical_the_hole_nan_reference));
|
| + __ fstp_d(FieldOperand(eax, edi, times_4, FixedDoubleArray::kHeaderSize));
|
| + }
|
| +
|
| + __ bind(&entry);
|
| + __ test(edi, edi);
|
| + __ j(not_zero, &loop);
|
| +
|
| + Label done;
|
| + __ pop(ebx);
|
| + __ pop(eax);
|
| + // eax: value
|
| + // ebx: target map
|
| + // Set transitioned map.
|
| + __ mov(FieldOperand(edx, HeapObject::kMapOffset), ebx);
|
| + __ RecordWriteField(edx,
|
| + HeapObject::kMapOffset,
|
| + ebx,
|
| + edi,
|
| + kDontSaveFPRegs,
|
| + EMIT_REMEMBERED_SET,
|
| + OMIT_SMI_CHECK);
|
| + // Restore esi.
|
| + __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
|
| + __ jmp(&done, Label::kNear);
|
| +
|
| + __ bind(&gc_required);
|
| + // Restore registers before jumping into runtime.
|
| + __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
|
| + __ pop(ebx);
|
| + __ pop(eax);
|
| + KeyedStoreIC::GenerateRuntimeSetProperty(masm, strict_mode);
|
| + __ bind(&done);
|
| +}
|
| +
|
| +
|
| +void FastElementsConversionStub::GenerateDoubleToObject(
|
| + MacroAssembler* masm, StrictModeFlag strict_mode) {
|
| + // ----------- S t a t e -------------
|
| + // -- eax : value
|
| + // -- ebx : target map
|
| + // -- ecx : key
|
| + // -- edx : receiver
|
| + // -- esp[0] : return address
|
| + // -----------------------------------
|
| + Label loop, entry, convert_hole, gc_required;
|
| + __ push(eax);
|
| + __ push(edx);
|
| + __ push(ebx);
|
| +
|
| + __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset));
|
| + __ mov(ebx, FieldOperand(edi, FixedDoubleArray::kLengthOffset));
|
| +
|
| + // Allocate new FixedArray.
|
| + // ebx: length of source FixedDoubleArray (smi-tagged)
|
| + __ lea(edi, Operand(ebx, times_2, FixedArray::kHeaderSize));
|
| + __ AllocateInNewSpace(edi, eax, esi, no_reg, &gc_required, TAG_OBJECT);
|
| +
|
| + // eax: destination FixedArray
|
| + // ebx: number of elements
|
| + __ mov(FieldOperand(eax, HeapObject::kMapOffset),
|
| + Immediate(masm->isolate()->factory()->fixed_array_map()));
|
| + __ mov(FieldOperand(eax, FixedArray::kLengthOffset), ebx);
|
| + __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset));
|
| +
|
| + // Box doubles into heap numbers.
|
| + // edi: source FixedDoubleArray
|
| + // eax: destination FixedArray
|
| + __ jmp(&entry);
|
| + __ bind(&loop);
|
| + __ sub(ebx, Immediate(Smi::FromInt(1)));
|
| + // ebx: index of current element (smi-tagged)
|
| + uint32_t offset = FixedDoubleArray::kHeaderSize + sizeof(kHoleNanLower32);
|
| + __ cmp(FieldOperand(edi, ebx, times_4, offset), Immediate(kHoleNanUpper32));
|
| + __ j(equal, &convert_hole);
|
| +
|
| + // Non-hole double, copy value into a heap number.
|
| + __ AllocateHeapNumber(edx, esi, no_reg, &gc_required);
|
| + // edx: new heap number
|
| + if (CpuFeatures::IsSupported(SSE2)) {
|
| + CpuFeatures::Scope fscope(SSE2);
|
| + __ movdbl(xmm0,
|
| + FieldOperand(edi, ebx, times_4, FixedDoubleArray::kHeaderSize));
|
| + __ movdbl(FieldOperand(edx, HeapNumber::kValueOffset), xmm0);
|
| + } else {
|
| + __ mov(esi, FieldOperand(edi, ebx, times_4, FixedDoubleArray::kHeaderSize));
|
| + __ mov(FieldOperand(edx, HeapNumber::kValueOffset), esi);
|
| + __ mov(esi, FieldOperand(edi, ebx, times_4, offset));
|
| + __ mov(FieldOperand(edx, HeapNumber::kValueOffset + kPointerSize), esi);
|
| + }
|
| + __ mov(FieldOperand(eax, ebx, times_2, FixedArray::kHeaderSize), edx);
|
| + __ mov(esi, ebx);
|
| + __ RecordWriteArray(eax,
|
| + edx,
|
| + esi,
|
| + kDontSaveFPRegs,
|
| + EMIT_REMEMBERED_SET,
|
| + OMIT_SMI_CHECK);
|
| + __ jmp(&entry);
|
| +
|
| + // Replace the-hole nan with the-hole pointer.
|
| + __ bind(&convert_hole);
|
| + __ mov(FieldOperand(eax, ebx, times_2, FixedArray::kHeaderSize),
|
| + masm->isolate()->factory()->the_hole_value());
|
| +
|
| + __ bind(&entry);
|
| + __ test(ebx, ebx);
|
| + __ j(not_zero, &loop);
|
| +
|
| + __ pop(ebx);
|
| + __ pop(edx);
|
| + // ebx: target map
|
| + // edx: receiver
|
| + // Set transitioned map.
|
| + __ mov(FieldOperand(edx, HeapObject::kMapOffset), ebx);
|
| + __ RecordWriteField(edx,
|
| + HeapObject::kMapOffset,
|
| + ebx,
|
| + edi,
|
| + kDontSaveFPRegs,
|
| + EMIT_REMEMBERED_SET,
|
| + OMIT_SMI_CHECK);
|
| + // Replace receiver's backing store with newly created and filled FixedArray.
|
| + __ mov(FieldOperand(edx, JSObject::kElementsOffset), eax);
|
| + __ RecordWriteField(edx,
|
| + JSObject::kElementsOffset,
|
| + eax,
|
| + edi,
|
| + kDontSaveFPRegs,
|
| + EMIT_REMEMBERED_SET,
|
| + OMIT_SMI_CHECK);
|
| +
|
| + // Restore registers.
|
| + Label done;
|
| + __ pop(eax);
|
| + __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
|
| + __ jmp(&done, Label::kNear);
|
| +
|
| + __ bind(&gc_required);
|
| + __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
|
| + __ pop(ebx);
|
| + __ pop(edx);
|
| + __ pop(eax);
|
| + KeyedStoreIC::GenerateRuntimeSetProperty(masm, strict_mode);
|
| + __ bind(&done);
|
| +}
|
| +
|
| #undef __
|
|
|
| } } // namespace v8::internal
|
|
|