Index: src/ia32/code-stubs-ia32.cc |
diff --git a/src/ia32/code-stubs-ia32.cc b/src/ia32/code-stubs-ia32.cc |
index aa533bf836bffd4c551f894eef6b98b420f2bb5a..90d752072344ce80ea952a08ee7405d2a6e1257b 100644 |
--- a/src/ia32/code-stubs-ia32.cc |
+++ b/src/ia32/code-stubs-ia32.cc |
@@ -142,6 +142,28 @@ static void InitializeArrayConstructorDescriptor( |
} |
+static void InitializeInternalArrayConstructorDescriptor( |
+ Isolate* isolate, |
+ CodeStubInterfaceDescriptor* descriptor, |
+ int constant_stack_parameter_count) { |
+ // register state |
+ // eax -- number of arguments |
+ // edi -- constructor function |
+ static Register registers[] = { edi }; |
+ descriptor->register_param_count_ = 1; |
+ |
+ if (constant_stack_parameter_count != 0) { |
+ // stack param count needs (constructor pointer, and single argument) |
+ descriptor->stack_parameter_count_ = &eax; |
+ } |
+ 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) { |
@@ -163,6 +185,27 @@ void ArrayNArgumentsConstructorStub::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); |
+} |
+ |
+ |
void CompareNilICStub::InitializeInterfaceDescriptor( |
Isolate* isolate, |
CodeStubInterfaceDescriptor* descriptor) { |
@@ -4777,7 +4820,11 @@ void CallFunctionStub::Generate(MacroAssembler* masm) { |
__ j(not_equal, &slow); |
if (RecordCallTarget()) { |
- GenerateRecordCallTargetNoArray(masm); |
+ if (FLAG_optimize_constructed_arrays) { |
+ GenerateRecordCallTarget(masm); |
+ } else { |
+ GenerateRecordCallTargetNoArray(masm); |
+ } |
} |
// Fast-case: Just invoke the function. |
@@ -7834,6 +7881,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 ------------- |
// -- eax : argc (only if argument_count_ == ANY) |
@@ -7919,6 +7981,107 @@ void ArrayConstructorStub::Generate(MacroAssembler* masm) { |
} |
+void InternalArrayConstructorStub::GenerateCase( |
+ MacroAssembler* masm, ElementsKind kind) { |
+ Label not_zero_case, not_one_case; |
+ Label normal_sequence; |
+ |
+ __ test(eax, eax); |
+ __ j(not_zero, ¬_zero_case); |
+ InternalArrayNoArgumentConstructorStub stub0(kind); |
+ __ TailCallStub(&stub0); |
+ |
+ __ bind(¬_zero_case); |
+ __ cmp(eax, 1); |
+ __ j(greater, ¬_one_case); |
+ |
+ if (IsFastPackedElementsKind(kind)) { |
+ // We might need to create a holey array |
+ // look at the first argument |
+ __ mov(ecx, Operand(esp, kPointerSize)); |
+ __ test(ecx, ecx); |
+ __ j(zero, &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 ------------- |
+ // -- eax : argc |
+ // -- ebx : type info cell |
+ // -- edi : constructor |
+ // -- esp[0] : return address |
+ // -- esp[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. |
+ __ mov(ecx, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset)); |
+ // Will both indicate a NULL and a Smi. |
+ __ test(ecx, Immediate(kSmiTagMask)); |
+ __ Assert(not_zero, "Unexpected initial map for Array function"); |
+ __ CmpObjectType(ecx, MAP_TYPE, ecx); |
+ __ Assert(equal, "Unexpected initial map for Array function"); |
+ } |
+ |
+ if (FLAG_optimize_constructed_arrays) { |
+ // Figure out the right elements kind |
+ __ mov(ecx, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset)); |
+ |
+ // Load the map's "bit field 2" into |result|. We only need the first byte, |
+ // but the following masking takes care of that anyway. |
+ __ mov(ecx, FieldOperand(ecx, Map::kBitField2Offset)); |
+ // Retrieve elements_kind from bit field 2. |
+ __ and_(ecx, Map::kElementsKindMask); |
+ __ shr(ecx, Map::kElementsKindShift); |
+ |
+ if (FLAG_debug_code) { |
+ Label done; |
+ __ cmp(ecx, Immediate(FAST_ELEMENTS)); |
+ __ j(equal, &done); |
+ __ cmp(ecx, Immediate(FAST_HOLEY_ELEMENTS)); |
+ __ Assert(equal, |
+ "Invalid ElementsKind for InternalArray or InternalPackedArray"); |
+ __ bind(&done); |
+ } |
+ |
+ Label fast_elements_case; |
+ __ cmp(ecx, Immediate(FAST_ELEMENTS)); |
+ __ j(equal, &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, true, &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(); |
+ __ jmp(generic_construct_stub, RelocInfo::CODE_TARGET); |
+ } |
+} |
+ |
+ |
#undef __ |
} } // namespace v8::internal |