Commit bd5e694a authored by yangguo@chromium.org's avatar yangguo@chromium.org

Refactor elements kind conversion.

Review URL: http://codereview.chromium.org/8355035

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@9724 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent a47caee0
......@@ -6936,11 +6936,11 @@ 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
// ElementsTransitionGenerator::GenerateSmiOnlyToObject
// and ElementsTransitionGenerator::GenerateSmiOnlyToDouble
// and ElementsTransitionGenerator::GenerateDoubleToObject
{ r2, r3, r9, EMIT_REMEMBERED_SET },
// FastElementsConversionStub::GenerateDoubleToObject
// ElementsTransitionGenerator::GenerateDoubleToObject
{ r6, r2, r0, EMIT_REMEMBERED_SET },
{ r2, r6, r9, EMIT_REMEMBERED_SET },
// Null termination.
......@@ -7179,248 +7179,6 @@ void RecordWriteStub::CheckNeedsToInformIncrementalMarker(
// Fall through when we need to inform the incremental marker.
}
void FastElementsConversionStub::GenerateSmiOnlyToObject(
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)
// -----------------------------------
// 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(r7, r6, Operand(FixedDoubleArray::kHeaderSize));
__ add(r6, r7, Operand(r5, LSL, 2));
__ mov(r4, Operand(kHoleNanLower32));
__ mov(r5, Operand(kHoleNanUpper32));
// r3: begin of source FixedArray element fields, not tagged
// r4: kHoleNanLower32
// r5: kHoleNanUpper32
// r6: end of destination FixedDoubleArray, not tagged
// r7: begin of FixedDoubleArray element fields, not tagged
if (vfp3_supported) __ Push(r1, r0);
__ 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, r7, 0);
__ add(r7, r7, Operand(8));
} else {
FloatingPointHelper::ConvertIntToDouble(masm,
r9,
FloatingPointHelper::kCoreRegisters,
d0,
r0,
r1,
ip,
s0);
__ Strd(r0, r1, MemOperand(r7, 8, PostIndex));
}
__ b(&entry);
// Hole found, store the-hole NaN.
__ bind(&convert_hole);
__ Strd(r4, r5, MemOperand(r7, 8, PostIndex));
__ bind(&entry);
__ cmp(r7, r6);
__ b(lt, &loop);
if (vfp3_supported) __ Pop(r1, r0);
}
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(r3, r2, r1, r0);
__ ldr(r4, FieldMemOperand(r2, JSObject::kElementsOffset));
__ ldr(r5, FieldMemOperand(r4, FixedArray::kLengthOffset));
// r4: source FixedDoubleArray
// 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));
__ add(r6, r6, Operand(kHeapObjectTag));
__ add(r5, r3, Operand(r5, LSL, 1));
__ LoadRoot(r7, Heap::kTheHoleValueRootIndex);
__ LoadRoot(r9, Heap::kHeapNumberMapRootIndex);
// Using offsetted addresses in r4 to fully take advantage of post-indexing.
// r3: begin of destination FixedArray element fields, not tagged
// r4: begin of source FixedDoubleArray element fields, not tagged, +4
// r5: end of destination FixedArray, not tagged
// r6: destination FixedArray
// r7: the-hole pointer
// r9: heap number map
__ b(&entry);
// Call into runtime if GC is required.
__ bind(&gc_required);
__ Pop(r3, r2, r1, r0);
__ pop(lr);
KeyedStoreIC::GenerateRuntimeSetProperty(masm, strict_mode);
__ bind(&loop);
__ ldr(r1, MemOperand(r4, 8, PostIndex));
// lr: current element's upper 32 bit
// r4: address of next element's upper 32 bit
__ cmp(r1, Operand(kHoleNanUpper32));
__ b(eq, &convert_hole);
// Non-hole double, copy value into a heap number.
__ AllocateHeapNumber(r2, r0, lr, r9, &gc_required);
// r2: new heap number
__ ldr(r0, MemOperand(r4, 12, NegOffset));
__ Strd(r0, r1, FieldMemOperand(r2, HeapNumber::kValueOffset));
__ mov(r0, r3);
__ str(r2, MemOperand(r3, 4, PostIndex));
__ RecordWrite(r6,
r0,
r2,
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, PostIndex));
__ bind(&entry);
__ cmp(r3, r5);
__ b(lt, &loop);
__ Pop(r3, r2, r1, r0);
// 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
......
......@@ -30,10 +30,13 @@
#if defined(V8_TARGET_ARCH_ARM)
#include "codegen.h"
#include "macro-assembler.h"
namespace v8 {
namespace internal {
#define __ ACCESS_MASM(masm)
// -------------------------------------------------------------------------
// Platform-specific RuntimeCallHelper functions.
......@@ -51,6 +54,252 @@ void StubRuntimeCallHelper::AfterCall(MacroAssembler* masm) const {
}
// -------------------------------------------------------------------------
// Code generators
void ElementsTransitionGenerator::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 ElementsTransitionGenerator::GenerateSmiOnlyToDouble(
MacroAssembler* masm, Label* fail) {
// ----------- 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;
bool vfp3_supported = CpuFeatures::IsSupported(VFP3);
__ push(lr);
__ 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(lr, Operand(FixedDoubleArray::kHeaderSize));
__ add(lr, lr, Operand(r5, LSL, 2));
__ AllocateInNewSpace(lr, 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.
__ 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);
// Prepare for conversion loop.
__ add(r3, r4, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
__ add(r7, r6, Operand(FixedDoubleArray::kHeaderSize));
__ add(r6, r7, Operand(r5, LSL, 2));
__ mov(r4, Operand(kHoleNanLower32));
__ mov(r5, Operand(kHoleNanUpper32));
// r3: begin of source FixedArray element fields, not tagged
// r4: kHoleNanLower32
// r5: kHoleNanUpper32
// r6: end of destination FixedDoubleArray, not tagged
// r7: begin of FixedDoubleArray element fields, not tagged
if (!vfp3_supported) __ Push(r1, r0);
__ b(&entry);
// Call into runtime if GC is required.
__ bind(&gc_required);
__ pop(lr);
__ b(fail);
// 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, r7, 0);
__ add(r7, r7, Operand(8));
} else {
FloatingPointHelper::ConvertIntToDouble(masm,
r9,
FloatingPointHelper::kCoreRegisters,
d0,
r0,
r1,
lr,
s0);
__ Strd(r0, r1, MemOperand(r7, 8, PostIndex));
}
__ b(&entry);
// Hole found, store the-hole NaN.
__ bind(&convert_hole);
__ Strd(r4, r5, MemOperand(r7, 8, PostIndex));
__ bind(&entry);
__ cmp(r7, r6);
__ b(lt, &loop);
if (!vfp3_supported) __ Pop(r1, r0);
__ pop(lr);
}
void ElementsTransitionGenerator::GenerateDoubleToObject(
MacroAssembler* masm, Label* fail) {
// ----------- 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(r3, r2, r1, r0);
__ ldr(r4, FieldMemOperand(r2, JSObject::kElementsOffset));
__ ldr(r5, FieldMemOperand(r4, FixedArray::kLengthOffset));
// r4: source FixedDoubleArray
// 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));
__ add(r6, r6, Operand(kHeapObjectTag));
__ add(r5, r3, Operand(r5, LSL, 1));
__ LoadRoot(r7, Heap::kTheHoleValueRootIndex);
__ LoadRoot(r9, Heap::kHeapNumberMapRootIndex);
// Using offsetted addresses in r4 to fully take advantage of post-indexing.
// r3: begin of destination FixedArray element fields, not tagged
// r4: begin of source FixedDoubleArray element fields, not tagged, +4
// r5: end of destination FixedArray, not tagged
// r6: destination FixedArray
// r7: the-hole pointer
// r9: heap number map
__ b(&entry);
// Call into runtime if GC is required.
__ bind(&gc_required);
__ Pop(r3, r2, r1, r0);
__ pop(lr);
__ b(fail);
__ bind(&loop);
__ ldr(r1, MemOperand(r4, 8, PostIndex));
// lr: current element's upper 32 bit
// r4: address of next element's upper 32 bit
__ cmp(r1, Operand(kHoleNanUpper32));
__ b(eq, &convert_hole);
// Non-hole double, copy value into a heap number.
__ AllocateHeapNumber(r2, r0, lr, r9, &gc_required);
// r2: new heap number
__ ldr(r0, MemOperand(r4, 12, NegOffset));
__ Strd(r0, r1, FieldMemOperand(r2, HeapNumber::kValueOffset));
__ mov(r0, r3);
__ str(r2, MemOperand(r3, 4, PostIndex));
__ RecordWrite(r6,
r0,
r2,
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, PostIndex));
__ bind(&entry);
__ cmp(r3, r5);
__ b(lt, &loop);
__ Pop(r3, r2, r1, r0);
// 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
#endif // V8_TARGET_ARCH_ARM
......@@ -29,7 +29,6 @@
#define V8_ARM_CODEGEN_ARM_H_
#include "ast.h"
#include "code-stubs-arm.h"
#include "ic-inl.h"
namespace v8 {
......
......@@ -1247,9 +1247,17 @@ void KeyedStoreIC::GenerateSlow(MacroAssembler* masm) {
void KeyedStoreIC::GenerateTransitionElementsSmiToDouble(MacroAssembler* masm) {
// ---------- S t a t e --------------
// -- r2 : receiver
// -- r3 : target map
// -- lr : return address
// -----------------------------------
// Must return the modified receiver in r0.
if (!FLAG_trace_elements_transitions) {
Label fail;
ElementsTransitionGenerator::GenerateSmiOnlyToDouble(masm, &fail);
__ mov(r0, r2);
__ Ret();
__ bind(&fail);
}
__ push(r2);
__ TailCallRuntime(Runtime::kTransitionElementsSmiToDouble, 1, 1);
......@@ -1260,9 +1268,17 @@ void KeyedStoreIC::GenerateTransitionElementsDoubleToObject(
MacroAssembler* masm) {
// ---------- S t a t e --------------
// -- r2 : receiver
// -- r3 : target map
// -- lr : return address
// -----------------------------------
// Must return the modified receiver in r0.
if (!FLAG_trace_elements_transitions) {
Label fail;
ElementsTransitionGenerator::GenerateDoubleToObject(masm, &fail);
__ mov(r0, r2);
__ Ret();
__ bind(&fail);
}
__ push(r2);
__ TailCallRuntime(Runtime::kTransitionElementsDoubleToObject, 1, 1);
......
......@@ -1602,6 +1602,7 @@ void MacroAssembler::AllocateInNewSpace(Register object_size,
ASSERT(!result.is(scratch1));
ASSERT(!result.is(scratch2));
ASSERT(!scratch1.is(scratch2));
ASSERT(!object_size.is(ip));
ASSERT(!result.is(ip));
ASSERT(!scratch1.is(ip));
ASSERT(!scratch2.is(ip));
......
......@@ -415,24 +415,29 @@ bool ToBooleanStub::Types::CanBeUndetectable() const {
}
void FastElementsConversionStub::Generate(MacroAssembler* masm) {
if (to_ == FAST_ELEMENTS) {
if (from_ == FAST_SMI_ONLY_ELEMENTS) {
GenerateSmiOnlyToObject(masm, strict_mode_);
} else if (from_ == FAST_DOUBLE_ELEMENTS) {
GenerateDoubleToObject(masm, strict_mode_);
void ElementsTransitionAndStoreStub::Generate(MacroAssembler* masm) {
Label fail;
if (!FLAG_trace_elements_transitions) {
if (to_ == FAST_ELEMENTS) {
if (from_ == FAST_SMI_ONLY_ELEMENTS) {
ElementsTransitionGenerator::GenerateSmiOnlyToObject(masm);
} else if (from_ == FAST_DOUBLE_ELEMENTS) {
ElementsTransitionGenerator::GenerateDoubleToObject(masm, &fail);
} else {
UNREACHABLE();
}
KeyedStoreStubCompiler::GenerateStoreFastElement(masm,
is_jsarray_,
FAST_ELEMENTS);
} else if (from_ == FAST_SMI_ONLY_ELEMENTS && to_ == FAST_DOUBLE_ELEMENTS) {
ElementsTransitionGenerator::GenerateSmiOnlyToDouble(masm, &fail);
KeyedStoreStubCompiler::GenerateStoreFastDoubleElement(masm, is_jsarray_);
} else {
UNREACHABLE();
}
KeyedStoreStubCompiler::GenerateStoreFastElement(masm,
is_jsarray_,
FAST_ELEMENTS);
} else if (from_ == FAST_SMI_ONLY_ELEMENTS && to_ == FAST_DOUBLE_ELEMENTS) {
GenerateSmiOnlyToDouble(masm, strict_mode_);
KeyedStoreStubCompiler::GenerateStoreFastDoubleElement(masm, is_jsarray_);
} else {
UNREACHABLE();
}
masm->bind(&fail);
KeyedStoreIC::GenerateRuntimeSetProperty(masm, strict_mode_);
}
} } // namespace v8::internal
......@@ -30,6 +30,7 @@
#include "allocation.h"
#include "globals.h"
#include "codegen.h"
namespace v8 {
namespace internal {
......@@ -70,7 +71,7 @@ namespace internal {
V(KeyedStoreElement) \
V(DebuggerStatement) \
V(StringDictionaryLookup) \
V(FastElementsConversion)
V(ElementsTransitionAndStore)
// List of code stubs only used on ARM platforms.
#ifdef V8_TARGET_ARCH_ARM
......@@ -1028,12 +1029,12 @@ class ToBooleanStub: public CodeStub {
};
class FastElementsConversionStub : public CodeStub {
class ElementsTransitionAndStoreStub : public CodeStub {
public:
FastElementsConversionStub(ElementsKind from,
ElementsKind to,
bool is_jsarray,
StrictModeFlag strict_mode)
ElementsTransitionAndStoreStub(ElementsKind from,
ElementsKind to,
bool is_jsarray,
StrictModeFlag strict_mode)
: from_(from),
to_(to),
is_jsarray_(is_jsarray),
......@@ -1045,7 +1046,7 @@ class FastElementsConversionStub : public CodeStub {
class IsJSArrayBits: public BitField<bool, 16, 8> {};
class StrictModeBits: public BitField<StrictModeFlag, 24, 8> {};
Major MajorKey() { return FastElementsConversion; }
Major MajorKey() { return ElementsTransitionAndStore; }
int MinorKey() {
return FromBits::encode(from_) |
ToBits::encode(to_) |
......@@ -1054,19 +1055,13 @@ class FastElementsConversionStub : public CodeStub {
}
void Generate(MacroAssembler* masm);
static void GenerateSmiOnlyToObject(MacroAssembler* masm,
StrictModeFlag strict_mode);
static void GenerateSmiOnlyToDouble(MacroAssembler* masm,
StrictModeFlag strict_mode);
static void GenerateDoubleToObject(MacroAssembler* masm,
StrictModeFlag strict_mode);
ElementsKind from_;
ElementsKind to_;
bool is_jsarray_;
StrictModeFlag strict_mode_;
DISALLOW_COPY_AND_ASSIGN(FastElementsConversionStub);
DISALLOW_COPY_AND_ASSIGN(ElementsTransitionAndStoreStub);
};
} } // namespace v8::internal
......
......@@ -81,4 +81,19 @@ enum TypeofState { INSIDE_TYPEOF, NOT_INSIDE_TYPEOF };
#error Unsupported target architecture.
#endif
namespace v8 {
namespace internal {
class ElementsTransitionGenerator : public AllStatic {
public:
static void GenerateSmiOnlyToObject(MacroAssembler* masm);
static void GenerateSmiOnlyToDouble(MacroAssembler* masm, Label* fail);
static void GenerateDoubleToObject(MacroAssembler* masm, Label* fail);
private:
DISALLOW_COPY_AND_ASSIGN(ElementsTransitionGenerator);
};
} } // namespace v8::internal
#endif // V8_CODEGEN_H_
This diff is collapsed.
......@@ -30,6 +30,7 @@
#if defined(V8_TARGET_ARCH_IA32)
#include "codegen.h"
#include "macro-assembler.h"
namespace v8 {
namespace internal {
......@@ -265,6 +266,263 @@ OS::MemCopyFunction CreateMemCopyFunction() {
#undef __
// -------------------------------------------------------------------------
// Code generators
#define __ ACCESS_MASM(masm)
void ElementsTransitionGenerator::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 ElementsTransitionGenerator::GenerateSmiOnlyToDouble(
MacroAssembler* masm, Label* fail) {
// ----------- 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));
// Prepare for conversion loop.
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);
// Call into runtime if GC is required.
__ bind(&gc_required);
// Restore registers before jumping into runtime.
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
__ pop(ebx);
__ pop(eax);
__ jmp(fail);
// Convert and copy elements
// esi: source FixedArray
// edi: number of elements to convert/copy
__ 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);
__ 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));
}
void ElementsTransitionGenerator::GenerateDoubleToObject(
MacroAssembler* masm, Label* fail) {
// ----------- 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));
__ jmp(&entry);
// Call into runtime if GC is required.
__ bind(&gc_required);
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
__ pop(ebx);
__ pop(edx);
__ pop(eax);
__ jmp(fail);
// Box doubles into heap numbers.
// edi: source FixedDoubleArray
// eax: destination FixedArray
__ 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, Label::kNear);
// 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.
__ pop(eax);
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
}
#undef __
} } // namespace v8::internal
#endif // V8_TARGET_ARCH_IA32
......@@ -1582,15 +1582,22 @@ void KeyedStoreIC::GenerateSlow(MacroAssembler* masm) {
void KeyedStoreIC::GenerateTransitionElementsSmiToDouble(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- ebx : target map
// -- edx : receiver
// -- esp[0] : return address
// -----------------------------------
// Must return the modified receiver in eax.
if (!FLAG_trace_elements_transitions) {
Label fail;
ElementsTransitionGenerator::GenerateSmiOnlyToDouble(masm, &fail);
__ mov(eax, edx);
__ Ret();
__ bind(&fail);
}
__ pop(ebx);
__ push(edx);
__ push(ebx); // return address
__ TailCallRuntime(Runtime::kTransitionElementsSmiToDouble, 1, 1);
}
......@@ -1598,15 +1605,22 @@ void KeyedStoreIC::GenerateTransitionElementsSmiToDouble(MacroAssembler* masm) {
void KeyedStoreIC::GenerateTransitionElementsDoubleToObject(
MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- ebx : target map
// -- edx : receiver
// -- esp[0] : return address
// -----------------------------------
// Must return the modified receiver in eax.
if (!FLAG_trace_elements_transitions) {
Label fail;
ElementsTransitionGenerator::GenerateDoubleToObject(masm, &fail);
__ mov(eax, edx);
__ Ret();
__ bind(&fail);
}
__ pop(ebx);
__ push(edx);
__ push(ebx); // return address
__ TailCallRuntime(Runtime::kTransitionElementsDoubleToObject, 1, 1);
}
......
......@@ -1686,7 +1686,7 @@ MaybeObject* KeyedStoreIC::ComputePolymorphicStub(
MaybeObject* maybe_cached_stub = NULL;
Map* transitioned_map = receiver_map->FindTransitionedMap(receiver_maps);
if (transitioned_map != NULL) {
maybe_cached_stub = FastElementsConversionStub(
maybe_cached_stub = ElementsTransitionAndStoreStub(
receiver_map->elements_kind(), // original elements_kind
transitioned_map->elements_kind(),
receiver_map->instance_type() == JS_ARRAY_TYPE, // is_js_array
......
......@@ -490,6 +490,10 @@ void ExternalReferenceTable::PopulateTable(Isolate* isolate) {
UNCLASSIFIED,
44,
"canonical_nan");
Add(ExternalReference::address_of_the_hole_nan().address(),
UNCLASSIFIED,
45,
"the_hole_nan");
}
......
......@@ -5688,10 +5688,10 @@ struct AheadOfTimeWriteBarrierStubList kAheadOfTime[] = {
{ rbx, rdx, rcx, EMIT_REMEMBERED_SET},
// KeyedStoreStubCompiler::GenerateStoreFastElement.
{ rdi, rdx, rcx, EMIT_REMEMBERED_SET},
// FastElementsConversionStub::GenerateSmiOnlyToObject
// and FastElementsConversionStub::GenerateDoubleToObject
// ElementsTransitionGenerator::GenerateSmiOnlyToObject
// and ElementsTransitionGenerator::GenerateDoubleToObject
{ rdx, rbx, rdi, EMIT_REMEMBERED_SET},
// FastElementsConversionStub::GenerateDoubleToObject
// ElementsTransitionGenerator::GenerateDoubleToObject
{ rax, r11, r15, EMIT_REMEMBERED_SET},
{ rdx, rax, rdi, EMIT_REMEMBERED_SET},
// Null termination.
......@@ -5941,184 +5941,6 @@ void RecordWriteStub::CheckNeedsToInformIncrementalMarker(
// Fall through when we need to inform the incremental marker.
}
void FastElementsConversionStub::GenerateSmiOnlyToObject(
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);
}
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);
__ LoadRoot(rdi, Heap::kTheHoleValueRootIndex);
// 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
......
......@@ -30,6 +30,7 @@
#if defined(V8_TARGET_ARCH_X64)
#include "codegen.h"
#include "macro-assembler.h"
namespace v8 {
namespace internal {
......@@ -143,6 +144,190 @@ ModuloFunction CreateModuloFunction() {
#endif
#undef __
// -------------------------------------------------------------------------
// Code generators
#define __ ACCESS_MASM(masm)
void ElementsTransitionGenerator::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 ElementsTransitionGenerator::GenerateSmiOnlyToDouble(
MacroAssembler* masm, Label* fail) {
// ----------- S t a t e -------------
// -- rax : value
// -- rbx : target map
// -- rcx : key
// -- rdx : receiver
// -- rsp[0] : return address
// -----------------------------------
// The fail label is not actually used since we do not allocate.
// 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 ElementsTransitionGenerator::GenerateDoubleToObject(
MacroAssembler* masm, Label* fail) {
// ----------- 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);
__ LoadRoot(rdi, Heap::kTheHoleValueRootIndex);
// 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));
__ jmp(fail);
// 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 __
......
......@@ -1603,15 +1603,22 @@ void KeyedStoreIC::GenerateMiss(MacroAssembler* masm, bool force_generic) {
void KeyedStoreIC::GenerateTransitionElementsSmiToDouble(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- rbx : target map
// -- rdx : receiver
// -- rsp[0] : return address
// -----------------------------------
// Must return the modified receiver in eax.
if (!FLAG_trace_elements_transitions) {
Label fail;
ElementsTransitionGenerator::GenerateSmiOnlyToDouble(masm, &fail);
__ movq(rax, rdx);
__ Ret();
__ bind(&fail);
}
__ pop(rbx);
__ push(rdx);
__ push(rbx); // return address
__ TailCallRuntime(Runtime::kTransitionElementsSmiToDouble, 1, 1);
}
......@@ -1619,15 +1626,22 @@ void KeyedStoreIC::GenerateTransitionElementsSmiToDouble(MacroAssembler* masm) {
void KeyedStoreIC::GenerateTransitionElementsDoubleToObject(
MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- rbx : target map
// -- rdx : receiver
// -- rsp[0] : return address
// -----------------------------------
// Must return the modified receiver in eax.
if (!FLAG_trace_elements_transitions) {
Label fail;
ElementsTransitionGenerator::GenerateDoubleToObject(masm, &fail);
__ movq(rax, rdx);
__ Ret();
__ bind(&fail);
}
__ pop(rbx);
__ push(rdx);
__ push(rbx); // return address
__ TailCallRuntime(Runtime::kTransitionElementsDoubleToObject, 1, 1);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment