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:
parent
669bfc0363
commit
75585d9643
@ -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_
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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) {
|
||||||
|
@ -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) \
|
||||||
|
Loading…
Reference in New Issue
Block a user