Index: src/arm/code-stubs-arm.cc |
diff --git a/src/arm/code-stubs-arm.cc b/src/arm/code-stubs-arm.cc |
index c15ecb245e5e24d4aca82ca9fe4ee91b91db4909..e80316985d49da454a8a2a67da3b7d84d53ffb2c 100644 |
--- a/src/arm/code-stubs-arm.cc |
+++ b/src/arm/code-stubs-arm.cc |
@@ -150,6 +150,28 @@ static void InitializeArrayConstructorDescriptor( |
} |
+static void InitializeInternalArrayConstructorDescriptor( |
+ Isolate* isolate, |
+ CodeStubInterfaceDescriptor* descriptor, |
+ int constant_stack_parameter_count) { |
+ // register state |
+ // r0 -- number of arguments |
+ // r1 -- constructor function |
+ static Register registers[] = { r1 }; |
+ descriptor->register_param_count_ = 1; |
+ |
+ if (constant_stack_parameter_count != 0) { |
+ // stack param count needs (constructor pointer, and single argument) |
+ descriptor->stack_parameter_count_ = &r0; |
+ } |
+ descriptor->hint_stack_parameter_count_ = constant_stack_parameter_count; |
+ descriptor->register_params_ = registers; |
+ descriptor->function_mode_ = JS_FUNCTION_STUB_MODE; |
+ descriptor->deoptimization_handler_ = |
+ FUNCTION_ADDR(InternalArrayConstructor_StubFailure); |
+} |
+ |
+ |
void ArrayNoArgumentConstructorStub::InitializeInterfaceDescriptor( |
Isolate* isolate, |
CodeStubInterfaceDescriptor* descriptor) { |
@@ -184,6 +206,27 @@ void ToBooleanStub::InitializeInterfaceDescriptor( |
} |
+void InternalArrayNoArgumentConstructorStub::InitializeInterfaceDescriptor( |
+ Isolate* isolate, |
+ CodeStubInterfaceDescriptor* descriptor) { |
+ InitializeInternalArrayConstructorDescriptor(isolate, descriptor, 0); |
+} |
+ |
+ |
+void InternalArraySingleArgumentConstructorStub::InitializeInterfaceDescriptor( |
+ Isolate* isolate, |
+ CodeStubInterfaceDescriptor* descriptor) { |
+ InitializeInternalArrayConstructorDescriptor(isolate, descriptor, 1); |
+} |
+ |
+ |
+void InternalArrayNArgumentsConstructorStub::InitializeInterfaceDescriptor( |
+ Isolate* isolate, |
+ CodeStubInterfaceDescriptor* descriptor) { |
+ InitializeInternalArrayConstructorDescriptor(isolate, descriptor, -1); |
+} |
+ |
+ |
#define __ ACCESS_MASM(masm) |
static void EmitIdenticalObjectComparison(MacroAssembler* masm, |
@@ -4731,7 +4774,11 @@ void CallFunctionStub::Generate(MacroAssembler* masm) { |
__ b(ne, &slow); |
if (RecordCallTarget()) { |
- GenerateRecordCallTargetNoArray(masm); |
+ if (FLAG_optimize_constructed_arrays) { |
+ GenerateRecordCallTarget(masm); |
+ } else { |
+ GenerateRecordCallTargetNoArray(masm); |
+ } |
} |
// Fast-case: Invoke the function now. |
@@ -7244,6 +7291,21 @@ void ArrayConstructorStubBase::GenerateStubsAheadOfTime(Isolate* isolate) { |
} |
+void InternalArrayConstructorStubBase::GenerateStubsAheadOfTime( |
+ Isolate* isolate) { |
+ ElementsKind kinds[2] = { FAST_ELEMENTS, FAST_HOLEY_ELEMENTS }; |
+ for (int i = 0; i < 2; i++) { |
+ // For internal arrays we only need a few things |
+ InternalArrayNoArgumentConstructorStub stubh1(kinds[i]); |
+ stubh1.GetCode(isolate)->set_is_pregenerated(true); |
+ InternalArraySingleArgumentConstructorStub stubh2(kinds[i]); |
+ stubh2.GetCode(isolate)->set_is_pregenerated(true); |
+ InternalArrayNArgumentsConstructorStub stubh3(kinds[i]); |
+ stubh3.GetCode(isolate)->set_is_pregenerated(true); |
+ } |
+} |
+ |
+ |
void ArrayConstructorStub::Generate(MacroAssembler* masm) { |
// ----------- S t a t e ------------- |
// -- r0 : argc (only if argument_count_ == ANY) |
@@ -7330,6 +7392,105 @@ void ArrayConstructorStub::Generate(MacroAssembler* masm) { |
} |
+void InternalArrayConstructorStub::GenerateCase( |
+ MacroAssembler* masm, ElementsKind kind) { |
+ Label not_zero_case, not_one_case; |
+ Label normal_sequence; |
+ |
+ __ tst(r0, r0); |
+ __ b(ne, ¬_zero_case); |
+ InternalArrayNoArgumentConstructorStub stub0(kind); |
+ __ TailCallStub(&stub0); |
+ |
+ __ bind(¬_zero_case); |
+ __ cmp(r0, Operand(1)); |
+ __ b(gt, ¬_one_case); |
+ |
+ if (IsFastPackedElementsKind(kind)) { |
+ // We might need to create a holey array |
+ // look at the first argument |
+ __ ldr(r3, MemOperand(sp, 0)); |
+ __ cmp(r3, Operand::Zero()); |
+ __ b(eq, &normal_sequence); |
+ |
+ InternalArraySingleArgumentConstructorStub |
+ stub1_holey(GetHoleyElementsKind(kind)); |
+ __ TailCallStub(&stub1_holey); |
+ } |
+ |
+ __ bind(&normal_sequence); |
+ InternalArraySingleArgumentConstructorStub stub1(kind); |
+ __ TailCallStub(&stub1); |
+ |
+ __ bind(¬_one_case); |
+ InternalArrayNArgumentsConstructorStub stubN(kind); |
+ __ TailCallStub(&stubN); |
+} |
+ |
+ |
+void InternalArrayConstructorStub::Generate(MacroAssembler* masm) { |
+ // ----------- S t a t e ------------- |
+ // -- r0 : argc |
+ // -- r1 : constructor |
+ // -- sp[0] : return address |
+ // -- sp[4] : last argument |
+ // ----------------------------------- |
+ |
+ if (FLAG_debug_code) { |
+ // The array construct code is only set for the global and natives |
+ // builtin Array functions which always have maps. |
+ |
+ // Initial map for the builtin Array function should be a map. |
+ __ ldr(r3, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset)); |
+ // Will both indicate a NULL and a Smi. |
+ __ tst(r3, Operand(kSmiTagMask)); |
+ __ Assert(ne, "Unexpected initial map for Array function"); |
+ __ CompareObjectType(r3, r3, r4, MAP_TYPE); |
+ __ Assert(eq, "Unexpected initial map for Array function"); |
+ } |
+ |
+ if (FLAG_optimize_constructed_arrays) { |
+ // Figure out the right elements kind |
+ __ ldr(r3, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset)); |
+ |
+ // Load the map's "bit field 2" into |result|. We only need the first byte, |
+ // but the following bit field extraction takes care of that anyway. |
+ __ ldr(r3, FieldMemOperand(r3, Map::kBitField2Offset)); |
+ // Retrieve elements_kind from bit field 2. |
+ __ ubfx(r3, r3, Map::kElementsKindShift, Map::kElementsKindBitCount); |
+ |
+ if (FLAG_debug_code) { |
+ Label done; |
+ __ cmp(r3, Operand(FAST_ELEMENTS)); |
+ __ b(eq, &done); |
+ __ cmp(r3, Operand(FAST_HOLEY_ELEMENTS)); |
+ __ Assert(eq, |
+ "Invalid ElementsKind for InternalArray or InternalPackedArray"); |
+ __ bind(&done); |
+ } |
+ |
+ Label fast_elements_case; |
+ __ cmp(r3, Operand(FAST_ELEMENTS)); |
+ __ b(eq, &fast_elements_case); |
+ GenerateCase(masm, FAST_HOLEY_ELEMENTS); |
+ |
+ __ bind(&fast_elements_case); |
+ GenerateCase(masm, FAST_ELEMENTS); |
+ } else { |
+ Label generic_constructor; |
+ // Run the native code for the Array function called as constructor. |
+ ArrayNativeCode(masm, &generic_constructor); |
+ |
+ // Jump to the generic construct code in case the specialized code cannot |
+ // handle the construction. |
+ __ bind(&generic_constructor); |
+ Handle<Code> generic_construct_stub = |
+ masm->isolate()->builtins()->JSConstructStubGeneric(); |
+ __ Jump(generic_construct_stub, RelocInfo::CODE_TARGET); |
+ } |
+} |
+ |
+ |
#undef __ |
} } // namespace v8::internal |