V(KeyedStoreElement) \
V(DebuggerStatement) \
V(StringDictionaryLookup) \
- V(ElementsTransitionAndStore)
+ V(ElementsTransitionAndStore) \
+ V(StoreArrayLiteralElement)
// List of code stubs only used on ARM platforms.
#ifdef V8_TARGET_ARCH_ARM
DISALLOW_COPY_AND_ASSIGN(ElementsTransitionAndStoreStub);
};
+
+class StoreArrayLiteralElementStub : public CodeStub {
+ public:
+ explicit StoreArrayLiteralElementStub() {}
+
+ private:
+ Major MajorKey() { return StoreArrayLiteralElement; }
+ int MinorKey() { return 0; }
+
+ void Generate(MacroAssembler* masm);
+
+ DISALLOW_COPY_AND_ASSIGN(StoreArrayLiteralElementStub);
+};
+
} } // namespace v8::internal
#endif // V8_CODE_STUBS_H_
// ElementsTransitionGenerator::GenerateDoubleToObject
{ eax, edx, esi, EMIT_REMEMBERED_SET},
{ edx, eax, edi, EMIT_REMEMBERED_SET},
+ // StoreArrayLiteralElementStub::Generate
+ { ebx, eax, ecx, EMIT_REMEMBERED_SET},
// Null termination.
{ no_reg, no_reg, no_reg, EMIT_REMEMBERED_SET}
};
// Fall through when we need to inform the incremental marker.
}
+
+void StoreArrayLiteralElementStub::Generate(MacroAssembler* masm) {
+ // ----------- S t a t e -------------
+ // -- eax : element value to store
+ // -- ebx : array literal
+ // -- edi : map of array literal
+ // -- ecx : element index as smi
+ // -- edx : array literal index in function
+ // -- esp[0] : return address
+ // -----------------------------------
+
+ Label element_done;
+ Label double_elements;
+ Label smi_element;
+ Label slow_elements;
+ 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.
+ }
+
+ __ bind(&slow_elements);
+ __ pop(edi); // Pop return address and remember to put back later for tail
+ // call.
+ __ push(ebx);
+ __ push(ecx);
+ __ push(eax);
+ __ mov(ebx, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
+ __ push(FieldOperand(ebx, JSFunction::kLiteralsOffset));
+ __ push(edx);
+ __ push(edi); // Return return address so that tail call returns to right
+ // 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);
+ }
+}
+
#undef __
} } // namespace v8::internal
// Store the subexpression value in the array's elements.
__ mov(ebx, Operand(esp, 0)); // Copy of array literal.
__ mov(edi, FieldOperand(ebx, JSObject::kMapOffset));
- __ mov(ebx, FieldOperand(ebx, JSObject::kElementsOffset));
- int offset = FixedArray::kHeaderSize + (i * kPointerSize);
-
- Label element_done;
- Label double_elements;
- Label smi_element;
- Label slow_elements;
- Label fast_elements;
- __ CheckFastElements(edi, &double_elements);
-
- // FAST_SMI_ONLY_ELEMENTS or FAST_ELEMENTS
- __ JumpIfSmi(result_register(), &smi_element);
- __ CheckFastSmiOnlyElements(edi, &fast_elements, Label::kNear);
-
- // Store into the array literal requires a elements transition. Call into
- // the runtime.
- __ bind(&slow_elements);
- __ push(Operand(esp, 0)); // Copy of array literal.
- __ push(Immediate(Smi::FromInt(i)));
- __ push(result_register());
- __ push(Immediate(Smi::FromInt(NONE))); // PropertyAttributes
- __ push(Immediate(Smi::FromInt(strict_mode_flag()))); // Strict mode.
- __ CallRuntime(Runtime::kSetProperty, 5);
- __ jmp(&element_done);
-
- // Array literal has ElementsKind of FAST_DOUBLE_ELEMENTS.
- __ bind(&double_elements);
__ mov(ecx, Immediate(Smi::FromInt(i)));
- __ StoreNumberToDoubleElements(result_register(),
- ebx,
- ecx,
- edx,
- xmm0,
- &slow_elements,
- false);
- __ jmp(&element_done);
-
- // Array literal has ElementsKind of FAST_ELEMENTS and value is an object.
- __ bind(&fast_elements);
- __ mov(FieldOperand(ebx, offset), result_register());
- // Update the write barrier for the array store.
- __ RecordWriteField(ebx, offset, result_register(), ecx,
- 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(FieldOperand(ebx, offset), result_register());
- // Fall through
-
- __ bind(&element_done);
+ __ mov(edx, Immediate(Smi::FromInt(expr->literal_index())));
+ StoreArrayLiteralElementStub stub;
+ __ CallStub(&stub);
PrepareForBailoutForId(expr->GetIdForElement(i), NO_REGISTERS);
}
}
+RUNTIME_FUNCTION(MaybeObject*, Runtime_StoreArrayLiteralElement) {
+ RUNTIME_ASSERT(args.length() == 5);
+ CONVERT_ARG_CHECKED(JSObject, object, 0);
+ CONVERT_SMI_ARG_CHECKED(store_index, 1);
+ Handle<Object> value = args.at<Object>(2);
+ CONVERT_ARG_CHECKED(FixedArray, literals, 3);
+ CONVERT_SMI_ARG_CHECKED(literal_index, 4);
+ HandleScope scope;
+
+ Object* raw_boilerplate_object = literals->get(literal_index);
+ Handle<JSArray> boilerplate_object(JSArray::cast(raw_boilerplate_object));
+#if DEBUG
+ ElementsKind elements_kind = object->GetElementsKind();
+#endif
+ ASSERT(elements_kind <= FAST_DOUBLE_ELEMENTS);
+ // Smis should never trigger transitions.
+ ASSERT(!value->IsSmi());
+
+ if (value->IsNumber()) {
+ ASSERT(elements_kind == FAST_SMI_ONLY_ELEMENTS);
+ TransitionElementsKind(object, FAST_DOUBLE_ELEMENTS);
+ ASSERT(object->GetElementsKind() == FAST_DOUBLE_ELEMENTS);
+ FixedDoubleArray* double_array =
+ FixedDoubleArray::cast(object->elements());
+ HeapNumber* number = HeapNumber::cast(*value);
+ double_array->set(store_index, number->Number());
+ } else {
+ ASSERT(elements_kind == FAST_SMI_ONLY_ELEMENTS ||
+ elements_kind == FAST_DOUBLE_ELEMENTS);
+ TransitionElementsKind(object, FAST_ELEMENTS);
+ FixedArray* object_array =
+ FixedArray::cast(object->elements());
+ object_array->set(store_index, *value);
+ }
+ return *object;
+}
+
+
// Set a local property, even if it is READ_ONLY. If the property does not
// exist, it will be added with attributes NONE.
RUNTIME_FUNCTION(MaybeObject*, Runtime_IgnoreAttributesAndSetProperty) {
F(SetNewFunctionAttributes, 1, 1) \
F(AllocateInNewSpace, 1, 1) \
F(SetNativeFlag, 1, 1) \
+ F(StoreArrayLiteralElement, 5, 1) \
\
/* Array join support */ \
F(PushIfAbsent, 2, 1) \