Commit 896468fe authored by palfia@homejinni.com's avatar palfia@homejinni.com

MIPS: Constructed arrays can be created with Hydrogen code stubs. The feature...

MIPS: Constructed arrays can be created with Hydrogen code stubs. The feature is still off by default (--optimize-constructed-arrays).

Port r14441 (0c30d023)

BUG=

Review URL: https://codereview.chromium.org/13905009

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@14443 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 7b2abd7c
......@@ -317,8 +317,7 @@ static void AllocateJSArray(MacroAssembler* masm,
// entering the generic code. In both cases argc in a0 needs to be preserved.
// Both registers are preserved by this code so no need to differentiate between
// construct call and normal call.
static void ArrayNativeCode(MacroAssembler* masm,
Label* call_generic_code) {
void ArrayNativeCode(MacroAssembler* masm, Label* call_generic_code) {
Counters* counters = masm->isolate()->counters();
Label argc_one_or_more, argc_two_or_more, not_empty_array, empty_array,
has_non_smi_element, finish, cant_transition_map, not_double;
......@@ -546,7 +545,7 @@ void Builtins::Generate_ArrayCode(MacroAssembler* masm) {
}
void Builtins::Generate_ArrayConstructCode(MacroAssembler* masm) {
void Builtins::Generate_CommonArrayConstructCode(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- a0 : number of arguments
// -- a1 : constructor function
......@@ -566,48 +565,17 @@ void Builtins::Generate_ArrayConstructCode(MacroAssembler* masm) {
__ GetObjectType(a3, a3, t0);
__ Assert(eq, "Unexpected initial map for Array function (4)",
t0, Operand(MAP_TYPE));
if (FLAG_optimize_constructed_arrays) {
// We should either have undefined in a2 or a valid jsglobalpropertycell
Label okay_here;
Handle<Object> undefined_sentinel(
masm->isolate()->heap()->undefined_value(), masm->isolate());
Handle<Map> global_property_cell_map(
masm->isolate()->heap()->global_property_cell_map());
__ Branch(&okay_here, eq, a2, Operand(undefined_sentinel));
__ lw(a3, FieldMemOperand(a2, 0));
__ Assert(eq, "Expected property cell in register a3",
a3, Operand(global_property_cell_map));
__ bind(&okay_here);
}
}
if (FLAG_optimize_constructed_arrays) {
Label not_zero_case, not_one_case;
__ Branch(&not_zero_case, ne, a0, Operand(zero_reg));
ArrayNoArgumentConstructorStub no_argument_stub;
__ TailCallStub(&no_argument_stub);
__ bind(&not_zero_case);
__ Branch(&not_one_case, gt, a0, Operand(1));
ArraySingleArgumentConstructorStub single_argument_stub;
__ TailCallStub(&single_argument_stub);
__ bind(&not_one_case);
ArrayNArgumentsConstructorStub n_argument_stub;
__ TailCallStub(&n_argument_stub);
} else {
Label generic_constructor;
// Run the native code for the Array function called as a 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);
}
Label generic_constructor;
// Run the native code for the Array function called as a 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);
}
......
......@@ -110,16 +110,20 @@ void CompareNilICStub::InitializeInterfaceDescriptor(
}
static void InitializeArrayConstructorDescriptor(Isolate* isolate,
CodeStubInterfaceDescriptor* descriptor) {
static void InitializeArrayConstructorDescriptor(
Isolate* isolate,
CodeStubInterfaceDescriptor* descriptor,
int constant_stack_parameter_count) {
// register state
// a1 -- constructor function
// a0 -- number of arguments
// a2 -- type info cell with elements kind
// a0 -- number of arguments to the constructor function
static Register registers[] = { a1, a2 };
descriptor->register_param_count_ = 2;
// stack param count needs (constructor pointer, and single argument)
descriptor->stack_parameter_count_ = &a0;
static Register registers[] = { a2 };
descriptor->register_param_count_ = 1;
if (constant_stack_parameter_count != 0) {
// stack param count needs (constructor pointer, and single argument)
descriptor->stack_parameter_count_ = &a0;
}
descriptor->hint_stack_parameter_count_ = constant_stack_parameter_count;
descriptor->register_params_ = registers;
descriptor->function_mode_ = JS_FUNCTION_STUB_MODE;
descriptor->deoptimization_handler_ =
......@@ -130,21 +134,21 @@ static void InitializeArrayConstructorDescriptor(Isolate* isolate,
void ArrayNoArgumentConstructorStub::InitializeInterfaceDescriptor(
Isolate* isolate,
CodeStubInterfaceDescriptor* descriptor) {
InitializeArrayConstructorDescriptor(isolate, descriptor);
InitializeArrayConstructorDescriptor(isolate, descriptor, 0);
}
void ArraySingleArgumentConstructorStub::InitializeInterfaceDescriptor(
Isolate* isolate,
CodeStubInterfaceDescriptor* descriptor) {
InitializeArrayConstructorDescriptor(isolate, descriptor);
InitializeArrayConstructorDescriptor(isolate, descriptor, 1);
}
void ArrayNArgumentsConstructorStub::InitializeInterfaceDescriptor(
Isolate* isolate,
CodeStubInterfaceDescriptor* descriptor) {
InitializeArrayConstructorDescriptor(isolate, descriptor);
InitializeArrayConstructorDescriptor(isolate, descriptor, -1);
}
......@@ -3342,6 +3346,9 @@ void CodeStub::GenerateStubsAheadOfTime(Isolate* isolate) {
StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate);
StubFailureTrampolineStub::GenerateAheadOfTime(isolate);
RecordWriteStub::GenerateFixedRegStubsAheadOfTime(isolate);
if (FLAG_optimize_constructed_arrays) {
ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
}
}
......@@ -5096,7 +5103,7 @@ static void GenerateRecordCallTarget(MacroAssembler* masm) {
Handle<Object> terminal_kind_sentinel =
TypeFeedbackCells::MonomorphicArraySentinel(masm->isolate(),
LAST_FAST_ELEMENTS_KIND);
__ Branch(&miss, ne, a3, Operand(terminal_kind_sentinel));
__ Branch(&miss, gt, a3, Operand(terminal_kind_sentinel));
// Make sure the function is the Array() function
__ LoadArrayFunction(a3);
__ Branch(&megamorphic, ne, a1, Operand(a3));
......@@ -7562,6 +7569,189 @@ void ProfileEntryHookStub::Generate(MacroAssembler* masm) {
}
template<class T>
static void CreateArrayDispatch(MacroAssembler* masm) {
int last_index = GetSequenceIndexFromFastElementsKind(
TERMINAL_FAST_ELEMENTS_KIND);
for (int i = 0; i <= last_index; ++i) {
Label next;
ElementsKind kind = GetFastElementsKindFromSequenceIndex(i);
__ Branch(&next, ne, a3, Operand(kind));
T stub(kind);
__ TailCallStub(&stub);
__ bind(&next);
}
// If we reached this point there is a problem.
__ Abort("Unexpected ElementsKind in array constructor");
}
static void CreateArrayDispatchOneArgument(MacroAssembler* masm) {
// a2 - type info cell
// a3 - kind
// a0 - number of arguments
// a1 - constructor?
// sp[0] - last argument
ASSERT(FAST_SMI_ELEMENTS == 0);
ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1);
ASSERT(FAST_ELEMENTS == 2);
ASSERT(FAST_HOLEY_ELEMENTS == 3);
ASSERT(FAST_DOUBLE_ELEMENTS == 4);
ASSERT(FAST_HOLEY_DOUBLE_ELEMENTS == 5);
Handle<Object> undefined_sentinel(
masm->isolate()->heap()->undefined_value(),
masm->isolate());
// is the low bit set? If so, we are holey and that is good.
Label normal_sequence;
__ And(at, a3, Operand(1));
__ Branch(&normal_sequence, ne, at, Operand(zero_reg));
// look at the first argument
__ lw(t1, MemOperand(sp, 0));
__ Branch(&normal_sequence, eq, t1, Operand(zero_reg));
// We are going to create a holey array, but our kind is non-holey.
// Fix kind and retry
__ Addu(a3, a3, Operand(1));
__ Branch(&normal_sequence, eq, a2, Operand(undefined_sentinel));
// Save the resulting elements kind in type info
__ SmiTag(a3);
__ sw(a3, FieldMemOperand(a2, kPointerSize));
__ SmiUntag(a3);
__ bind(&normal_sequence);
int last_index = GetSequenceIndexFromFastElementsKind(
TERMINAL_FAST_ELEMENTS_KIND);
for (int i = 0; i <= last_index; ++i) {
Label next;
ElementsKind kind = GetFastElementsKindFromSequenceIndex(i);
__ Branch(&next, ne, a3, Operand(kind));
ArraySingleArgumentConstructorStub stub(kind);
__ TailCallStub(&stub);
__ bind(&next);
}
// If we reached this point there is a problem.
__ Abort("Unexpected ElementsKind in array constructor");
}
template<class T>
static void ArrayConstructorStubAheadOfTimeHelper(Isolate* isolate) {
int to_index = GetSequenceIndexFromFastElementsKind(
TERMINAL_FAST_ELEMENTS_KIND);
for (int i = 0; i <= to_index; ++i) {
ElementsKind kind = GetFastElementsKindFromSequenceIndex(i);
T stub(kind);
stub.GetCode(isolate)->set_is_pregenerated(true);
}
}
void ArrayConstructorStubBase::GenerateStubsAheadOfTime(Isolate* isolate) {
ArrayConstructorStubAheadOfTimeHelper<ArrayNoArgumentConstructorStub>(
isolate);
ArrayConstructorStubAheadOfTimeHelper<ArraySingleArgumentConstructorStub>(
isolate);
ArrayConstructorStubAheadOfTimeHelper<ArrayNArgumentsConstructorStub>(
isolate);
}
void ArrayConstructorStub::Generate(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- a0 : argc (only if argument_count_ == ANY)
// -- a1 : constructor
// -- a2 : type info cell
// -- sp[0] : return address
// -- sp[4] : last argument
// -----------------------------------
Handle<Object> undefined_sentinel(
masm->isolate()->heap()->undefined_value(),
masm->isolate());
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.
__ lw(a3, FieldMemOperand(a1, JSFunction::kPrototypeOrInitialMapOffset));
// Will both indicate a NULL and a Smi.
__ And(at, a3, Operand(kSmiTagMask));
__ Assert(ne, "Unexpected initial map for Array function",
at, Operand(zero_reg));
__ GetObjectType(a3, a3, t0);
__ Assert(eq, "Unexpected initial map for Array function",
t0, Operand(MAP_TYPE));
// We should either have undefined in ebx or a valid jsglobalpropertycell
Label okay_here;
Handle<Map> global_property_cell_map(
masm->isolate()->heap()->global_property_cell_map());
__ Branch(&okay_here, eq, a2, Operand(undefined_sentinel));
__ lw(a3, FieldMemOperand(a2, 0));
__ Assert(eq, "Expected property cell in register ebx",
a3, Operand(global_property_cell_map));
__ bind(&okay_here);
}
if (FLAG_optimize_constructed_arrays) {
Label no_info, switch_ready;
// Get the elements kind and case on that.
__ Branch(&no_info, eq, a2, Operand(undefined_sentinel));
__ lw(a3, FieldMemOperand(a2, kPointerSize));
// There is no info if the call site went megamorphic either
// TODO(mvstanton): Really? I thought if it was the array function that
// the cell wouldn't get stamped as megamorphic.
__ Branch(&no_info, eq, a3,
Operand(TypeFeedbackCells::MegamorphicSentinel(masm->isolate())));
__ SmiUntag(a3);
__ jmp(&switch_ready);
__ bind(&no_info);
__ li(a3, Operand(GetInitialFastElementsKind()));
__ bind(&switch_ready);
if (argument_count_ == ANY) {
Label not_zero_case, not_one_case;
__ And(at, a0, a0);
__ Branch(&not_zero_case, ne, at, Operand(zero_reg));
CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm);
__ bind(&not_zero_case);
__ Branch(&not_one_case, gt, a0, Operand(1));
CreateArrayDispatchOneArgument(masm);
__ bind(&not_one_case);
CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm);
} else if (argument_count_ == NONE) {
CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm);
} else if (argument_count_ == ONE) {
CreateArrayDispatchOneArgument(masm);
} else if (argument_count_ == MORE_THAN_ONE) {
CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm);
} else {
UNREACHABLE();
}
} else {
Label generic_constructor;
// Run the native code for the Array function called as a 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
......
......@@ -35,6 +35,9 @@ namespace v8 {
namespace internal {
void ArrayNativeCode(MacroAssembler* masm, Label* call_generic_code);
// Compute a transcendental math function natively, or call the
// TranscendentalCache runtime function.
class TranscendentalCacheStub: public PlatformCodeStub {
......
......@@ -2546,20 +2546,21 @@ void LCodeGen::DoReturn(LReturn* instr) {
if (NeedsEagerFrame()) {
__ mov(sp, fp);
__ Pop(ra, fp);
if (instr->has_constant_parameter_count()) {
int parameter_count = ToInteger32(instr->constant_parameter_count());
int32_t sp_delta = (parameter_count + 1) * kPointerSize;
if (sp_delta != 0) {
__ Addu(sp, sp, Operand(sp_delta));
}
} else {
Register reg = ToRegister(instr->parameter_count());
__ Addu(reg, reg, Operand(1));
__ sll(at, reg, kPointerSizeLog2);
__ Addu(sp, sp, at);
}
if (instr->has_constant_parameter_count()) {
int parameter_count = ToInteger32(instr->constant_parameter_count());
int32_t sp_delta = (parameter_count + 1) * kPointerSize;
if (sp_delta != 0) {
__ Addu(sp, sp, Operand(sp_delta));
}
} else {
Register reg = ToRegister(instr->parameter_count());
// The argument count parameter is a smi
__ SmiUntag(reg);
__ sll(at, reg, kPointerSizeLog2);
__ Addu(sp, sp, at);
}
__ Jump(ra);
}
......@@ -3890,10 +3891,18 @@ void LCodeGen::DoCallNewArray(LCallNewArray* instr) {
__ li(a0, Operand(instr->arity()));
__ li(a2, Operand(instr->hydrogen()->property_cell()));
Handle<Code> array_construct_code =
isolate()->builtins()->ArrayConstructCode();
CallCode(array_construct_code, RelocInfo::CONSTRUCT_CALL, instr);
Object* cell_value = instr->hydrogen()->property_cell()->value();
ElementsKind kind = static_cast<ElementsKind>(Smi::cast(cell_value)->value());
if (instr->arity() == 0) {
ArrayNoArgumentConstructorStub stub(kind);
CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr);
} else if (instr->arity() == 1) {
ArraySingleArgumentConstructorStub stub(kind);
CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr);
} else {
ArrayNArgumentsConstructorStub stub(kind);
CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr);
}
}
......
......@@ -2306,7 +2306,8 @@ LInstruction* LChunkBuilder::DoParameter(HParameter* instr) {
ASSERT(info()->IsStub());
CodeStubInterfaceDescriptor* descriptor =
info()->code_stub()->GetInterfaceDescriptor(info()->isolate());
Register reg = descriptor->register_params_[instr->index()];
int index = static_cast<int>(instr->index());
Register reg = DESCRIPTOR_GET_PARAMETER_REGISTER(descriptor, index);
return DefineFixed(result, reg);
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment