// Run the native code for the InternalArray function called as a normal
// function.
- ArrayNativeCode(masm, &generic_array_code);
-
- // Jump to the generic array code if the specialized code cannot handle the
- // construction.
- __ bind(&generic_array_code);
-
- Handle<Code> array_code =
- masm->isolate()->builtins()->InternalArrayCodeGeneric();
- __ Jump(array_code, RelocInfo::CODE_TARGET);
+ if (FLAG_optimize_constructed_arrays) {
+ // tail call a stub
+ InternalArrayConstructorStub stub(masm->isolate());
+ __ TailCallStub(&stub);
+ } else {
+ ArrayNativeCode(masm, &generic_array_code);
+
+ // Jump to the generic array code if the specialized code cannot handle the
+ // construction.
+ __ bind(&generic_array_code);
+ Handle<Code> array_code =
+ masm->isolate()->builtins()->InternalArrayCodeGeneric();
+ __ Jump(array_code, RelocInfo::CODE_TARGET);
+ }
}
}
// Run the native code for the Array function called as a normal function.
- ArrayNativeCode(masm, &generic_array_code);
-
- // Jump to the generic array code if the specialized code cannot handle
- // the construction.
- __ bind(&generic_array_code);
-
- Handle<Code> array_code =
- masm->isolate()->builtins()->ArrayCodeGeneric();
- __ Jump(array_code, RelocInfo::CODE_TARGET);
+ if (FLAG_optimize_constructed_arrays) {
+ // tail call a stub
+ Handle<Object> undefined_sentinel(
+ masm->isolate()->heap()->undefined_value(),
+ masm->isolate());
+ __ mov(r2, Operand(undefined_sentinel));
+ ArrayConstructorStub stub(masm->isolate());
+ __ TailCallStub(&stub);
+ } else {
+ ArrayNativeCode(masm, &generic_array_code);
+
+ // Jump to the generic array code if the specialized code cannot handle
+ // the construction.
+ __ bind(&generic_array_code);
+ Handle<Code> array_code =
+ masm->isolate()->builtins()->ArrayCodeGeneric();
+ __ Jump(array_code, RelocInfo::CODE_TARGET);
+ }
}
}
+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) {
}
+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,
__ b(ne, &slow);
if (RecordCallTarget()) {
- GenerateRecordCallTargetNoArray(masm);
+ if (FLAG_optimize_constructed_arrays) {
+ GenerateRecordCallTarget(masm);
+ } else {
+ GenerateRecordCallTargetNoArray(masm);
+ }
}
// Fast-case: Invoke the function now.
}
+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)
}
+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
factory()->NewJSObject(isolate()->object_function(), TENURED);
SetPrototype(array_function, prototype);
- array_function->shared()->set_construct_stub(
- isolate()->builtins()->builtin(Builtins::kCommonArrayConstructCode));
+ if (FLAG_optimize_constructed_arrays) {
+ InternalArrayConstructorStub internal_array_constructor_stub(isolate());
+ Handle<Code> code = internal_array_constructor_stub.GetCode(isolate());
+ array_function->shared()->set_construct_stub(*code);
+ } else {
+ array_function->shared()->set_construct_stub(
+ isolate()->builtins()->builtin(Builtins::kCommonArrayConstructCode));
+ }
array_function->shared()->DontAdaptArguments();
namespace v8 {
namespace internal {
+// TODO(mvstanton): move these to runtime.h/.cc
DECLARE_RUNTIME_FUNCTION(MaybeObject*, ArrayConstructor_StubFailure);
+DECLARE_RUNTIME_FUNCTION(MaybeObject*, InternalArrayConstructor_StubFailure);
} } // namespace v8::internal
}
-RUNTIME_FUNCTION(MaybeObject*, ArrayConstructor_StubFailure) {
- // If we get 2 arguments then they are the stub parameters (constructor, type
- // info). If we get 3, then the first one is a pointer to the arguments
- // passed by the caller.
- Arguments empty_args(0, NULL);
- bool no_caller_args = args.length() == 2;
- ASSERT(no_caller_args || args.length() == 3);
- int parameters_start = no_caller_args ? 0 : 1;
- Arguments* caller_args = no_caller_args
- ? &empty_args
- : reinterpret_cast<Arguments*>(args[0]);
- Handle<JSFunction> constructor = args.at<JSFunction>(parameters_start);
- Handle<Object> type_info = args.at<Object>(parameters_start + 1);
-
+static MaybeObject* ArrayConstructorStubFailureCommon(
+ Isolate* isolate,
+ Handle<JSFunction> constructor,
+ Handle<Object> type_info,
+ Arguments* caller_args) {
bool holey = false;
if (caller_args->length() == 1 && (*caller_args)[0]->IsSmi()) {
int value = Smi::cast((*caller_args)[0])->value();
JSArray* array;
MaybeObject* maybe_array;
- if (*type_info != isolate->heap()->undefined_value() &&
+ if (!type_info.is_null() &&
+ *type_info != isolate->heap()->undefined_value() &&
JSGlobalPropertyCell::cast(*type_info)->value()->IsSmi()) {
JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(*type_info);
Smi* smi = Smi::cast(cell->value());
*constructor, type_info);
if (!maybe_array->To(&array)) return maybe_array;
} else {
- ElementsKind kind = constructor->initial_map()->elements_kind();
- ASSERT(kind == GetInitialFastElementsKind());
maybe_array = isolate->heap()->AllocateJSObject(*constructor);
if (!maybe_array->To(&array)) return maybe_array;
// We might need to transition to holey
- if (holey) {
+ ElementsKind kind = constructor->initial_map()->elements_kind();
+ if (holey && !IsFastHoleyElementsKind(kind)) {
kind = GetHoleyElementsKind(kind);
maybe_array = array->TransitionElementsKind(kind);
if (maybe_array->IsFailure()) return maybe_array;
}
+RUNTIME_FUNCTION(MaybeObject*, ArrayConstructor_StubFailure) {
+ // If we get 2 arguments then they are the stub parameters (constructor, type
+ // info). If we get 3, then the first one is a pointer to the arguments
+ // passed by the caller.
+ Arguments empty_args(0, NULL);
+ bool no_caller_args = args.length() == 2;
+ ASSERT(no_caller_args || args.length() == 3);
+ int parameters_start = no_caller_args ? 0 : 1;
+ Arguments* caller_args = no_caller_args
+ ? &empty_args
+ : reinterpret_cast<Arguments*>(args[0]);
+ Handle<JSFunction> constructor = args.at<JSFunction>(parameters_start);
+ Handle<Object> type_info = args.at<Object>(parameters_start + 1);
+
+ return ArrayConstructorStubFailureCommon(isolate,
+ constructor,
+ type_info,
+ caller_args);
+}
+
+
+RUNTIME_FUNCTION(MaybeObject*, InternalArrayConstructor_StubFailure) {
+ Arguments empty_args(0, NULL);
+ bool no_caller_args = args.length() == 1;
+ ASSERT(no_caller_args || args.length() == 2);
+ int parameters_start = no_caller_args ? 0 : 1;
+ Arguments* caller_args = no_caller_args
+ ? &empty_args
+ : reinterpret_cast<Arguments*>(args[0]);
+ Handle<JSFunction> constructor = args.at<JSFunction>(parameters_start);
+
+ return ArrayConstructorStubFailureCommon(isolate,
+ constructor,
+ Handle<Object>::null(),
+ caller_args);
+}
+
+
static MaybeObject* ArrayCodeGenericCommon(Arguments* args,
Isolate* isolate,
JSFunction* constructor) {
IfBuilder checker_;
};
+ enum ArgumentClass {
+ NONE,
+ SINGLE,
+ MULTIPLE
+ };
+
+ HValue* BuildArrayConstructor(ElementsKind kind,
+ bool disable_allocation_sites,
+ ArgumentClass argument_class);
+ HValue* BuildInternalArrayConstructor(ElementsKind kind,
+ ArgumentClass argument_class);
+
private:
+ HValue* BuildArraySingleArgumentConstructor(JSArrayBuilder* builder);
+ HValue* BuildArrayNArgumentsConstructor(JSArrayBuilder* builder,
+ ElementsKind kind);
+
SmartArrayPointer<HParameter*> parameters_;
HValue* arguments_length_;
CompilationInfoWithZone info_;
return DoGenerateCode(this);
}
-
-template <>
-HValue* CodeStubGraphBuilder<ArrayNoArgumentConstructorStub>::BuildCodeStub() {
- // ----------- S t a t e -------------
- // -- Parameter 1 : type info cell
- // -- Parameter 0 : constructor
- // -----------------------------------
+HValue* CodeStubGraphBuilderBase::BuildArrayConstructor(
+ ElementsKind kind, bool disable_allocation_sites,
+ ArgumentClass argument_class) {
+ HValue* constructor = GetParameter(ArrayConstructorStubBase::kConstructor);
+ HValue* property_cell = GetParameter(ArrayConstructorStubBase::kPropertyCell);
HInstruction* array_function = BuildGetArrayFunction(context());
- ArrayContextChecker(this,
- GetParameter(ArrayConstructorStubBase::kConstructor),
- array_function);
- // Get the right map
- // Should be a constant
- JSArrayBuilder array_builder(
- this,
- casted_stub()->elements_kind(),
- GetParameter(ArrayConstructorStubBase::kPropertyCell),
- casted_stub()->disable_allocation_sites());
- return array_builder.AllocateEmptyArray();
+
+ ArrayContextChecker(this, constructor, array_function);
+ JSArrayBuilder array_builder(this, kind, property_cell,
+ disable_allocation_sites);
+ HValue* result = NULL;
+ switch (argument_class) {
+ case NONE:
+ result = array_builder.AllocateEmptyArray();
+ break;
+ case SINGLE:
+ result = BuildArraySingleArgumentConstructor(&array_builder);
+ break;
+ case MULTIPLE:
+ result = BuildArrayNArgumentsConstructor(&array_builder, kind);
+ break;
+ }
+ return result;
}
-Handle<Code> ArrayNoArgumentConstructorStub::GenerateCode() {
- return DoGenerateCode(this);
+HValue* CodeStubGraphBuilderBase::BuildInternalArrayConstructor(
+ ElementsKind kind, ArgumentClass argument_class) {
+ HValue* constructor = GetParameter(
+ InternalArrayConstructorStubBase::kConstructor);
+ JSArrayBuilder array_builder(this, kind, constructor);
+
+ HValue* result = NULL;
+ switch (argument_class) {
+ case NONE:
+ result = array_builder.AllocateEmptyArray();
+ break;
+ case SINGLE:
+ result = BuildArraySingleArgumentConstructor(&array_builder);
+ break;
+ case MULTIPLE:
+ result = BuildArrayNArgumentsConstructor(&array_builder, kind);
+ break;
+ }
+ return result;
}
-template <>
-HValue* CodeStubGraphBuilder<ArraySingleArgumentConstructorStub>::
- BuildCodeStub() {
- HInstruction* array_function = BuildGetArrayFunction(context());
- ArrayContextChecker(this,
- GetParameter(ArrayConstructorStubBase::kConstructor),
- array_function);
+HValue* CodeStubGraphBuilderBase::BuildArraySingleArgumentConstructor(
+ JSArrayBuilder* array_builder) {
// Smi check and range check on the input arg.
HValue* constant_one = graph()->GetConstant1();
HValue* constant_zero = graph()->GetConstant0();
// Figure out total size
HValue* length = Pop();
HValue* capacity = Pop();
-
- JSArrayBuilder array_builder(
- this,
- casted_stub()->elements_kind(),
- GetParameter(ArrayConstructorStubBase::kPropertyCell),
- casted_stub()->disable_allocation_sites());
- return array_builder.AllocateArray(capacity, length, true);
-}
-
-
-Handle<Code> ArraySingleArgumentConstructorStub::GenerateCode() {
- return DoGenerateCode(this);
+ return array_builder->AllocateArray(capacity, length, true);
}
-template <>
-HValue* CodeStubGraphBuilder<ArrayNArgumentsConstructorStub>::BuildCodeStub() {
- HInstruction* array_function = BuildGetArrayFunction(context());
- ArrayContextChecker(this,
- GetParameter(ArrayConstructorStubBase::kConstructor),
- array_function);
- ElementsKind kind = casted_stub()->elements_kind();
- HValue* length = GetArgumentsLength();
-
- JSArrayBuilder array_builder(
- this,
- kind,
- GetParameter(ArrayConstructorStubBase::kPropertyCell),
- casted_stub()->disable_allocation_sites());
-
+HValue* CodeStubGraphBuilderBase::BuildArrayNArgumentsConstructor(
+ JSArrayBuilder* array_builder, ElementsKind kind) {
// We need to fill with the hole if it's a smi array in the multi-argument
// case because we might have to bail out while copying arguments into
// the array because they aren't compatible with a smi array.
// If it's a double array, no problem, and if it's fast then no
// problem either because doubles are boxed.
+ HValue* length = GetArgumentsLength();
bool fill_with_hole = IsFastSmiElementsKind(kind);
- HValue* new_object = array_builder.AllocateArray(length,
- length,
- fill_with_hole);
- HValue* elements = array_builder.GetElementsLocation();
+ HValue* new_object = array_builder->AllocateArray(length,
+ length,
+ fill_with_hole);
+ HValue* elements = array_builder->GetElementsLocation();
ASSERT(elements != NULL);
// Now populate the elements correctly.
}
+template <>
+HValue* CodeStubGraphBuilder<ArrayNoArgumentConstructorStub>::BuildCodeStub() {
+ ElementsKind kind = casted_stub()->elements_kind();
+ bool disable_allocation_sites = casted_stub()->disable_allocation_sites();
+ return BuildArrayConstructor(kind, disable_allocation_sites, NONE);
+}
+
+
+Handle<Code> ArrayNoArgumentConstructorStub::GenerateCode() {
+ return DoGenerateCode(this);
+}
+
+
+template <>
+HValue* CodeStubGraphBuilder<ArraySingleArgumentConstructorStub>::
+ BuildCodeStub() {
+ ElementsKind kind = casted_stub()->elements_kind();
+ bool disable_allocation_sites = casted_stub()->disable_allocation_sites();
+ return BuildArrayConstructor(kind, disable_allocation_sites, SINGLE);
+}
+
+
+Handle<Code> ArraySingleArgumentConstructorStub::GenerateCode() {
+ return DoGenerateCode(this);
+}
+
+
+template <>
+HValue* CodeStubGraphBuilder<ArrayNArgumentsConstructorStub>::BuildCodeStub() {
+ ElementsKind kind = casted_stub()->elements_kind();
+ bool disable_allocation_sites = casted_stub()->disable_allocation_sites();
+ return BuildArrayConstructor(kind, disable_allocation_sites, MULTIPLE);
+}
+
+
Handle<Code> ArrayNArgumentsConstructorStub::GenerateCode() {
return DoGenerateCode(this);
}
template <>
+HValue* CodeStubGraphBuilder<InternalArrayNoArgumentConstructorStub>::
+ BuildCodeStub() {
+ ElementsKind kind = casted_stub()->elements_kind();
+ return BuildInternalArrayConstructor(kind, NONE);
+}
+
+
+Handle<Code> InternalArrayNoArgumentConstructorStub::GenerateCode() {
+ return DoGenerateCode(this);
+}
+
+
+template <>
+HValue* CodeStubGraphBuilder<InternalArraySingleArgumentConstructorStub>::
+ BuildCodeStub() {
+ ElementsKind kind = casted_stub()->elements_kind();
+ return BuildInternalArrayConstructor(kind, SINGLE);
+}
+
+
+Handle<Code> InternalArraySingleArgumentConstructorStub::GenerateCode() {
+ return DoGenerateCode(this);
+}
+
+
+template <>
+HValue* CodeStubGraphBuilder<InternalArrayNArgumentsConstructorStub>::
+ BuildCodeStub() {
+ ElementsKind kind = casted_stub()->elements_kind();
+ return BuildInternalArrayConstructor(kind, MULTIPLE);
+}
+
+
+Handle<Code> InternalArrayNArgumentsConstructorStub::GenerateCode() {
+ return DoGenerateCode(this);
+}
+
+
+template <>
HValue* CodeStubGraphBuilder<CompareNilICStub>::BuildCodeInitializedStub() {
CompareNilICStub* stub = casted_stub();
HIfContinuation continuation;
}
+void InternalArrayConstructorStubBase::InstallDescriptors(Isolate* isolate) {
+ InternalArrayNoArgumentConstructorStub stub1(FAST_ELEMENTS);
+ InstallDescriptor(isolate, &stub1);
+ InternalArraySingleArgumentConstructorStub stub2(FAST_ELEMENTS);
+ InstallDescriptor(isolate, &stub2);
+ InternalArrayNArgumentsConstructorStub stub3(FAST_ELEMENTS);
+ InstallDescriptor(isolate, &stub3);
+}
+
+InternalArrayConstructorStub::InternalArrayConstructorStub(
+ Isolate* isolate) {
+ InternalArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
+}
+
+
} } // namespace v8::internal
V(ArrayNoArgumentConstructor) \
V(ArraySingleArgumentConstructor) \
V(ArrayNArgumentsConstructor) \
+ V(InternalArrayNoArgumentConstructor) \
+ V(InternalArraySingleArgumentConstructor) \
+ V(InternalArrayNArgumentsConstructor) \
V(KeyedStoreElement) \
V(DebuggerStatement) \
V(NameDictionaryLookup) \
V(StoreArrayLiteralElement) \
V(StubFailureTrampoline) \
V(ArrayConstructor) \
+ V(InternalArrayConstructor) \
V(ProfileEntryHook) \
/* IC Handler stubs */ \
V(LoadField) \
};
+class InternalArrayConstructorStub: public PlatformCodeStub {
+ public:
+ explicit InternalArrayConstructorStub(Isolate* isolate);
+
+ void Generate(MacroAssembler* masm);
+
+ private:
+ virtual CodeStub::Major MajorKey() { return InternalArrayConstructor; }
+ virtual int MinorKey() { return 0; }
+
+ void GenerateCase(MacroAssembler* masm, ElementsKind kind);
+};
+
+
class MathPowStub: public PlatformCodeStub {
public:
enum ExponentType { INTEGER, DOUBLE, TAGGED, ON_STACK };
};
+class InternalArrayConstructorStubBase : public HydrogenCodeStub {
+ public:
+ explicit InternalArrayConstructorStubBase(ElementsKind kind) {
+ kind_ = kind;
+ }
+
+ virtual bool IsPregenerated() { return true; }
+ static void GenerateStubsAheadOfTime(Isolate* isolate);
+ static void InstallDescriptors(Isolate* isolate);
+
+ // Parameters accessed via CodeStubGraphBuilder::GetParameter()
+ static const int kConstructor = 0;
+
+ ElementsKind elements_kind() const { return kind_; }
+
+ private:
+ int NotMissMinorKey() { return kind_; }
+
+ ElementsKind kind_;
+
+ DISALLOW_COPY_AND_ASSIGN(InternalArrayConstructorStubBase);
+};
+
+
+class InternalArrayNoArgumentConstructorStub : public
+ InternalArrayConstructorStubBase {
+ public:
+ explicit InternalArrayNoArgumentConstructorStub(ElementsKind kind)
+ : InternalArrayConstructorStubBase(kind) { }
+
+ virtual Handle<Code> GenerateCode();
+
+ virtual void InitializeInterfaceDescriptor(
+ Isolate* isolate,
+ CodeStubInterfaceDescriptor* descriptor);
+
+ private:
+ Major MajorKey() { return InternalArrayNoArgumentConstructor; }
+
+ DISALLOW_COPY_AND_ASSIGN(InternalArrayNoArgumentConstructorStub);
+};
+
+
+class InternalArraySingleArgumentConstructorStub : public
+ InternalArrayConstructorStubBase {
+ public:
+ explicit InternalArraySingleArgumentConstructorStub(ElementsKind kind)
+ : InternalArrayConstructorStubBase(kind) { }
+
+ virtual Handle<Code> GenerateCode();
+
+ virtual void InitializeInterfaceDescriptor(
+ Isolate* isolate,
+ CodeStubInterfaceDescriptor* descriptor);
+
+ private:
+ Major MajorKey() { return InternalArraySingleArgumentConstructor; }
+
+ DISALLOW_COPY_AND_ASSIGN(InternalArraySingleArgumentConstructorStub);
+};
+
+
+class InternalArrayNArgumentsConstructorStub : public
+ InternalArrayConstructorStubBase {
+ public:
+ explicit InternalArrayNArgumentsConstructorStub(ElementsKind kind)
+ : InternalArrayConstructorStubBase(kind) { }
+
+ virtual Handle<Code> GenerateCode();
+
+ virtual void InitializeInterfaceDescriptor(
+ Isolate* isolate,
+ CodeStubInterfaceDescriptor* descriptor);
+
+ private:
+ Major MajorKey() { return InternalArrayNArgumentsConstructor; }
+
+ DISALLOW_COPY_AND_ASSIGN(InternalArrayNArgumentsConstructorStub);
+};
+
+
class KeyedStoreElementStub : public PlatformCodeStub {
public:
KeyedStoreElementStub(bool is_js_array,
return HObjectAccess(kInobject, JSObject::kPropertiesOffset);
}
+ static HObjectAccess ForPrototypeOrInitialMap() {
+ return HObjectAccess(kInobject, JSFunction::kPrototypeOrInitialMapOffset);
+ }
+
static HObjectAccess ForMap() {
return HObjectAccess(kMaps, JSObject::kMapOffset);
}
bool disable_allocation_sites) :
builder_(builder),
kind_(kind),
- allocation_site_payload_(allocation_site_payload) {
+ allocation_site_payload_(allocation_site_payload),
+ constructor_function_(NULL) {
mode_ = disable_allocation_sites
? DONT_TRACK_ALLOCATION_SITE
: AllocationSiteInfo::GetMode(kind);
}
+HGraphBuilder::JSArrayBuilder::JSArrayBuilder(HGraphBuilder* builder,
+ ElementsKind kind,
+ HValue* constructor_function) :
+ builder_(builder),
+ kind_(kind),
+ mode_(DONT_TRACK_ALLOCATION_SITE),
+ allocation_site_payload_(NULL),
+ constructor_function_(constructor_function) {
+}
+
+
HValue* HGraphBuilder::JSArrayBuilder::EmitMapCode(HValue* context) {
HInstruction* native_context = builder()->BuildGetNativeContext(context);
}
+HValue* HGraphBuilder::JSArrayBuilder::EmitInternalMapCode() {
+ // Find the map near the constructor function
+ HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap();
+ return AddInstruction(
+ builder()->BuildLoadNamedField(constructor_function_,
+ access,
+ Representation::Tagged()));
+}
+
+
HValue* HGraphBuilder::JSArrayBuilder::EstablishAllocationSize(
HValue* length_node) {
HValue* context = builder()->environment()->LookupContext();
AddInstruction(new_object);
// Fill in the fields: map, properties, length
- HValue* map = EmitMapCode(context);
+ HValue* map;
+ if (constructor_function_ != NULL) {
+ map = EmitInternalMapCode();
+ } else {
+ map = EmitMapCode(context);
+ }
elements_location_ = builder()->BuildJSArrayHeader(new_object,
map,
mode_,
HValue* allocation_site_payload,
bool disable_allocation_sites);
+ JSArrayBuilder(HGraphBuilder* builder,
+ ElementsKind kind,
+ HValue* constructor_function);
+
HValue* AllocateEmptyArray();
HValue* AllocateArray(HValue* capacity, HValue* length_field,
bool fill_with_hole);
}
HValue* EmitMapCode(HValue* context);
+ HValue* EmitInternalMapCode();
HValue* EstablishEmptyArrayAllocationSize();
HValue* EstablishAllocationSize(HValue* length_node);
HValue* AllocateArray(HValue* size_in_bytes, HValue* capacity,
ElementsKind kind_;
AllocationSiteMode mode_;
HValue* allocation_site_payload_;
+ HValue* constructor_function_;
HInnerAllocatedObject* elements_location_;
};
// Run the native code for the InternalArray function called as a normal
// function.
- ArrayNativeCode(masm, false, &generic_array_code);
-
- // Jump to the generic internal array code in case the specialized code cannot
- // handle the construction.
- __ bind(&generic_array_code);
- Handle<Code> array_code =
- masm->isolate()->builtins()->InternalArrayCodeGeneric();
- __ jmp(array_code, RelocInfo::CODE_TARGET);
+ if (FLAG_optimize_constructed_arrays) {
+ // tail call a stub
+ InternalArrayConstructorStub stub(masm->isolate());
+ __ TailCallStub(&stub);
+ } else {
+ ArrayNativeCode(masm, false, &generic_array_code);
+
+ // Jump to the generic internal array code in case the specialized code
+ // cannot handle the construction.
+ __ bind(&generic_array_code);
+ Handle<Code> array_code =
+ masm->isolate()->builtins()->InternalArrayCodeGeneric();
+ __ jmp(array_code, RelocInfo::CODE_TARGET);
+ }
}
}
// Run the native code for the Array function called as a normal function.
- ArrayNativeCode(masm, false, &generic_array_code);
-
- // Jump to the generic array code in case the specialized code cannot handle
- // the construction.
- __ bind(&generic_array_code);
- Handle<Code> array_code =
- masm->isolate()->builtins()->ArrayCodeGeneric();
- __ jmp(array_code, RelocInfo::CODE_TARGET);
+ if (FLAG_optimize_constructed_arrays) {
+ // tail call a stub
+ Handle<Object> undefined_sentinel(
+ masm->isolate()->heap()->undefined_value(),
+ masm->isolate());
+ __ mov(ebx, Immediate(undefined_sentinel));
+ ArrayConstructorStub stub(masm->isolate());
+ __ TailCallStub(&stub);
+ } else {
+ ArrayNativeCode(masm, false, &generic_array_code);
+
+ // Jump to the generic internal array code in case the specialized code
+ // cannot handle the construction.
+ __ bind(&generic_array_code);
+ Handle<Code> array_code =
+ masm->isolate()->builtins()->ArrayCodeGeneric();
+ __ jmp(array_code, RelocInfo::CODE_TARGET);
+ }
}
}
+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) {
}
+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) {
__ j(not_equal, &slow);
if (RecordCallTarget()) {
- GenerateRecordCallTargetNoArray(masm);
+ if (FLAG_optimize_constructed_arrays) {
+ GenerateRecordCallTarget(masm);
+ } else {
+ GenerateRecordCallTargetNoArray(masm);
+ }
}
// Fast-case: Just invoke the function.
}
+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)
}
+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
CompareNilICStub::InitializeForIsolate(this);
ToBooleanStub::InitializeForIsolate(this);
ArrayConstructorStubBase::InstallDescriptors(this);
+ InternalArrayConstructorStubBase::InstallDescriptors(this);
}
if (FLAG_parallel_recompilation) optimizing_compiler_thread_.Start();
__ Branch(&slow, ne, a3, Operand(JS_FUNCTION_TYPE));
if (RecordCallTarget()) {
- GenerateRecordCallTargetNoArray(masm);
+ if (FLAG_optimize_constructed_arrays) {
+ GenerateRecordCallTarget(masm);
+ } else {
+ GenerateRecordCallTargetNoArray(masm);
+ }
}
// Fast-case: Invoke the function now.
bool TypeFeedbackOracle::CallNewIsMonomorphic(CallNew* expr) {
Handle<Object> info = GetInfo(expr->CallNewFeedbackId());
- if (info->IsSmi()) {
- ASSERT(static_cast<ElementsKind>(Smi::cast(*info)->value()) <=
- LAST_FAST_ELEMENTS_KIND);
- return isolate_->global_context()->array_function();
- }
- return info->IsJSFunction();
+ return info->IsSmi() || info->IsJSFunction();
}
Handle<JSFunction> TypeFeedbackOracle::GetCallTarget(Call* expr) {
- return Handle<JSFunction>::cast(GetInfo(expr->CallFeedbackId()));
+ Handle<Object> info = GetInfo(expr->CallFeedbackId());
+ if (info->IsSmi()) {
+ ASSERT(static_cast<ElementsKind>(Smi::cast(*info)->value()) <=
+ LAST_FAST_ELEMENTS_KIND);
+ return Handle<JSFunction>(isolate_->global_context()->array_function());
+ } else {
+ return Handle<JSFunction>::cast(info);
+ }
}
// Run the native code for the InternalArray function called as a normal
// function.
- ArrayNativeCode(masm, &generic_array_code);
-
- // Jump to the generic array code in case the specialized code cannot handle
- // the construction.
- __ bind(&generic_array_code);
- Handle<Code> array_code =
- masm->isolate()->builtins()->InternalArrayCodeGeneric();
- __ Jump(array_code, RelocInfo::CODE_TARGET);
+ if (FLAG_optimize_constructed_arrays) {
+ // tail call a stub
+ InternalArrayConstructorStub stub(masm->isolate());
+ __ TailCallStub(&stub);
+ } else {
+ ArrayNativeCode(masm, &generic_array_code);
+
+ // Jump to the generic array code in case the specialized code cannot handle
+ // the construction.
+ __ bind(&generic_array_code);
+ Handle<Code> array_code =
+ masm->isolate()->builtins()->InternalArrayCodeGeneric();
+ __ Jump(array_code, RelocInfo::CODE_TARGET);
+ }
}
}
// Run the native code for the Array function called as a normal function.
- ArrayNativeCode(masm, &generic_array_code);
-
- // Jump to the generic array code in case the specialized code cannot handle
- // the construction.
- __ bind(&generic_array_code);
- Handle<Code> array_code =
- masm->isolate()->builtins()->ArrayCodeGeneric();
- __ Jump(array_code, RelocInfo::CODE_TARGET);
+ if (FLAG_optimize_constructed_arrays) {
+ // tail call a stub
+ Handle<Object> undefined_sentinel(
+ masm->isolate()->heap()->undefined_value(),
+ masm->isolate());
+ __ Move(rbx, undefined_sentinel);
+ ArrayConstructorStub stub(masm->isolate());
+ __ TailCallStub(&stub);
+ } else {
+ ArrayNativeCode(masm, &generic_array_code);
+
+ // Jump to the generic array code in case the specialized code cannot handle
+ // the construction.
+ __ bind(&generic_array_code);
+ Handle<Code> array_code =
+ masm->isolate()->builtins()->ArrayCodeGeneric();
+ __ Jump(array_code, RelocInfo::CODE_TARGET);
+ }
}
}
+static void InitializeInternalArrayConstructorDescriptor(
+ Isolate* isolate,
+ CodeStubInterfaceDescriptor* descriptor,
+ int constant_stack_parameter_count) {
+ // register state
+ // rax -- number of arguments
+ // rdi -- constructor function
+ static Register registers[] = { rdi };
+ descriptor->register_param_count_ = 1;
+
+ if (constant_stack_parameter_count != 0) {
+ // stack param count needs (constructor pointer, and single argument)
+ descriptor->stack_parameter_count_ = &rax;
+ }
+ 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) {
}
+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) {
__ j(not_equal, &slow);
if (RecordCallTarget()) {
- GenerateRecordCallTargetNoArray(masm);
+ if (FLAG_optimize_constructed_arrays) {
+ GenerateRecordCallTarget(masm);
+ } else {
+ GenerateRecordCallTargetNoArray(masm);
+ }
}
// Fast-case: Just invoke the function.
}
+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 -------------
}
+void InternalArrayConstructorStub::GenerateCase(
+ MacroAssembler* masm, ElementsKind kind) {
+ Label not_zero_case, not_one_case;
+ Label normal_sequence;
+
+ __ testq(rax, rax);
+ __ j(not_zero, ¬_zero_case);
+ InternalArrayNoArgumentConstructorStub stub0(kind);
+ __ TailCallStub(&stub0);
+
+ __ bind(¬_zero_case);
+ __ cmpl(rax, Immediate(1));
+ __ j(greater, ¬_one_case);
+
+ if (IsFastPackedElementsKind(kind)) {
+ // We might need to create a holey array
+ // look at the first argument
+ __ movq(rcx, Operand(rsp, kPointerSize));
+ __ testq(rcx, rcx);
+ __ 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.
+ __ movq(rcx, FieldOperand(rdi, JSFunction::kPrototypeOrInitialMapOffset));
+ // Will both indicate a NULL and a Smi.
+ STATIC_ASSERT(kSmiTag == 0);
+ Condition not_smi = NegateCondition(masm->CheckSmi(rcx));
+ __ Check(not_smi, "Unexpected initial map for Array function");
+ __ CmpObjectType(rcx, MAP_TYPE, rcx);
+ __ Check(equal, "Unexpected initial map for Array function");
+ }
+
+ if (FLAG_optimize_constructed_arrays) {
+ // Figure out the right elements kind
+ __ movq(rcx, FieldOperand(rdi, 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.
+ __ movzxbq(rcx, FieldOperand(rcx, Map::kBitField2Offset));
+ // Retrieve elements_kind from bit field 2.
+ __ and_(rcx, Immediate(Map::kElementsKindMask));
+ __ shr(rcx, Immediate(Map::kElementsKindShift));
+
+ if (FLAG_debug_code) {
+ Label done;
+ __ cmpl(rcx, Immediate(FAST_ELEMENTS));
+ __ j(equal, &done);
+ __ cmpl(rcx, Immediate(FAST_HOLEY_ELEMENTS));
+ __ Assert(equal,
+ "Invalid ElementsKind for InternalArray or InternalPackedArray");
+ __ bind(&done);
+ }
+
+ Label fast_elements_case;
+ __ cmpl(rcx, 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, &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