PPC/s390: [builtins] Move ArrayConstructorStub to builtin

Port 111c5735ef

Original Commit Message:

    Calls from embedded builtins to stubs are expensive due to the
    indirection through the builtins constants table. This moves
    the ArrayConstructorStub to a builtin.

R=jgruber@chromium.org, joransiu@ca.ibm.com, michael_dawson@ca.ibm.com
BUG=
LOG=N

Change-Id: Icc6af15d80eb5c95a191832eb9636ebe97e61e07
Reviewed-on: https://chromium-review.googlesource.com/1074548
Reviewed-by: Joran Siu <joransiu@ca.ibm.com>
Commit-Queue: Junliang Yan <jyan@ca.ibm.com>
Cr-Commit-Position: refs/heads/master@{#53377}
This commit is contained in:
Junliang Yan 2018-05-26 02:33:13 -04:00 committed by Commit Bot
parent c45f74e29f
commit b6b079d872
4 changed files with 341 additions and 339 deletions

View File

@ -135,11 +135,11 @@ void Builtins::Generate_ArrayConstructor(MacroAssembler* masm) {
__ cmp(r6, r5);
__ bne(&call);
__ mr(r6, r4);
__ bind(&call);
// Run the native code for the Array function called as a normal function.
__ bind(&call);
ArrayConstructorStub stub(masm->isolate());
__ TailCallStub(&stub);
Handle<Code> code = BUILTIN_CODE(masm->isolate(), ArrayConstructorImpl);
__ Jump(code, RelocInfo::CODE_TARGET);
}
static void GenerateTailCallToReturnedCode(MacroAssembler* masm,
@ -1192,8 +1192,8 @@ void Builtins::Generate_InterpreterPushArgsThenConstructImpl(
// Tail call to the array construct stub (still in the caller
// context at this point).
ArrayConstructorStub array_constructor_stub(masm->isolate());
__ Jump(array_constructor_stub.GetCode(), RelocInfo::CODE_TARGET);
Handle<Code> code = BUILTIN_CODE(masm->isolate(), ArrayConstructorImpl);
__ Jump(code, RelocInfo::CODE_TARGET);
} else if (mode == InterpreterPushArgsMode::kWithFinalSpread) {
// Call the constructor with r3, r4, and r6 unmodified.
__ Jump(BUILTIN_CODE(masm->isolate(), ConstructWithSpread),
@ -3069,6 +3069,173 @@ void Builtins::Generate_MathPowInternal(MacroAssembler* masm) {
__ Ret();
}
namespace {
template <class T>
static void CreateArrayDispatch(MacroAssembler* masm,
AllocationSiteOverrideMode mode) {
if (mode == DISABLE_ALLOCATION_SITES) {
T stub(masm->isolate(), GetInitialFastElementsKind(), mode);
__ TailCallStub(&stub);
} else if (mode == DONT_OVERRIDE) {
int last_index =
GetSequenceIndexFromFastElementsKind(TERMINAL_FAST_ELEMENTS_KIND);
for (int i = 0; i <= last_index; ++i) {
ElementsKind kind = GetFastElementsKindFromSequenceIndex(i);
__ Cmpi(r6, Operand(kind), r0);
T stub(masm->isolate(), kind);
__ TailCallStub(&stub, eq);
}
// If we reached this point there is a problem.
__ Abort(AbortReason::kUnexpectedElementsKindInArrayConstructor);
} else {
UNREACHABLE();
}
}
static void CreateArrayDispatchOneArgument(MacroAssembler* masm,
AllocationSiteOverrideMode mode) {
// r5 - allocation site (if mode != DISABLE_ALLOCATION_SITES)
// r6 - kind (if mode != DISABLE_ALLOCATION_SITES)
// r3 - number of arguments
// r4 - constructor?
// sp[0] - last argument
STATIC_ASSERT(PACKED_SMI_ELEMENTS == 0);
STATIC_ASSERT(HOLEY_SMI_ELEMENTS == 1);
STATIC_ASSERT(PACKED_ELEMENTS == 2);
STATIC_ASSERT(HOLEY_ELEMENTS == 3);
STATIC_ASSERT(PACKED_DOUBLE_ELEMENTS == 4);
STATIC_ASSERT(HOLEY_DOUBLE_ELEMENTS == 5);
if (mode == DISABLE_ALLOCATION_SITES) {
ElementsKind initial = GetInitialFastElementsKind();
ElementsKind holey_initial = GetHoleyElementsKind(initial);
ArraySingleArgumentConstructorStub stub_holey(
masm->isolate(), holey_initial, DISABLE_ALLOCATION_SITES);
__ TailCallStub(&stub_holey);
} else if (mode == DONT_OVERRIDE) {
// is the low bit set? If so, we are holey and that is good.
Label normal_sequence;
__ andi(r0, r6, Operand(1));
__ bne(&normal_sequence, cr0);
// We are going to create a holey array, but our kind is non-holey.
// Fix kind and retry (only if we have an allocation site in the slot).
__ addi(r6, r6, Operand(1));
if (FLAG_debug_code) {
__ LoadP(r8, FieldMemOperand(r5, 0));
__ CompareRoot(r8, Heap::kAllocationSiteMapRootIndex);
__ Assert(eq, AbortReason::kExpectedAllocationSite);
}
// Save the resulting elements kind in type info. We can't just store r6
// in the AllocationSite::transition_info field because elements kind is
// restricted to a portion of the field...upper bits need to be left alone.
STATIC_ASSERT(AllocationSite::ElementsKindBits::kShift == 0);
__ LoadP(r7, FieldMemOperand(
r5, AllocationSite::kTransitionInfoOrBoilerplateOffset));
__ AddSmiLiteral(r7, r7, Smi::FromInt(kFastElementsKindPackedToHoley), r0);
__ StoreP(
r7,
FieldMemOperand(r5, AllocationSite::kTransitionInfoOrBoilerplateOffset),
r0);
__ bind(&normal_sequence);
int last_index =
GetSequenceIndexFromFastElementsKind(TERMINAL_FAST_ELEMENTS_KIND);
for (int i = 0; i <= last_index; ++i) {
ElementsKind kind = GetFastElementsKindFromSequenceIndex(i);
__ mov(r0, Operand(kind));
__ cmp(r6, r0);
ArraySingleArgumentConstructorStub stub(masm->isolate(), kind);
__ TailCallStub(&stub, eq);
}
// If we reached this point there is a problem.
__ Abort(AbortReason::kUnexpectedElementsKindInArrayConstructor);
} else {
UNREACHABLE();
}
}
void GenerateDispatchToArrayStub(
MacroAssembler* masm, AllocationSiteOverrideMode mode) {
Label not_zero_case, not_one_case;
__ cmpi(r3, Operand::Zero());
__ bne(&not_zero_case);
CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm, mode);
__ bind(&not_zero_case);
__ cmpi(r3, Operand(1));
__ bgt(&not_one_case);
CreateArrayDispatchOneArgument(masm, mode);
__ bind(&not_one_case);
__ Jump(BUILTIN_CODE(masm->isolate(), ArrayNArgumentsConstructor),
RelocInfo::CODE_TARGET);
}
} // namespace
void Builtins::Generate_ArrayConstructorImpl(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- r3 : argc (only if argument_count() == ANY)
// -- r4 : constructor
// -- r5 : AllocationSite or undefined
// -- r6 : new target
// -- 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.
__ LoadP(r7, FieldMemOperand(r4, JSFunction::kPrototypeOrInitialMapOffset));
// Will both indicate a nullptr and a Smi.
__ TestIfSmi(r7, r0);
__ Assert(ne, AbortReason::kUnexpectedInitialMapForArrayFunction, cr0);
__ CompareObjectType(r7, r7, r8, MAP_TYPE);
__ Assert(eq, AbortReason::kUnexpectedInitialMapForArrayFunction);
// We should either have undefined in r5 or a valid AllocationSite
__ AssertUndefinedOrAllocationSite(r5, r7);
}
// Enter the context of the Array function.
__ LoadP(cp, FieldMemOperand(r4, JSFunction::kContextOffset));
Label subclassing;
__ cmp(r6, r4);
__ bne(&subclassing);
Label no_info;
// Get the elements kind and case on that.
__ CompareRoot(r5, Heap::kUndefinedValueRootIndex);
__ beq(&no_info);
__ LoadP(r6, FieldMemOperand(
r5, AllocationSite::kTransitionInfoOrBoilerplateOffset));
__ SmiUntag(r6);
STATIC_ASSERT(AllocationSite::ElementsKindBits::kShift == 0);
__ And(r6, r6, Operand(AllocationSite::ElementsKindBits::kMask));
GenerateDispatchToArrayStub(masm, DONT_OVERRIDE);
__ bind(&no_info);
GenerateDispatchToArrayStub(masm, DISABLE_ALLOCATION_SITES);
__ bind(&subclassing);
__ ShiftLeftImm(r0, r3, Operand(kPointerSizeLog2));
__ StorePX(r4, MemOperand(sp, r0));
__ addi(r3, r3, Operand(3));
__ Push(r6, r5);
__ JumpToExternalReference(ExternalReference::Create(Runtime::kNewArray));
}
void Builtins::Generate_ArrayNArgumentsConstructor(MacroAssembler* masm) {
__ ShiftLeftImm(r0, r3, Operand(kPointerSizeLog2));
__ StorePX(r4, MemOperand(sp, r0));

View File

@ -144,11 +144,11 @@ void Builtins::Generate_ArrayConstructor(MacroAssembler* masm) {
__ CmpP(r5, r4);
__ bne(&call);
__ LoadRR(r5, r3);
__ bind(&call);
// Run the native code for the Array function called as a normal function.
__ bind(&call);
ArrayConstructorStub stub(masm->isolate());
__ TailCallStub(&stub);
Handle<Code> code = BUILTIN_CODE(masm->isolate(), ArrayConstructorImpl);
__ Jump(code, RelocInfo::CODE_TARGET);
}
static void GenerateTailCallToReturnedCode(MacroAssembler* masm,
@ -1206,8 +1206,8 @@ void Builtins::Generate_InterpreterPushArgsThenConstructImpl(
// Tail call to the array construct stub (still in the caller
// context at this point).
ArrayConstructorStub array_constructor_stub(masm->isolate());
__ Jump(array_constructor_stub.GetCode(), RelocInfo::CODE_TARGET);
Handle<Code> code = BUILTIN_CODE(masm->isolate(), ArrayConstructorImpl);
__ Jump(code, RelocInfo::CODE_TARGET);
} else if (mode == InterpreterPushArgsMode::kWithFinalSpread) {
// Call the constructor with r2, r3, and r5 unmodified.
__ Jump(BUILTIN_CODE(masm->isolate(), ConstructWithSpread),
@ -3071,6 +3071,170 @@ void Builtins::Generate_ArrayNArgumentsConstructor(MacroAssembler* masm) {
__ AddP(r2, r2, Operand(3));
__ TailCallRuntime(Runtime::kNewArray);
}
namespace {
template <class T>
static void CreateArrayDispatch(MacroAssembler* masm,
AllocationSiteOverrideMode mode) {
if (mode == DISABLE_ALLOCATION_SITES) {
T stub(masm->isolate(), GetInitialFastElementsKind(), mode);
__ TailCallStub(&stub);
} else if (mode == DONT_OVERRIDE) {
int last_index =
GetSequenceIndexFromFastElementsKind(TERMINAL_FAST_ELEMENTS_KIND);
for (int i = 0; i <= last_index; ++i) {
ElementsKind kind = GetFastElementsKindFromSequenceIndex(i);
__ CmpP(r5, Operand(kind));
T stub(masm->isolate(), kind);
__ TailCallStub(&stub, eq);
}
// If we reached this point there is a problem.
__ Abort(AbortReason::kUnexpectedElementsKindInArrayConstructor);
} else {
UNREACHABLE();
}
}
static void CreateArrayDispatchOneArgument(MacroAssembler* masm,
AllocationSiteOverrideMode mode) {
// r4 - allocation site (if mode != DISABLE_ALLOCATION_SITES)
// r5 - kind (if mode != DISABLE_ALLOCATION_SITES)
// r2 - number of arguments
// r3 - constructor?
// sp[0] - last argument
STATIC_ASSERT(PACKED_SMI_ELEMENTS == 0);
STATIC_ASSERT(HOLEY_SMI_ELEMENTS == 1);
STATIC_ASSERT(PACKED_ELEMENTS == 2);
STATIC_ASSERT(HOLEY_ELEMENTS == 3);
STATIC_ASSERT(PACKED_DOUBLE_ELEMENTS == 4);
STATIC_ASSERT(HOLEY_DOUBLE_ELEMENTS == 5);
if (mode == DISABLE_ALLOCATION_SITES) {
ElementsKind initial = GetInitialFastElementsKind();
ElementsKind holey_initial = GetHoleyElementsKind(initial);
ArraySingleArgumentConstructorStub stub_holey(
masm->isolate(), holey_initial, DISABLE_ALLOCATION_SITES);
__ TailCallStub(&stub_holey);
} else if (mode == DONT_OVERRIDE) {
Label normal_sequence;
// is the low bit set? If so, we are holey and that is good.
__ AndP(r0, r5, Operand(1));
__ bne(&normal_sequence);
// We are going to create a holey array, but our kind is non-holey.
// Fix kind and retry (only if we have an allocation site in the slot).
__ AddP(r5, r5, Operand(1));
if (FLAG_debug_code) {
__ LoadP(r7, FieldMemOperand(r4, 0));
__ CompareRoot(r7, Heap::kAllocationSiteMapRootIndex);
__ Assert(eq, AbortReason::kExpectedAllocationSite);
}
// Save the resulting elements kind in type info. We can't just store r5
// in the AllocationSite::transition_info field because elements kind is
// restricted to a portion of the field...upper bits need to be left alone.
STATIC_ASSERT(AllocationSite::ElementsKindBits::kShift == 0);
__ LoadP(r6, FieldMemOperand(
r4, AllocationSite::kTransitionInfoOrBoilerplateOffset));
__ AddSmiLiteral(r6, r6, Smi::FromInt(kFastElementsKindPackedToHoley), r0);
__ StoreP(r6, FieldMemOperand(
r4, AllocationSite::kTransitionInfoOrBoilerplateOffset));
__ bind(&normal_sequence);
int last_index =
GetSequenceIndexFromFastElementsKind(TERMINAL_FAST_ELEMENTS_KIND);
for (int i = 0; i <= last_index; ++i) {
ElementsKind kind = GetFastElementsKindFromSequenceIndex(i);
__ CmpP(r5, Operand(kind));
ArraySingleArgumentConstructorStub stub(masm->isolate(), kind);
__ TailCallStub(&stub, eq);
}
// If we reached this point there is a problem.
__ Abort(AbortReason::kUnexpectedElementsKindInArrayConstructor);
} else {
UNREACHABLE();
}
}
void GenerateDispatchToArrayStub(
MacroAssembler* masm, AllocationSiteOverrideMode mode) {
Label not_zero_case, not_one_case;
__ CmpP(r2, Operand::Zero());
__ bne(&not_zero_case);
CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm, mode);
__ bind(&not_zero_case);
__ CmpP(r2, Operand(1));
__ bgt(&not_one_case);
CreateArrayDispatchOneArgument(masm, mode);
__ bind(&not_one_case);
__ Jump(BUILTIN_CODE(masm->isolate(), ArrayNArgumentsConstructor),
RelocInfo::CODE_TARGET);
}
} // namespace
void Builtins::Generate_ArrayConstructorImpl(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- r2 : argc (only if argument_count() == ANY)
// -- r3 : constructor
// -- r4 : AllocationSite or undefined
// -- r5 : new target
// -- 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.
__ LoadP(r6, FieldMemOperand(r3, JSFunction::kPrototypeOrInitialMapOffset));
// Will both indicate a nullptr and a Smi.
__ TestIfSmi(r6);
__ Assert(ne, AbortReason::kUnexpectedInitialMapForArrayFunction, cr0);
__ CompareObjectType(r6, r6, r7, MAP_TYPE);
__ Assert(eq, AbortReason::kUnexpectedInitialMapForArrayFunction);
// We should either have undefined in r4 or a valid AllocationSite
__ AssertUndefinedOrAllocationSite(r4, r6);
}
// Enter the context of the Array function.
__ LoadP(cp, FieldMemOperand(r3, JSFunction::kContextOffset));
Label subclassing;
__ CmpP(r5, r3);
__ bne(&subclassing, Label::kNear);
Label no_info;
// Get the elements kind and case on that.
__ CompareRoot(r4, Heap::kUndefinedValueRootIndex);
__ beq(&no_info);
__ LoadP(r5, FieldMemOperand(
r4, AllocationSite::kTransitionInfoOrBoilerplateOffset));
__ SmiUntag(r5);
STATIC_ASSERT(AllocationSite::ElementsKindBits::kShift == 0);
__ AndP(r5, Operand(AllocationSite::ElementsKindBits::kMask));
GenerateDispatchToArrayStub(masm, DONT_OVERRIDE);
__ bind(&no_info);
GenerateDispatchToArrayStub(masm, DISABLE_ALLOCATION_SITES);
__ bind(&subclassing);
__ ShiftLeftP(r1, r2, Operand(kPointerSizeLog2));
__ StoreP(r3, MemOperand(sp, r1));
__ AddP(r2, r2, Operand(3));
__ Push(r5, r4);
__ JumpToExternalReference(ExternalReference::Create(Runtime::kNewArray));
}
#undef __
} // namespace internal

View File

@ -329,99 +329,6 @@ void ProfileEntryHookStub::Generate(MacroAssembler* masm) {
__ Ret();
}
template <class T>
static void CreateArrayDispatch(MacroAssembler* masm,
AllocationSiteOverrideMode mode) {
if (mode == DISABLE_ALLOCATION_SITES) {
T stub(masm->isolate(), GetInitialFastElementsKind(), mode);
__ TailCallStub(&stub);
} else if (mode == DONT_OVERRIDE) {
int last_index =
GetSequenceIndexFromFastElementsKind(TERMINAL_FAST_ELEMENTS_KIND);
for (int i = 0; i <= last_index; ++i) {
ElementsKind kind = GetFastElementsKindFromSequenceIndex(i);
__ Cmpi(r6, Operand(kind), r0);
T stub(masm->isolate(), kind);
__ TailCallStub(&stub, eq);
}
// If we reached this point there is a problem.
__ Abort(AbortReason::kUnexpectedElementsKindInArrayConstructor);
} else {
UNREACHABLE();
}
}
static void CreateArrayDispatchOneArgument(MacroAssembler* masm,
AllocationSiteOverrideMode mode) {
// r5 - allocation site (if mode != DISABLE_ALLOCATION_SITES)
// r6 - kind (if mode != DISABLE_ALLOCATION_SITES)
// r3 - number of arguments
// r4 - constructor?
// sp[0] - last argument
STATIC_ASSERT(PACKED_SMI_ELEMENTS == 0);
STATIC_ASSERT(HOLEY_SMI_ELEMENTS == 1);
STATIC_ASSERT(PACKED_ELEMENTS == 2);
STATIC_ASSERT(HOLEY_ELEMENTS == 3);
STATIC_ASSERT(PACKED_DOUBLE_ELEMENTS == 4);
STATIC_ASSERT(HOLEY_DOUBLE_ELEMENTS == 5);
if (mode == DISABLE_ALLOCATION_SITES) {
ElementsKind initial = GetInitialFastElementsKind();
ElementsKind holey_initial = GetHoleyElementsKind(initial);
ArraySingleArgumentConstructorStub stub_holey(
masm->isolate(), holey_initial, DISABLE_ALLOCATION_SITES);
__ TailCallStub(&stub_holey);
} else if (mode == DONT_OVERRIDE) {
// is the low bit set? If so, we are holey and that is good.
Label normal_sequence;
__ andi(r0, r6, Operand(1));
__ bne(&normal_sequence, cr0);
// We are going to create a holey array, but our kind is non-holey.
// Fix kind and retry (only if we have an allocation site in the slot).
__ addi(r6, r6, Operand(1));
if (FLAG_debug_code) {
__ LoadP(r8, FieldMemOperand(r5, 0));
__ CompareRoot(r8, Heap::kAllocationSiteMapRootIndex);
__ Assert(eq, AbortReason::kExpectedAllocationSite);
}
// Save the resulting elements kind in type info. We can't just store r6
// in the AllocationSite::transition_info field because elements kind is
// restricted to a portion of the field...upper bits need to be left alone.
STATIC_ASSERT(AllocationSite::ElementsKindBits::kShift == 0);
__ LoadP(r7, FieldMemOperand(
r5, AllocationSite::kTransitionInfoOrBoilerplateOffset));
__ AddSmiLiteral(r7, r7, Smi::FromInt(kFastElementsKindPackedToHoley), r0);
__ StoreP(
r7,
FieldMemOperand(r5, AllocationSite::kTransitionInfoOrBoilerplateOffset),
r0);
__ bind(&normal_sequence);
int last_index =
GetSequenceIndexFromFastElementsKind(TERMINAL_FAST_ELEMENTS_KIND);
for (int i = 0; i <= last_index; ++i) {
ElementsKind kind = GetFastElementsKindFromSequenceIndex(i);
__ mov(r0, Operand(kind));
__ cmp(r6, r0);
ArraySingleArgumentConstructorStub stub(masm->isolate(), kind);
__ TailCallStub(&stub, eq);
}
// If we reached this point there is a problem.
__ Abort(AbortReason::kUnexpectedElementsKindInArrayConstructor);
} else {
UNREACHABLE();
}
}
template <class T>
static void ArrayConstructorStubAheadOfTimeHelper(Isolate* isolate) {
int to_index =
@ -437,7 +344,6 @@ static void ArrayConstructorStubAheadOfTimeHelper(Isolate* isolate) {
}
}
void CommonArrayConstructorStub::GenerateStubsAheadOfTime(Isolate* isolate) {
ArrayConstructorStubAheadOfTimeHelper<ArrayNoArgumentConstructorStub>(
isolate);
@ -451,82 +357,6 @@ void CommonArrayConstructorStub::GenerateStubsAheadOfTime(Isolate* isolate) {
}
}
void ArrayConstructorStub::GenerateDispatchToArrayStub(
MacroAssembler* masm, AllocationSiteOverrideMode mode) {
Label not_zero_case, not_one_case;
__ cmpi(r3, Operand::Zero());
__ bne(&not_zero_case);
CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm, mode);
__ bind(&not_zero_case);
__ cmpi(r3, Operand(1));
__ bgt(&not_one_case);
CreateArrayDispatchOneArgument(masm, mode);
__ bind(&not_one_case);
__ Jump(BUILTIN_CODE(masm->isolate(), ArrayNArgumentsConstructor),
RelocInfo::CODE_TARGET);
}
void ArrayConstructorStub::Generate(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- r3 : argc (only if argument_count() == ANY)
// -- r4 : constructor
// -- r5 : AllocationSite or undefined
// -- r6 : new target
// -- 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.
__ LoadP(r7, FieldMemOperand(r4, JSFunction::kPrototypeOrInitialMapOffset));
// Will both indicate a nullptr and a Smi.
__ TestIfSmi(r7, r0);
__ Assert(ne, AbortReason::kUnexpectedInitialMapForArrayFunction, cr0);
__ CompareObjectType(r7, r7, r8, MAP_TYPE);
__ Assert(eq, AbortReason::kUnexpectedInitialMapForArrayFunction);
// We should either have undefined in r5 or a valid AllocationSite
__ AssertUndefinedOrAllocationSite(r5, r7);
}
// Enter the context of the Array function.
__ LoadP(cp, FieldMemOperand(r4, JSFunction::kContextOffset));
Label subclassing;
__ cmp(r6, r4);
__ bne(&subclassing);
Label no_info;
// Get the elements kind and case on that.
__ CompareRoot(r5, Heap::kUndefinedValueRootIndex);
__ beq(&no_info);
__ LoadP(r6, FieldMemOperand(
r5, AllocationSite::kTransitionInfoOrBoilerplateOffset));
__ SmiUntag(r6);
STATIC_ASSERT(AllocationSite::ElementsKindBits::kShift == 0);
__ And(r6, r6, Operand(AllocationSite::ElementsKindBits::kMask));
GenerateDispatchToArrayStub(masm, DONT_OVERRIDE);
__ bind(&no_info);
GenerateDispatchToArrayStub(masm, DISABLE_ALLOCATION_SITES);
__ bind(&subclassing);
__ ShiftLeftImm(r0, r3, Operand(kPointerSizeLog2));
__ StorePX(r4, MemOperand(sp, r0));
__ addi(r3, r3, Operand(3));
__ Push(r6, r5);
__ JumpToExternalReference(ExternalReference::Create(Runtime::kNewArray));
}
void InternalArrayConstructorStub::GenerateCase(MacroAssembler* masm,
ElementsKind kind) {
__ cmpli(r3, Operand(1));

View File

@ -370,92 +370,6 @@ void ProfileEntryHookStub::Generate(MacroAssembler* masm) {
__ Ret();
}
template <class T>
static void CreateArrayDispatch(MacroAssembler* masm,
AllocationSiteOverrideMode mode) {
if (mode == DISABLE_ALLOCATION_SITES) {
T stub(masm->isolate(), GetInitialFastElementsKind(), mode);
__ TailCallStub(&stub);
} else if (mode == DONT_OVERRIDE) {
int last_index =
GetSequenceIndexFromFastElementsKind(TERMINAL_FAST_ELEMENTS_KIND);
for (int i = 0; i <= last_index; ++i) {
ElementsKind kind = GetFastElementsKindFromSequenceIndex(i);
__ CmpP(r5, Operand(kind));
T stub(masm->isolate(), kind);
__ TailCallStub(&stub, eq);
}
// If we reached this point there is a problem.
__ Abort(AbortReason::kUnexpectedElementsKindInArrayConstructor);
} else {
UNREACHABLE();
}
}
static void CreateArrayDispatchOneArgument(MacroAssembler* masm,
AllocationSiteOverrideMode mode) {
// r4 - allocation site (if mode != DISABLE_ALLOCATION_SITES)
// r5 - kind (if mode != DISABLE_ALLOCATION_SITES)
// r2 - number of arguments
// r3 - constructor?
// sp[0] - last argument
STATIC_ASSERT(PACKED_SMI_ELEMENTS == 0);
STATIC_ASSERT(HOLEY_SMI_ELEMENTS == 1);
STATIC_ASSERT(PACKED_ELEMENTS == 2);
STATIC_ASSERT(HOLEY_ELEMENTS == 3);
STATIC_ASSERT(PACKED_DOUBLE_ELEMENTS == 4);
STATIC_ASSERT(HOLEY_DOUBLE_ELEMENTS == 5);
if (mode == DISABLE_ALLOCATION_SITES) {
ElementsKind initial = GetInitialFastElementsKind();
ElementsKind holey_initial = GetHoleyElementsKind(initial);
ArraySingleArgumentConstructorStub stub_holey(
masm->isolate(), holey_initial, DISABLE_ALLOCATION_SITES);
__ TailCallStub(&stub_holey);
} else if (mode == DONT_OVERRIDE) {
Label normal_sequence;
// is the low bit set? If so, we are holey and that is good.
__ AndP(r0, r5, Operand(1));
__ bne(&normal_sequence);
// We are going to create a holey array, but our kind is non-holey.
// Fix kind and retry (only if we have an allocation site in the slot).
__ AddP(r5, r5, Operand(1));
if (FLAG_debug_code) {
__ LoadP(r7, FieldMemOperand(r4, 0));
__ CompareRoot(r7, Heap::kAllocationSiteMapRootIndex);
__ Assert(eq, AbortReason::kExpectedAllocationSite);
}
// Save the resulting elements kind in type info. We can't just store r5
// in the AllocationSite::transition_info field because elements kind is
// restricted to a portion of the field...upper bits need to be left alone.
STATIC_ASSERT(AllocationSite::ElementsKindBits::kShift == 0);
__ LoadP(r6, FieldMemOperand(
r4, AllocationSite::kTransitionInfoOrBoilerplateOffset));
__ AddSmiLiteral(r6, r6, Smi::FromInt(kFastElementsKindPackedToHoley), r0);
__ StoreP(r6, FieldMemOperand(
r4, AllocationSite::kTransitionInfoOrBoilerplateOffset));
__ bind(&normal_sequence);
int last_index =
GetSequenceIndexFromFastElementsKind(TERMINAL_FAST_ELEMENTS_KIND);
for (int i = 0; i <= last_index; ++i) {
ElementsKind kind = GetFastElementsKindFromSequenceIndex(i);
__ CmpP(r5, Operand(kind));
ArraySingleArgumentConstructorStub stub(masm->isolate(), kind);
__ TailCallStub(&stub, eq);
}
// If we reached this point there is a problem.
__ Abort(AbortReason::kUnexpectedElementsKindInArrayConstructor);
} else {
UNREACHABLE();
}
}
template <class T>
static void ArrayConstructorStubAheadOfTimeHelper(Isolate* isolate) {
int to_index =
@ -484,79 +398,6 @@ void CommonArrayConstructorStub::GenerateStubsAheadOfTime(Isolate* isolate) {
}
}
void ArrayConstructorStub::GenerateDispatchToArrayStub(
MacroAssembler* masm, AllocationSiteOverrideMode mode) {
Label not_zero_case, not_one_case;
__ CmpP(r2, Operand::Zero());
__ bne(&not_zero_case);
CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm, mode);
__ bind(&not_zero_case);
__ CmpP(r2, Operand(1));
__ bgt(&not_one_case);
CreateArrayDispatchOneArgument(masm, mode);
__ bind(&not_one_case);
__ Jump(BUILTIN_CODE(masm->isolate(), ArrayNArgumentsConstructor),
RelocInfo::CODE_TARGET);
}
void ArrayConstructorStub::Generate(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- r2 : argc (only if argument_count() == ANY)
// -- r3 : constructor
// -- r4 : AllocationSite or undefined
// -- r5 : new target
// -- 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.
__ LoadP(r6, FieldMemOperand(r3, JSFunction::kPrototypeOrInitialMapOffset));
// Will both indicate a nullptr and a Smi.
__ TestIfSmi(r6);
__ Assert(ne, AbortReason::kUnexpectedInitialMapForArrayFunction, cr0);
__ CompareObjectType(r6, r6, r7, MAP_TYPE);
__ Assert(eq, AbortReason::kUnexpectedInitialMapForArrayFunction);
// We should either have undefined in r4 or a valid AllocationSite
__ AssertUndefinedOrAllocationSite(r4, r6);
}
// Enter the context of the Array function.
__ LoadP(cp, FieldMemOperand(r3, JSFunction::kContextOffset));
Label subclassing;
__ CmpP(r5, r3);
__ bne(&subclassing, Label::kNear);
Label no_info;
// Get the elements kind and case on that.
__ CompareRoot(r4, Heap::kUndefinedValueRootIndex);
__ beq(&no_info);
__ LoadP(r5, FieldMemOperand(
r4, AllocationSite::kTransitionInfoOrBoilerplateOffset));
__ SmiUntag(r5);
STATIC_ASSERT(AllocationSite::ElementsKindBits::kShift == 0);
__ AndP(r5, Operand(AllocationSite::ElementsKindBits::kMask));
GenerateDispatchToArrayStub(masm, DONT_OVERRIDE);
__ bind(&no_info);
GenerateDispatchToArrayStub(masm, DISABLE_ALLOCATION_SITES);
__ bind(&subclassing);
__ ShiftLeftP(r1, r2, Operand(kPointerSizeLog2));
__ StoreP(r3, MemOperand(sp, r1));
__ AddP(r2, r2, Operand(3));
__ Push(r5, r4);
__ JumpToExternalReference(ExternalReference::Create(Runtime::kNewArray));
}
void InternalArrayConstructorStub::GenerateCase(MacroAssembler* masm,
ElementsKind kind) {
__ CmpLogicalP(r2, Operand(1));