Create stub and runtime function for ia32 full-codegen array literal element initialization.

BUG=none
TEST=none

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@9849 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
danno@chromium.org 2011-10-31 14:42:06 +00:00
parent 669bfc0363
commit 75585d9643
5 changed files with 147 additions and 54 deletions

View File

@ -71,7 +71,8 @@ namespace internal {
V(KeyedStoreElement) \ V(KeyedStoreElement) \
V(DebuggerStatement) \ V(DebuggerStatement) \
V(StringDictionaryLookup) \ V(StringDictionaryLookup) \
V(ElementsTransitionAndStore) V(ElementsTransitionAndStore) \
V(StoreArrayLiteralElement)
// List of code stubs only used on ARM platforms. // List of code stubs only used on ARM platforms.
#ifdef V8_TARGET_ARCH_ARM #ifdef V8_TARGET_ARCH_ARM
@ -1064,6 +1065,20 @@ class ElementsTransitionAndStoreStub : public CodeStub {
DISALLOW_COPY_AND_ASSIGN(ElementsTransitionAndStoreStub); 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 } } // namespace v8::internal
#endif // V8_CODE_STUBS_H_ #endif // V8_CODE_STUBS_H_

View File

@ -6787,6 +6787,8 @@ struct AheadOfTimeWriteBarrierStubList kAheadOfTime[] = {
// ElementsTransitionGenerator::GenerateDoubleToObject // ElementsTransitionGenerator::GenerateDoubleToObject
{ eax, edx, esi, EMIT_REMEMBERED_SET}, { eax, edx, esi, EMIT_REMEMBERED_SET},
{ edx, eax, edi, EMIT_REMEMBERED_SET}, { edx, eax, edi, EMIT_REMEMBERED_SET},
// StoreArrayLiteralElementStub::Generate
{ ebx, eax, ecx, EMIT_REMEMBERED_SET},
// Null termination. // Null termination.
{ no_reg, no_reg, no_reg, EMIT_REMEMBERED_SET} { no_reg, no_reg, no_reg, EMIT_REMEMBERED_SET}
}; };
@ -7029,6 +7031,93 @@ void RecordWriteStub::CheckNeedsToInformIncrementalMarker(
// Fall through when we need to inform the incremental marker. // 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 __ #undef __
} } // namespace v8::internal } } // namespace v8::internal

View File

@ -1539,60 +1539,10 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
// Store the subexpression value in the array's elements. // Store the subexpression value in the array's elements.
__ mov(ebx, Operand(esp, 0)); // Copy of array literal. __ mov(ebx, Operand(esp, 0)); // Copy of array literal.
__ mov(edi, FieldOperand(ebx, JSObject::kMapOffset)); __ 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))); __ mov(ecx, Immediate(Smi::FromInt(i)));
__ StoreNumberToDoubleElements(result_register(), __ mov(edx, Immediate(Smi::FromInt(expr->literal_index())));
ebx, StoreArrayLiteralElementStub stub;
ecx, __ CallStub(&stub);
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);
PrepareForBailoutForId(expr->GetIdForElement(i), NO_REGISTERS); PrepareForBailoutForId(expr->GetIdForElement(i), NO_REGISTERS);
} }

View File

@ -4689,6 +4689,44 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_SetNativeFlag) {
} }
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 // Set a local property, even if it is READ_ONLY. If the property does not
// exist, it will be added with attributes NONE. // exist, it will be added with attributes NONE.
RUNTIME_FUNCTION(MaybeObject*, Runtime_IgnoreAttributesAndSetProperty) { RUNTIME_FUNCTION(MaybeObject*, Runtime_IgnoreAttributesAndSetProperty) {

View File

@ -98,6 +98,7 @@ namespace internal {
F(SetNewFunctionAttributes, 1, 1) \ F(SetNewFunctionAttributes, 1, 1) \
F(AllocateInNewSpace, 1, 1) \ F(AllocateInNewSpace, 1, 1) \
F(SetNativeFlag, 1, 1) \ F(SetNativeFlag, 1, 1) \
F(StoreArrayLiteralElement, 5, 1) \
\ \
/* Array join support */ \ /* Array join support */ \
F(PushIfAbsent, 2, 1) \ F(PushIfAbsent, 2, 1) \