Index: src/arm/code-stubs-arm.cc |
diff --git a/src/arm/code-stubs-arm.cc b/src/arm/code-stubs-arm.cc |
index 62fcc9a981ccd5946ed7946d006d7e6d5224d4d1..a3701037b9cb29749a5ddd320d94905c4319051d 100644 |
--- a/src/arm/code-stubs-arm.cc |
+++ b/src/arm/code-stubs-arm.cc |
@@ -61,6 +61,40 @@ void TransitionElementsKindStub::InitializeInterfaceDescriptor( |
} |
+static void InitializeArrayConstructorDescriptor(Isolate* isolate, |
+ CodeStubInterfaceDescriptor* descriptor) { |
+ static Register registers[] = { r1, r2 }; |
+ descriptor->register_param_count_ = 2; |
+ // stack param count needs (constructor pointer, and single argument) |
+ descriptor->stack_parameter_count_ = &r0; |
+ descriptor->register_params_ = registers; |
+ descriptor->extra_expression_stack_count_ = 1; |
+ descriptor->deoptimization_handler_ = |
+ FUNCTION_ADDR(ArrayConstructor_StubFailure); |
+} |
+ |
+ |
+void ArrayNoArgumentConstructorStub::InitializeInterfaceDescriptor( |
+ Isolate* isolate, |
+ CodeStubInterfaceDescriptor* descriptor) { |
+ InitializeArrayConstructorDescriptor(isolate, descriptor); |
+} |
+ |
+ |
+void ArraySingleArgumentConstructorStub::InitializeInterfaceDescriptor( |
+ Isolate* isolate, |
+ CodeStubInterfaceDescriptor* descriptor) { |
+ InitializeArrayConstructorDescriptor(isolate, descriptor); |
+} |
+ |
+ |
+void ArrayNArgumentsConstructorStub::InitializeInterfaceDescriptor( |
+ Isolate* isolate, |
+ CodeStubInterfaceDescriptor* descriptor) { |
+ InitializeArrayConstructorDescriptor(isolate, descriptor); |
+} |
+ |
+ |
#define __ ACCESS_MASM(masm) |
static void EmitIdenticalObjectComparison(MacroAssembler* masm, |
@@ -5581,7 +5615,7 @@ static void GenerateRecordCallTarget(MacroAssembler* masm) { |
// megamorphic. |
// r1 : the function to call |
// r2 : cache cell for call target |
- Label done; |
+ Label initialize, done, miss, megamorphic, not_array_function; |
ASSERT_EQ(*TypeFeedbackCells::MegamorphicSentinel(masm->isolate()), |
masm->isolate()->heap()->undefined_value()); |
@@ -5598,16 +5632,62 @@ static void GenerateRecordCallTarget(MacroAssembler* masm) { |
__ CompareRoot(r3, Heap::kUndefinedValueRootIndex); |
__ b(eq, &done); |
+ // Special handling of the Array() function, which caches not only the |
+ // monomorphic Array function but the initial ElementsKind with special |
+ // sentinels |
+ Handle<Object> terminal_kind_sentinel = |
+ TypeFeedbackCells::MonomorphicArraySentinel(LAST_FAST_ELEMENTS_KIND); |
+ __ cmp(r3, Operand(terminal_kind_sentinel)); |
+ __ b(ne, &miss); |
+ // Load the global or builtins object from the current context |
+ __ ldr(r3, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); |
+ __ ldr(r3, FieldMemOperand(r3, GlobalObject::kGlobalContextOffset)); |
+ // Make sure the function is the Array() function |
+ __ ldr(r3, |
+ MemOperand(r3, Context::SlotOffset(Context::ARRAY_FUNCTION_INDEX))); |
+ __ cmp(r1, r3); |
+ Label megamorphic_pre; |
+ __ b(ne, &megamorphic_pre); |
+ __ jmp(&done); |
+ |
+ __ bind(&megamorphic_pre); |
+ __ jmp(&megamorphic); |
+ |
+ __ bind(&miss); |
+ |
// A monomorphic miss (i.e, here the cache is not uninitialized) goes |
// megamorphic. |
__ CompareRoot(r3, Heap::kTheHoleValueRootIndex); |
+ __ b(eq, &initialize); |
// MegamorphicSentinel is an immortal immovable object (undefined) so no |
// write-barrier is needed. |
- __ LoadRoot(ip, Heap::kUndefinedValueRootIndex, ne); |
- __ str(ip, FieldMemOperand(r2, JSGlobalPropertyCell::kValueOffset), ne); |
+ __ bind(&megamorphic); |
+ __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); |
+ __ str(ip, FieldMemOperand(r2, JSGlobalPropertyCell::kValueOffset)); |
+ |
+ // An uninitialized cache is patched with the function or sentinel to |
+ // indicate the ElementsKind if function is the Array constructor. |
+ __ bind(&initialize); |
+ __ ldr(r3, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); |
+ __ ldr(r3, FieldMemOperand(r3, GlobalObject::kGlobalContextOffset)); |
+ __ ldr(r3, |
+ MemOperand(r3, Context::SlotOffset(Context::ARRAY_FUNCTION_INDEX))); |
+ // Make sure the function is the Array() function |
+ __ cmp(r1, r3); |
+ __ b(ne, ¬_array_function); |
+ |
+ // The target function is the Array constructor, install a sentinel value in |
+ // the constructor's type info cell that will track the initial ElementsKind |
+ // that should be used for the array when its constructed. |
+ Handle<Object> initial_kind_sentinel = |
+ TypeFeedbackCells::MonomorphicArraySentinel( |
+ GetInitialFastElementsKind()); |
+ __ mov(r3, Operand(initial_kind_sentinel)); |
+ __ str(r3, FieldMemOperand(r2, JSGlobalPropertyCell::kValueOffset)); |
+ __ b(&done); |
- // An uninitialized cache is patched with the function. |
- __ str(r1, FieldMemOperand(r2, JSGlobalPropertyCell::kValueOffset), eq); |
+ __ bind(¬_array_function); |
+ __ str(r1, FieldMemOperand(r2, JSGlobalPropertyCell::kValueOffset)); |
// No need for a write barrier here - cells are rescanned. |
__ bind(&done); |
@@ -5725,9 +5805,9 @@ void CallConstructStub::Generate(MacroAssembler* masm) { |
} |
// Jump to the function-specific construct stub. |
- __ ldr(r2, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); |
- __ ldr(r2, FieldMemOperand(r2, SharedFunctionInfo::kConstructStubOffset)); |
- __ add(pc, r2, Operand(Code::kHeaderSize - kHeapObjectTag)); |
+ __ ldr(r3, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); |
+ __ ldr(r3, FieldMemOperand(r3, SharedFunctionInfo::kConstructStubOffset)); |
+ __ add(pc, r3, Operand(Code::kHeaderSize - kHeapObjectTag)); |
// r0: number of arguments |
// r1: called object |