Revision: 9979
Author: [email protected]
Date: Fri Nov 11 06:49:16 2011
Log: ARM: Implement runtime function for array literal transitions.
Also simplify ia32 and x64 handing of the trace_elements_transition flag.
[email protected]
BUG=none
TEST=array-literal-transitions.js
Review URL: http://codereview.chromium.org/8539011
http://code.google.com/p/v8/source/detail?r=9979
Modified:
/branches/bleeding_edge/src/arm/code-stubs-arm.cc
/branches/bleeding_edge/src/arm/full-codegen-arm.cc
/branches/bleeding_edge/src/builtins.cc
/branches/bleeding_edge/src/ia32/code-stubs-ia32.cc
/branches/bleeding_edge/src/objects-inl.h
/branches/bleeding_edge/src/objects.cc
/branches/bleeding_edge/src/objects.h
/branches/bleeding_edge/src/x64/code-stubs-x64.cc
=======================================
--- /branches/bleeding_edge/src/arm/code-stubs-arm.cc Fri Nov 11 05:48:14
2011
+++ /branches/bleeding_edge/src/arm/code-stubs-arm.cc Fri Nov 11 06:49:16
2011
@@ -6888,6 +6888,8 @@
// ElementsTransitionGenerator::GenerateDoubleToObject
{ r6, r2, r0, EMIT_REMEMBERED_SET },
{ r2, r6, r9, EMIT_REMEMBERED_SET },
+ // StoreArrayLiteralElementStub::Generate
+ { r5, r0, r6, EMIT_REMEMBERED_SET },
// Null termination.
{ no_reg, no_reg, no_reg, EMIT_REMEMBERED_SET}
};
@@ -7123,6 +7125,64 @@
// Fall through when we need to inform the incremental marker.
}
+
+
+void StoreArrayLiteralElementStub::Generate(MacroAssembler* masm) {
+ // ----------- S t a t e -------------
+ // -- r0 : element value to store
+ // -- r1 : array literal
+ // -- r2 : map of array literal
+ // -- r3 : element index as smi
+ // -- r4 : array literal index in function as smi
+ // -----------------------------------
+
+ Label element_done;
+ Label double_elements;
+ Label smi_element;
+ Label slow_elements;
+ Label fast_elements;
+
+ __ CheckFastElements(r2, r5, &double_elements);
+ // FAST_SMI_ONLY_ELEMENTS or FAST_ELEMENTS
+ __ JumpIfSmi(r0, &smi_element);
+ __ CheckFastSmiOnlyElements(r2, r5, &fast_elements);
+
+ // Store into the array literal requires a elements transition. Call into
+ // the runtime.
+ __ bind(&slow_elements);
+ // call.
+ __ Push(r1, r3, r0);
+ __ ldr(r5, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
+ __ ldr(r5, FieldMemOperand(r5, JSFunction::kLiteralsOffset));
+ __ Push(r5, r4);
+ __ TailCallRuntime(Runtime::kStoreArrayLiteralElement, 5, 1);
+
+ // Array literal has ElementsKind of FAST_ELEMENTS and value is an
object.
+ __ bind(&fast_elements);
+ __ ldr(r5, FieldMemOperand(r1, JSObject::kElementsOffset));
+ __ add(r6, r5, Operand(r3, LSL, kPointerSizeLog2 - kSmiTagSize));
+ __ add(r6, r6, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
+ __ str(r0, MemOperand(r6, 0));
+ // Update the write barrier for the array store.
+ __ RecordWrite(r5, r6, r0, kLRHasNotBeenSaved, kDontSaveFPRegs,
+ EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
+ __ Ret();
+
+ // Array literal has ElementsKind of FAST_SMI_ONLY_ELEMENTS or
+ // FAST_ELEMENTS, and value is Smi.
+ __ bind(&smi_element);
+ __ ldr(r5, FieldMemOperand(r1, JSObject::kElementsOffset));
+ __ add(r6, r5, Operand(r3, LSL, kPointerSizeLog2 - kSmiTagSize));
+ __ str(r0, FieldMemOperand(r6, FixedArray::kHeaderSize));
+ __ Ret();
+
+ // Array literal has ElementsKind of FAST_DOUBLE_ELEMENTS.
+ __ bind(&double_elements);
+ __ ldr(r5, FieldMemOperand(r1, JSObject::kElementsOffset));
+ __ StoreNumberToDoubleElements(r0, r3, r1, r5, r6, r7, r9, r10,
+ &slow_elements);
+ __ Ret();
+}
#undef __
=======================================
--- /branches/bleeding_edge/src/arm/full-codegen-arm.cc Fri Nov 11 05:48:14
2011
+++ /branches/bleeding_edge/src/arm/full-codegen-arm.cc Fri Nov 11 06:49:16
2011
@@ -1580,56 +1580,12 @@
}
VisitForAccumulatorValue(subexpr);
- __ ldr(r6, MemOperand(sp)); // Copy of array literal.
- __ ldr(r1, FieldMemOperand(r6, JSObject::kElementsOffset));
- __ ldr(r2, FieldMemOperand(r6, JSObject::kMapOffset));
- int offset = FixedArray::kHeaderSize + (i * kPointerSize);
-
- Label element_done;
- Label double_elements;
- Label smi_element;
- Label slow_elements;
- Label fast_elements;
- __ CheckFastElements(r2, r3, &double_elements);
-
- // FAST_SMI_ONLY_ELEMENTS or FAST_ELEMENTS
- __ JumpIfSmi(result_register(), &smi_element);
- __ CheckFastSmiOnlyElements(r2, r3, &fast_elements);
-
- // Store into the array literal requires a elements transition. Call
into
- // the runtime.
- __ bind(&slow_elements);
- __ push(r6); // Copy of array literal.
- __ mov(r1, Operand(Smi::FromInt(i)));
- __ mov(r2, Operand(Smi::FromInt(NONE))); // PropertyAttributes
- __ mov(r3, Operand(Smi::FromInt(strict_mode_flag()))); // Strict mode.
- __ Push(r1, result_register(), r2, r3);
- __ CallRuntime(Runtime::kSetProperty, 5);
- __ b(&element_done);
-
- // Array literal has ElementsKind of FAST_DOUBLE_ELEMENTS.
- __ bind(&double_elements);
+ __ ldr(r1, MemOperand(sp)); // Copy of array literal.
+ __ ldr(r2, FieldMemOperand(r1, JSObject::kMapOffset));
__ mov(r3, Operand(Smi::FromInt(i)));
- __ StoreNumberToDoubleElements(result_register(), r3, r6, r1, r4, r5,
r9,
- r7, &slow_elements);
- __ b(&element_done);
-
- // Array literal has ElementsKind of FAST_ELEMENTS and value is an
object.
- __ bind(&fast_elements);
- __ str(result_register(), FieldMemOperand(r1, offset));
- // Update the write barrier for the array store.
- __ RecordWriteField(
- r1, offset, result_register(), r2, kLRHasBeenSaved,
kDontSaveFPRegs,
- EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
- __ b(&element_done);
-
- // Array literal has ElementsKind of FAST_SMI_ONLY_ELEMENTS or
- // FAST_ELEMENTS, and value is Smi.
- __ bind(&smi_element);
- __ str(result_register(), FieldMemOperand(r1, offset));
- // Fall through
-
- __ bind(&element_done);
+ __ mov(r4, Operand(Smi::FromInt(expr->literal_index())));
+ StoreArrayLiteralElementStub stub;
+ __ CallStub(&stub);
PrepareForBailoutForId(expr->GetIdForElement(i), NO_REGISTERS);
}
=======================================
--- /branches/bleeding_edge/src/builtins.cc Tue Nov 8 06:39:37 2011
+++ /branches/bleeding_edge/src/builtins.cc Fri Nov 11 06:49:16 2011
@@ -775,7 +775,8 @@
// Set the ElementsKind.
ElementsKind elements_kind = JSObject::cast(receiver)->GetElementsKind();
- if (result_array->GetElementsKind() != elements_kind) {
+ if (IsMoreGeneralElementsKindTransition(result_array->GetElementsKind(),
+ elements_kind)) {
MaybeObject* maybe =
result_array->TransitionElementsKind(elements_kind);
if (maybe->IsFailure()) return maybe;
}
@@ -875,7 +876,8 @@
// Set the ElementsKind.
ElementsKind elements_kind = array->GetElementsKind();
- if (result_array->GetElementsKind() != elements_kind) {
+ if
(IsMoreGeneralElementsKindTransition(result_array->GetElementsKind(),
+ elements_kind)) {
MaybeObject* maybe =
result_array->TransitionElementsKind(elements_kind);
if (maybe->IsFailure()) return maybe;
}
=======================================
--- /branches/bleeding_edge/src/ia32/code-stubs-ia32.cc Fri Nov 11 05:48:14
2011
+++ /branches/bleeding_edge/src/ia32/code-stubs-ia32.cc Fri Nov 11 06:49:16
2011
@@ -7046,16 +7046,14 @@
Label slow_elements_from_double;
Label fast_elements;
- if (!FLAG_trace_elements_transitions) {
- __ CheckFastElements(edi, &double_elements);
-
- // FAST_SMI_ONLY_ELEMENTS or FAST_ELEMENTS
- __ JumpIfSmi(eax, &smi_element);
- __ CheckFastSmiOnlyElements(edi, &fast_elements, Label::kNear);
-
- // Store into the array literal requires a elements transition. Call
into
- // the runtime.
- }
+ __ CheckFastElements(edi, &double_elements);
+
+ // FAST_SMI_ONLY_ELEMENTS or FAST_ELEMENTS
+ __ JumpIfSmi(eax, &smi_element);
+ __ CheckFastSmiOnlyElements(edi, &fast_elements, Label::kNear);
+
+ // Store into the array literal requires a elements transition. Call into
+ // the runtime.
__ bind(&slow_elements);
__ pop(edi); // Pop return address and remember to put back later for
tail
@@ -7070,49 +7068,45 @@
// place.
__ TailCallRuntime(Runtime::kStoreArrayLiteralElement, 5, 1);
- if (!FLAG_trace_elements_transitions) {
- // Array literal has ElementsKind of FAST_DOUBLE_ELEMENTS.
- __ bind(&double_elements);
-
- __ push(edx);
- __ mov(edx, FieldOperand(ebx, JSObject::kElementsOffset));
- __ StoreNumberToDoubleElements(eax,
- edx,
- ecx,
- edi,
- xmm0,
- &slow_elements_from_double,
- false);
- __ pop(edx);
- __ jmp(&element_done);
-
- __ bind(&slow_elements_from_double);
- __ pop(edx);
- __ jmp(&slow_elements);
-
- // Array literal has ElementsKind of FAST_ELEMENTS and value is an
object.
- __ bind(&fast_elements);
- __ mov(ebx, FieldOperand(ebx, JSObject::kElementsOffset));
- __ lea(ecx, FieldOperand(ebx, ecx, times_half_pointer_size,
- FixedArrayBase::kHeaderSize));
- __ mov(Operand(ecx, 0), eax);
- // Update the write barrier for the array store.
- __ RecordWrite(ebx, ecx, eax,
- kDontSaveFPRegs,
- EMIT_REMEMBERED_SET,
- OMIT_SMI_CHECK);
- __ jmp(&element_done);
-
- // Array literal has ElementsKind of FAST_SMI_ONLY_ELEMENTS or
- // FAST_ELEMENTS, and value is Smi.
- __ bind(&smi_element);
- __ mov(ebx, FieldOperand(ebx, JSObject::kElementsOffset));
- __ mov(FieldOperand(ebx, ecx, times_half_pointer_size,
- FixedArrayBase::kHeaderSize), eax);
- // Fall through
- __ bind(&element_done);
- __ ret(0);
- }
+ __ bind(&slow_elements_from_double);
+ __ pop(edx);
+ __ jmp(&slow_elements);
+
+ // Array literal has ElementsKind of FAST_ELEMENTS and value is an
object.
+ __ bind(&fast_elements);
+ __ mov(ebx, FieldOperand(ebx, JSObject::kElementsOffset));
+ __ lea(ecx, FieldOperand(ebx, ecx, times_half_pointer_size,
+ FixedArrayBase::kHeaderSize));
+ __ mov(Operand(ecx, 0), eax);
+ // Update the write barrier for the array store.
+ __ RecordWrite(ebx, ecx, eax,
+ kDontSaveFPRegs,
+ EMIT_REMEMBERED_SET,
+ OMIT_SMI_CHECK);
+ __ ret(0);
+
+ // Array literal has ElementsKind of FAST_SMI_ONLY_ELEMENTS or
+ // FAST_ELEMENTS, and value is Smi.
+ __ bind(&smi_element);
+ __ mov(ebx, FieldOperand(ebx, JSObject::kElementsOffset));
+ __ mov(FieldOperand(ebx, ecx, times_half_pointer_size,
+ FixedArrayBase::kHeaderSize), eax);
+ __ ret(0);
+
+ // Array literal has ElementsKind of FAST_DOUBLE_ELEMENTS.
+ __ bind(&double_elements);
+
+ __ push(edx);
+ __ mov(edx, FieldOperand(ebx, JSObject::kElementsOffset));
+ __ StoreNumberToDoubleElements(eax,
+ edx,
+ ecx,
+ edi,
+ xmm0,
+ &slow_elements_from_double,
+ false);
+ __ pop(edx);
+ __ ret(0);
}
#undef __
=======================================
--- /branches/bleeding_edge/src/objects-inl.h Fri Nov 11 05:48:14 2011
+++ /branches/bleeding_edge/src/objects-inl.h Fri Nov 11 06:49:16 2011
@@ -117,6 +117,18 @@
void holder::set_##name(bool value) { \
set_##field(BooleanBit::set(field(), offset, value)); \
}
+
+
+bool IsMoreGeneralElementsKindTransition(ElementsKind from_kind,
+ ElementsKind to_kind) {
+ if (to_kind == FAST_ELEMENTS) {
+ return from_kind == FAST_SMI_ONLY_ELEMENTS ||
+ from_kind == FAST_DOUBLE_ELEMENTS;
+ } else {
+ return to_kind == FAST_DOUBLE_ELEMENTS &&
+ from_kind == FAST_SMI_ONLY_ELEMENTS;
+ }
+}
bool Object::IsFixedArrayBase() {
=======================================
--- /branches/bleeding_edge/src/objects.cc Fri Nov 11 04:28:42 2011
+++ /branches/bleeding_edge/src/objects.cc Fri Nov 11 06:49:16 2011
@@ -9501,6 +9501,9 @@
MaybeObject* maybe_new_map = GetElementsTransitionMap(FAST_ELEMENTS);
Map* new_map;
if (!maybe_new_map->To(&new_map)) return maybe_new_map;
+ if (FLAG_trace_elements_transitions) {
+ PrintElementsTransition(stdout, from_kind, elms, FAST_ELEMENTS,
elms);
+ }
set_map(new_map);
return this;
}
=======================================
--- /branches/bleeding_edge/src/objects.h Fri Nov 11 05:48:14 2011
+++ /branches/bleeding_edge/src/objects.h Fri Nov 11 06:49:16 2011
@@ -167,6 +167,8 @@
void PrintElementsKind(FILE* out, ElementsKind kind);
+inline bool IsMoreGeneralElementsKindTransition(ElementsKind from_kind,
+ ElementsKind to_kind);
// Setter that skips the write barrier if mode is SKIP_WRITE_BARRIER.
enum WriteBarrierMode { SKIP_WRITE_BARRIER, UPDATE_WRITE_BARRIER };
=======================================
--- /branches/bleeding_edge/src/x64/code-stubs-x64.cc Fri Nov 11 05:48:14
2011
+++ /branches/bleeding_edge/src/x64/code-stubs-x64.cc Fri Nov 11 06:49:16
2011
@@ -5971,16 +5971,14 @@
Label slow_elements;
Label fast_elements;
- if (!FLAG_trace_elements_transitions) {
- __ CheckFastElements(rdi, &double_elements);
-
- // FAST_SMI_ONLY_ELEMENTS or FAST_ELEMENTS
- __ JumpIfSmi(rax, &smi_element);
- __ CheckFastSmiOnlyElements(rdi, &fast_elements);
-
- // Store into the array literal requires a elements transition. Call
into
- // the runtime.
- }
+ __ CheckFastElements(rdi, &double_elements);
+
+ // FAST_SMI_ONLY_ELEMENTS or FAST_ELEMENTS
+ __ JumpIfSmi(rax, &smi_element);
+ __ CheckFastSmiOnlyElements(rdi, &fast_elements);
+
+ // Store into the array literal requires a elements transition. Call into
+ // the runtime.
__ bind(&slow_elements);
__ pop(rdi); // Pop return address and remember to put back later for
tail
@@ -5995,44 +5993,40 @@
// place.
__ TailCallRuntime(Runtime::kStoreArrayLiteralElement, 5, 1);
- if (!FLAG_trace_elements_transitions) {
- // Array literal has ElementsKind of FAST_DOUBLE_ELEMENTS.
- __ bind(&double_elements);
-
- __ movq(r9, FieldOperand(rbx, JSObject::kElementsOffset));
- __ SmiToInteger32(r11, rcx);
- __ StoreNumberToDoubleElements(rax,
- r9,
- r11,
- xmm0,
- &slow_elements);
- __ jmp(&element_done);
-
- // Array literal has ElementsKind of FAST_ELEMENTS and value is an
object.
- __ bind(&fast_elements);
- __ SmiToInteger32(kScratchRegister, rcx);
- __ movq(rbx, FieldOperand(rbx, JSObject::kElementsOffset));
- __ lea(rcx, FieldOperand(rbx, kScratchRegister, times_pointer_size,
- FixedArrayBase::kHeaderSize));
- __ movq(Operand(rcx, 0), rax);
- // Update the write barrier for the array store.
- __ RecordWrite(rbx, rcx, rax,
- kDontSaveFPRegs,
- EMIT_REMEMBERED_SET,
- OMIT_SMI_CHECK);
- __ jmp(&element_done);
-
- // Array literal has ElementsKind of FAST_SMI_ONLY_ELEMENTS or
- // FAST_ELEMENTS, and value is Smi.
- __ bind(&smi_element);
- __ SmiToInteger32(kScratchRegister, rcx);
- __ movq(rbx, FieldOperand(rbx, JSObject::kElementsOffset));
- __ movq(FieldOperand(rbx, kScratchRegister, times_pointer_size,
- FixedArrayBase::kHeaderSize), rax);
- // Fall through
- __ bind(&element_done);
- __ ret(0);
- }
+ // Array literal has ElementsKind of FAST_ELEMENTS and value is an
object.
+ __ bind(&fast_elements);
+ __ SmiToInteger32(kScratchRegister, rcx);
+ __ movq(rbx, FieldOperand(rbx, JSObject::kElementsOffset));
+ __ lea(rcx, FieldOperand(rbx, kScratchRegister, times_pointer_size,
+ FixedArrayBase::kHeaderSize));
+ __ movq(Operand(rcx, 0), rax);
+ // Update the write barrier for the array store.
+ __ RecordWrite(rbx, rcx, rax,
+ kDontSaveFPRegs,
+ EMIT_REMEMBERED_SET,
+ OMIT_SMI_CHECK);
+ __ ret(0);
+
+ // Array literal has ElementsKind of FAST_SMI_ONLY_ELEMENTS or
+ // FAST_ELEMENTS, and value is Smi.
+ __ bind(&smi_element);
+ __ SmiToInteger32(kScratchRegister, rcx);
+ __ movq(rbx, FieldOperand(rbx, JSObject::kElementsOffset));
+ __ movq(FieldOperand(rbx, kScratchRegister, times_pointer_size,
+ FixedArrayBase::kHeaderSize), rax);
+ __ ret(0);
+
+ // Array literal has ElementsKind of FAST_DOUBLE_ELEMENTS.
+ __ bind(&double_elements);
+
+ __ movq(r9, FieldOperand(rbx, JSObject::kElementsOffset));
+ __ SmiToInteger32(r11, rcx);
+ __ StoreNumberToDoubleElements(rax,
+ r9,
+ r11,
+ xmm0,
+ &slow_elements);
+ __ ret(0);
}
#undef __
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev