Commit 7d161e4d authored by jgruber's avatar jgruber Committed by Commit Bot

[builtins] Move InternalArrayConstructorStub to builtin

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

Bug: v8:6666
Change-Id: I8cd801bd9218ca9ef0853ed99c7a69090af5c9f9
Reviewed-on: https://chromium-review.googlesource.com/1072608Reviewed-by: 's avatarIgor Sheludko <ishell@chromium.org>
Commit-Queue: Jakob Gruber <jgruber@chromium.org>
Cr-Commit-Position: refs/heads/master@{#53360}
parent f83d8587
......@@ -348,81 +348,6 @@ void CommonArrayConstructorStub::GenerateStubsAheadOfTime(Isolate* isolate) {
}
}
void InternalArrayConstructorStub::GenerateCase(
MacroAssembler* masm, ElementsKind kind) {
__ cmp(r0, Operand(1));
InternalArrayNoArgumentConstructorStub stub0(isolate(), kind);
__ TailCallStub(&stub0, lo);
__ Jump(BUILTIN_CODE(masm->isolate(), ArrayNArgumentsConstructor),
RelocInfo::CODE_TARGET, hi);
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());
InternalArraySingleArgumentConstructorStub
stub1_holey(isolate(), GetHoleyElementsKind(kind));
__ TailCallStub(&stub1_holey, ne);
}
InternalArraySingleArgumentConstructorStub stub1(isolate(), kind);
__ TailCallStub(&stub1);
}
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 nullptr and a Smi.
__ tst(r3, Operand(kSmiTagMask));
__ Assert(ne, AbortReason::kUnexpectedInitialMapForArrayFunction);
__ CompareObjectType(r3, r3, r4, MAP_TYPE);
__ Assert(eq, AbortReason::kUnexpectedInitialMapForArrayFunction);
}
// 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.
__ DecodeField<Map::ElementsKindBits>(r3);
if (FLAG_debug_code) {
Label done;
__ cmp(r3, Operand(PACKED_ELEMENTS));
__ b(eq, &done);
__ cmp(r3, Operand(HOLEY_ELEMENTS));
__ Assert(
eq,
AbortReason::kInvalidElementsKindForInternalArrayOrInternalPackedArray);
__ bind(&done);
}
Label fast_elements_case;
__ cmp(r3, Operand(PACKED_ELEMENTS));
__ b(eq, &fast_elements_case);
GenerateCase(masm, HOLEY_ELEMENTS);
__ bind(&fast_elements_case);
GenerateCase(masm, PACKED_ELEMENTS);
}
static int AddressOffset(ExternalReference ref0, ExternalReference ref1) {
return ref0.address() - ref1.address();
}
......
......@@ -346,94 +346,6 @@ void CommonArrayConstructorStub::GenerateStubsAheadOfTime(Isolate* isolate) {
}
}
void InternalArrayConstructorStub::GenerateCase(
MacroAssembler* masm, ElementsKind kind) {
Label zero_case, n_case;
Register argc = x0;
__ Cbz(argc, &zero_case);
__ CompareAndBranch(argc, 1, ne, &n_case);
// One argument.
if (IsFastPackedElementsKind(kind)) {
Label packed_case;
// We might need to create a holey array; look at the first argument.
__ Peek(x10, 0);
__ Cbz(x10, &packed_case);
InternalArraySingleArgumentConstructorStub
stub1_holey(isolate(), GetHoleyElementsKind(kind));
__ TailCallStub(&stub1_holey);
__ Bind(&packed_case);
}
InternalArraySingleArgumentConstructorStub stub1(isolate(), kind);
__ TailCallStub(&stub1);
__ Bind(&zero_case);
// No arguments.
InternalArrayNoArgumentConstructorStub stub0(isolate(), kind);
__ TailCallStub(&stub0);
__ Bind(&n_case);
// N arguments.
__ Jump(BUILTIN_CODE(masm->isolate(), ArrayNArgumentsConstructor),
RelocInfo::CODE_TARGET);
}
void InternalArrayConstructorStub::Generate(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- x0 : argc
// -- x1 : constructor
// -- sp[0] : return address
// -- sp[4] : last argument
// -----------------------------------
Register constructor = x1;
if (FLAG_debug_code) {
// The array construct code is only set for the global and natives
// builtin Array functions which always have maps.
Label unexpected_map, map_ok;
// Initial map for the builtin Array function should be a map.
__ Ldr(x10, FieldMemOperand(constructor,
JSFunction::kPrototypeOrInitialMapOffset));
// Will both indicate a nullptr and a Smi.
__ JumpIfSmi(x10, &unexpected_map);
__ JumpIfObjectType(x10, x10, x11, MAP_TYPE, &map_ok);
__ Bind(&unexpected_map);
__ Abort(AbortReason::kUnexpectedInitialMapForArrayFunction);
__ Bind(&map_ok);
}
Register kind = w3;
// Figure out the right elements kind
__ Ldr(x10, FieldMemOperand(constructor,
JSFunction::kPrototypeOrInitialMapOffset));
// Retrieve elements_kind from map.
__ LoadElementsKindFromMap(kind, x10);
if (FLAG_debug_code) {
Label done;
__ Cmp(x3, PACKED_ELEMENTS);
__ Ccmp(x3, HOLEY_ELEMENTS, ZFlag, ne);
__ Assert(
eq,
AbortReason::kInvalidElementsKindForInternalArrayOrInternalPackedArray);
}
Label fast_elements_case;
__ CompareAndBranch(kind, PACKED_ELEMENTS, eq, &fast_elements_case);
GenerateCase(masm, HOLEY_ELEMENTS);
__ Bind(&fast_elements_case);
GenerateCase(masm, PACKED_ELEMENTS);
}
// The number of register that CallApiFunctionAndReturn will need to save on
// the stack. The space for these registers need to be allocated in the
// ExitFrame before calling CallApiFunctionAndReturn.
......
......@@ -111,8 +111,8 @@ void Builtins::Generate_InternalArrayConstructor(MacroAssembler* masm) {
// function.
// tail call a stub
__ LoadRoot(r2, Heap::kUndefinedValueRootIndex);
InternalArrayConstructorStub stub(masm->isolate());
__ TailCallStub(&stub);
__ Jump(BUILTIN_CODE(masm->isolate(), InternalArrayConstructorImpl),
RelocInfo::CODE_TARGET);
}
void Builtins::Generate_ArrayConstructor(MacroAssembler* masm) {
......@@ -3075,6 +3075,84 @@ void Builtins::Generate_ArrayConstructorImpl(MacroAssembler* masm) {
__ JumpToExternalReference(ExternalReference::Create(Runtime::kNewArray));
}
namespace {
void GenerateInternalArrayConstructorCase(MacroAssembler* masm,
ElementsKind kind) {
__ cmp(r0, Operand(1));
InternalArrayNoArgumentConstructorStub stub0(masm->isolate(), kind);
__ TailCallStub(&stub0, lo);
Handle<Code> code = BUILTIN_CODE(masm->isolate(), ArrayNArgumentsConstructor);
__ Jump(code, RelocInfo::CODE_TARGET, hi);
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());
InternalArraySingleArgumentConstructorStub stub1_holey(
masm->isolate(), GetHoleyElementsKind(kind));
__ TailCallStub(&stub1_holey, ne);
}
InternalArraySingleArgumentConstructorStub stub1(masm->isolate(), kind);
__ TailCallStub(&stub1);
}
} // namespace
void Builtins::Generate_InternalArrayConstructorImpl(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 nullptr and a Smi.
__ tst(r3, Operand(kSmiTagMask));
__ Assert(ne, AbortReason::kUnexpectedInitialMapForArrayFunction);
__ CompareObjectType(r3, r3, r4, MAP_TYPE);
__ Assert(eq, AbortReason::kUnexpectedInitialMapForArrayFunction);
}
// 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.
__ DecodeField<Map::ElementsKindBits>(r3);
if (FLAG_debug_code) {
Label done;
__ cmp(r3, Operand(PACKED_ELEMENTS));
__ b(eq, &done);
__ cmp(r3, Operand(HOLEY_ELEMENTS));
__ Assert(
eq,
AbortReason::kInvalidElementsKindForInternalArrayOrInternalPackedArray);
__ bind(&done);
}
Label fast_elements_case;
__ cmp(r3, Operand(PACKED_ELEMENTS));
__ b(eq, &fast_elements_case);
GenerateInternalArrayConstructorCase(masm, HOLEY_ELEMENTS);
__ bind(&fast_elements_case);
GenerateInternalArrayConstructorCase(masm, PACKED_ELEMENTS);
}
void Builtins::Generate_ArrayNArgumentsConstructor(MacroAssembler* masm) {
__ lsl(r5, r0, Operand(kPointerSizeLog2));
__ str(r1, MemOperand(sp, r5));
......
......@@ -105,8 +105,8 @@ void Builtins::Generate_InternalArrayConstructor(MacroAssembler* masm) {
// Run the native code for the InternalArray function called as a normal
// function.
__ LoadRoot(x2, Heap::kUndefinedValueRootIndex);
InternalArrayConstructorStub stub(masm->isolate());
__ TailCallStub(&stub);
__ Jump(BUILTIN_CODE(masm->isolate(), InternalArrayConstructorImpl),
RelocInfo::CODE_TARGET);
}
void Builtins::Generate_ArrayConstructor(MacroAssembler* masm) {
......@@ -3637,6 +3637,97 @@ void Builtins::Generate_ArrayConstructorImpl(MacroAssembler* masm) {
__ JumpToExternalReference(ExternalReference::Create(Runtime::kNewArray));
}
namespace {
void GenerateInternalArrayConstructorCase(MacroAssembler* masm,
ElementsKind kind) {
Label zero_case, n_case;
Register argc = x0;
__ Cbz(argc, &zero_case);
__ CompareAndBranch(argc, 1, ne, &n_case);
// One argument.
if (IsFastPackedElementsKind(kind)) {
Label packed_case;
// We might need to create a holey array; look at the first argument.
__ Peek(x10, 0);
__ Cbz(x10, &packed_case);
InternalArraySingleArgumentConstructorStub stub1_holey(
masm->isolate(), GetHoleyElementsKind(kind));
__ TailCallStub(&stub1_holey);
__ Bind(&packed_case);
}
InternalArraySingleArgumentConstructorStub stub1(masm->isolate(), kind);
__ TailCallStub(&stub1);
__ Bind(&zero_case);
// No arguments.
InternalArrayNoArgumentConstructorStub stub0(masm->isolate(), kind);
__ TailCallStub(&stub0);
__ Bind(&n_case);
// N arguments.
Handle<Code> code = BUILTIN_CODE(masm->isolate(), ArrayNArgumentsConstructor);
__ Jump(code, RelocInfo::CODE_TARGET);
}
} // namespace
void Builtins::Generate_InternalArrayConstructorImpl(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- x0 : argc
// -- x1 : constructor
// -- sp[0] : return address
// -- sp[4] : last argument
// -----------------------------------
Register constructor = x1;
if (FLAG_debug_code) {
// The array construct code is only set for the global and natives
// builtin Array functions which always have maps.
Label unexpected_map, map_ok;
// Initial map for the builtin Array function should be a map.
__ Ldr(x10, FieldMemOperand(constructor,
JSFunction::kPrototypeOrInitialMapOffset));
// Will both indicate a nullptr and a Smi.
__ JumpIfSmi(x10, &unexpected_map);
__ JumpIfObjectType(x10, x10, x11, MAP_TYPE, &map_ok);
__ Bind(&unexpected_map);
__ Abort(AbortReason::kUnexpectedInitialMapForArrayFunction);
__ Bind(&map_ok);
}
Register kind = w3;
// Figure out the right elements kind
__ Ldr(x10, FieldMemOperand(constructor,
JSFunction::kPrototypeOrInitialMapOffset));
// Retrieve elements_kind from map.
__ LoadElementsKindFromMap(kind, x10);
if (FLAG_debug_code) {
Label done;
__ Cmp(x3, PACKED_ELEMENTS);
__ Ccmp(x3, HOLEY_ELEMENTS, ZFlag, ne);
__ Assert(
eq,
AbortReason::kInvalidElementsKindForInternalArrayOrInternalPackedArray);
}
Label fast_elements_case;
__ CompareAndBranch(kind, PACKED_ELEMENTS, eq, &fast_elements_case);
GenerateInternalArrayConstructorCase(masm, HOLEY_ELEMENTS);
__ Bind(&fast_elements_case);
GenerateInternalArrayConstructorCase(masm, PACKED_ELEMENTS);
}
void Builtins::Generate_ArrayNArgumentsConstructor(MacroAssembler* masm) {
__ Mov(x5, Operand(x0, LSL, kPointerSizeLog2));
__ Poke(x1, Operand(x5));
......
......@@ -239,6 +239,7 @@ namespace internal {
ASM(ArrayConstructorImpl) \
ASM(ArrayNArgumentsConstructor) \
ASM(InternalArrayConstructor) \
ASM(InternalArrayConstructorImpl) \
CPP(ArrayConcat) \
/* ES6 #sec-array.isarray */ \
TFJ(ArrayIsArray, 1, kArg) \
......
......@@ -1915,10 +1915,9 @@ void Builtins::Generate_InternalArrayConstructor(MacroAssembler* masm) {
// Run the native code for the InternalArray function called as a normal
// function.
// tail call a stub
__ mov(ebx, masm->isolate()->factory()->undefined_value());
InternalArrayConstructorStub stub(masm->isolate());
__ TailCallStub(&stub);
__ Jump(BUILTIN_CODE(masm->isolate(), InternalArrayConstructorImpl),
RelocInfo::CODE_TARGET);
}
void Builtins::Generate_ArrayConstructor(MacroAssembler* masm) {
......@@ -3324,6 +3323,95 @@ void Builtins::Generate_ArrayConstructorImpl(MacroAssembler* masm) {
__ JumpToExternalReference(ExternalReference::Create(Runtime::kNewArray));
}
namespace {
void GenerateInternalArrayConstructorCase(MacroAssembler* masm,
ElementsKind kind) {
Label not_zero_case, not_one_case;
Label normal_sequence;
__ test(eax, eax);
__ j(not_zero, &not_zero_case);
InternalArrayNoArgumentConstructorStub stub0(masm->isolate(), kind);
__ TailCallStub(&stub0);
__ bind(&not_zero_case);
__ cmp(eax, 1);
__ j(greater, &not_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(
masm->isolate(), GetHoleyElementsKind(kind));
__ TailCallStub(&stub1_holey);
}
__ bind(&normal_sequence);
InternalArraySingleArgumentConstructorStub stub1(masm->isolate(), kind);
__ TailCallStub(&stub1);
__ bind(&not_one_case);
Handle<Code> code = BUILTIN_CODE(masm->isolate(), ArrayNArgumentsConstructor);
__ Jump(code, RelocInfo::CODE_TARGET);
}
} // namespace
void Builtins::Generate_InternalArrayConstructorImpl(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- eax : argc
// -- 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 nullptr and a Smi.
__ test(ecx, Immediate(kSmiTagMask));
__ Assert(not_zero, AbortReason::kUnexpectedInitialMapForArrayFunction);
__ CmpObjectType(ecx, MAP_TYPE, ecx);
__ Assert(equal, AbortReason::kUnexpectedInitialMapForArrayFunction);
}
// 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.
__ DecodeField<Map::ElementsKindBits>(ecx);
if (FLAG_debug_code) {
Label done;
__ cmp(ecx, Immediate(PACKED_ELEMENTS));
__ j(equal, &done);
__ cmp(ecx, Immediate(HOLEY_ELEMENTS));
__ Assert(
equal,
AbortReason::kInvalidElementsKindForInternalArrayOrInternalPackedArray);
__ bind(&done);
}
Label fast_elements_case;
__ cmp(ecx, Immediate(PACKED_ELEMENTS));
__ j(equal, &fast_elements_case);
GenerateInternalArrayConstructorCase(masm, HOLEY_ELEMENTS);
__ bind(&fast_elements_case);
GenerateInternalArrayConstructorCase(masm, PACKED_ELEMENTS);
}
void Builtins::Generate_ArrayNArgumentsConstructor(MacroAssembler* masm) {
__ pop(ecx);
__ mov(MemOperand(esp, eax, times_4, 0), edi);
......
......@@ -106,10 +106,9 @@ void Builtins::Generate_InternalArrayConstructor(MacroAssembler* masm) {
// Run the native code for the InternalArray function called as a normal
// function.
// Tail call a stub.
__ LoadRoot(a2, Heap::kUndefinedValueRootIndex);
InternalArrayConstructorStub stub(masm->isolate());
__ TailCallStub(&stub);
__ Jump(BUILTIN_CODE(masm->isolate(), InternalArrayConstructorImpl),
RelocInfo::CODE_TARGET);
}
void Builtins::Generate_ArrayConstructor(MacroAssembler* masm) {
......@@ -3201,6 +3200,82 @@ void Builtins::Generate_ArrayConstructorImpl(MacroAssembler* masm) {
__ JumpToExternalReference(ExternalReference::Create(Runtime::kNewArray));
}
namespace {
void GenerateInternalArrayConstructorCase(MacroAssembler* masm,
ElementsKind kind) {
InternalArrayNoArgumentConstructorStub stub0(masm->isolate(), kind);
__ TailCallStub(&stub0, lo, a0, Operand(1));
__ Jump(BUILTIN_CODE(masm->isolate(), ArrayNArgumentsConstructor),
RelocInfo::CODE_TARGET, hi, a0, Operand(1));
if (IsFastPackedElementsKind(kind)) {
// We might need to create a holey array
// look at the first argument.
__ lw(kScratchReg, MemOperand(sp, 0));
InternalArraySingleArgumentConstructorStub stub1_holey(
masm->isolate(), GetHoleyElementsKind(kind));
__ TailCallStub(&stub1_holey, ne, kScratchReg, Operand(zero_reg));
}
InternalArraySingleArgumentConstructorStub stub1(masm->isolate(), kind);
__ TailCallStub(&stub1);
}
} // namespace
void Builtins::Generate_InternalArrayConstructorImpl(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- a0 : argc
// -- a1 : 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.
__ lw(a3, FieldMemOperand(a1, JSFunction::kPrototypeOrInitialMapOffset));
// Will both indicate a nullptr and a Smi.
__ SmiTst(a3, kScratchReg);
__ Assert(ne, AbortReason::kUnexpectedInitialMapForArrayFunction,
kScratchReg, Operand(zero_reg));
__ GetObjectType(a3, a3, t0);
__ Assert(eq, AbortReason::kUnexpectedInitialMapForArrayFunction, t0,
Operand(MAP_TYPE));
}
// Figure out the right elements kind.
__ lw(a3, FieldMemOperand(a1, JSFunction::kPrototypeOrInitialMapOffset));
// Load the map's "bit field 2" into a3. We only need the first byte,
// but the following bit field extraction takes care of that anyway.
__ lbu(a3, FieldMemOperand(a3, Map::kBitField2Offset));
// Retrieve elements_kind from bit field 2.
__ DecodeField<Map::ElementsKindBits>(a3);
if (FLAG_debug_code) {
Label done;
__ Branch(&done, eq, a3, Operand(PACKED_ELEMENTS));
__ Assert(
eq,
AbortReason::kInvalidElementsKindForInternalArrayOrInternalPackedArray,
a3, Operand(HOLEY_ELEMENTS));
__ bind(&done);
}
Label fast_elements_case;
__ Branch(&fast_elements_case, eq, a3, Operand(PACKED_ELEMENTS));
GenerateInternalArrayConstructorCase(masm, HOLEY_ELEMENTS);
__ bind(&fast_elements_case);
GenerateInternalArrayConstructorCase(masm, PACKED_ELEMENTS);
}
void Builtins::Generate_ArrayNArgumentsConstructor(MacroAssembler* masm) {
__ sll(t9, a0, kPointerSizeLog2);
__ Addu(t9, sp, t9);
......
......@@ -106,10 +106,9 @@ void Builtins::Generate_InternalArrayConstructor(MacroAssembler* masm) {
// Run the native code for the InternalArray function called as a normal
// function.
// Tail call a stub.
__ LoadRoot(a2, Heap::kUndefinedValueRootIndex);
InternalArrayConstructorStub stub(masm->isolate());
__ TailCallStub(&stub);
__ Jump(BUILTIN_CODE(masm->isolate(), InternalArrayConstructorImpl),
RelocInfo::CODE_TARGET);
}
void Builtins::Generate_ArrayConstructor(MacroAssembler* masm) {
......@@ -3223,6 +3222,82 @@ void Builtins::Generate_ArrayConstructorImpl(MacroAssembler* masm) {
__ JumpToExternalReference(ExternalReference::Create(Runtime::kNewArray));
}
namespace {
void GenerateInternalArrayConstructorCase(MacroAssembler* masm,
ElementsKind kind) {
InternalArrayNoArgumentConstructorStub stub0(masm->isolate(), kind);
__ TailCallStub(&stub0, lo, a0, Operand(1));
__ Jump(BUILTIN_CODE(masm->isolate(), ArrayNArgumentsConstructor),
RelocInfo::CODE_TARGET, hi, a0, Operand(1));
if (IsFastPackedElementsKind(kind)) {
// We might need to create a holey array
// look at the first argument.
__ Ld(kScratchReg, MemOperand(sp, 0));
InternalArraySingleArgumentConstructorStub stub1_holey(
masm->isolate(), GetHoleyElementsKind(kind));
__ TailCallStub(&stub1_holey, ne, kScratchReg, Operand(zero_reg));
}
InternalArraySingleArgumentConstructorStub stub1(masm->isolate(), kind);
__ TailCallStub(&stub1);
}
} // namespace
void Builtins::Generate_InternalArrayConstructorImpl(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- a0 : argc
// -- a1 : 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.
__ Ld(a3, FieldMemOperand(a1, JSFunction::kPrototypeOrInitialMapOffset));
// Will both indicate a nullptr and a Smi.
__ SmiTst(a3, kScratchReg);
__ Assert(ne, AbortReason::kUnexpectedInitialMapForArrayFunction,
kScratchReg, Operand(zero_reg));
__ GetObjectType(a3, a3, a4);
__ Assert(eq, AbortReason::kUnexpectedInitialMapForArrayFunction, a4,
Operand(MAP_TYPE));
}
// Figure out the right elements kind.
__ Ld(a3, FieldMemOperand(a1, JSFunction::kPrototypeOrInitialMapOffset));
// Load the map's "bit field 2" into a3. We only need the first byte,
// but the following bit field extraction takes care of that anyway.
__ Lbu(a3, FieldMemOperand(a3, Map::kBitField2Offset));
// Retrieve elements_kind from bit field 2.
__ DecodeField<Map::ElementsKindBits>(a3);
if (FLAG_debug_code) {
Label done;
__ Branch(&done, eq, a3, Operand(PACKED_ELEMENTS));
__ Assert(
eq,
AbortReason::kInvalidElementsKindForInternalArrayOrInternalPackedArray,
a3, Operand(HOLEY_ELEMENTS));
__ bind(&done);
}
Label fast_elements_case;
__ Branch(&fast_elements_case, eq, a3, Operand(PACKED_ELEMENTS));
GenerateInternalArrayConstructorCase(masm, HOLEY_ELEMENTS);
__ bind(&fast_elements_case);
GenerateInternalArrayConstructorCase(masm, PACKED_ELEMENTS);
}
void Builtins::Generate_ArrayNArgumentsConstructor(MacroAssembler* masm) {
__ dsll(t9, a0, kPointerSizeLog2);
__ Daddu(t9, sp, t9);
......
......@@ -1895,10 +1895,9 @@ void Builtins::Generate_InternalArrayConstructor(MacroAssembler* masm) {
// Run the native code for the InternalArray function called as a normal
// function.
// tail call a stub
__ LoadRoot(rbx, Heap::kUndefinedValueRootIndex);
InternalArrayConstructorStub stub(masm->isolate());
__ TailCallStub(&stub);
__ Jump(BUILTIN_CODE(masm->isolate(), InternalArrayConstructorImpl),
RelocInfo::CODE_TARGET);
}
void Builtins::Generate_ArrayConstructor(MacroAssembler* masm) {
......@@ -3273,6 +3272,97 @@ void Builtins::Generate_ArrayConstructorImpl(MacroAssembler* masm) {
__ JumpToExternalReference(ExternalReference::Create(Runtime::kNewArray));
}
namespace {
void GenerateInternalArrayConstructorCase(MacroAssembler* masm,
ElementsKind kind) {
Label not_zero_case, not_one_case;
Label normal_sequence;
__ testp(rax, rax);
__ j(not_zero, &not_zero_case);
InternalArrayNoArgumentConstructorStub stub0(masm->isolate(), kind);
__ TailCallStub(&stub0);
__ bind(&not_zero_case);
__ cmpl(rax, Immediate(1));
__ j(greater, &not_one_case);
if (IsFastPackedElementsKind(kind)) {
// We might need to create a holey array
// look at the first argument
StackArgumentsAccessor args(rsp, 1, ARGUMENTS_DONT_CONTAIN_RECEIVER);
__ movp(rcx, args.GetArgumentOperand(0));
__ testp(rcx, rcx);
__ j(zero, &normal_sequence);
InternalArraySingleArgumentConstructorStub stub1_holey(
masm->isolate(), GetHoleyElementsKind(kind));
__ TailCallStub(&stub1_holey);
}
__ bind(&normal_sequence);
InternalArraySingleArgumentConstructorStub stub1(masm->isolate(), kind);
__ TailCallStub(&stub1);
__ bind(&not_one_case);
Handle<Code> code = BUILTIN_CODE(masm->isolate(), ArrayNArgumentsConstructor);
__ Jump(code, RelocInfo::CODE_TARGET);
}
} // namespace
void Builtins::Generate_InternalArrayConstructorImpl(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- rax : argc
// -- rdi : constructor
// -- rsp[0] : return address
// -- rsp[8] : 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.
__ movp(rcx, FieldOperand(rdi, JSFunction::kPrototypeOrInitialMapOffset));
// Will both indicate a nullptr and a Smi.
STATIC_ASSERT(kSmiTag == 0);
Condition not_smi = NegateCondition(masm->CheckSmi(rcx));
__ Check(not_smi, AbortReason::kUnexpectedInitialMapForArrayFunction);
__ CmpObjectType(rcx, MAP_TYPE, rcx);
__ Check(equal, AbortReason::kUnexpectedInitialMapForArrayFunction);
}
// Figure out the right elements kind
__ movp(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.
__ movzxbp(rcx, FieldOperand(rcx, Map::kBitField2Offset));
// Retrieve elements_kind from bit field 2.
__ DecodeField<Map::ElementsKindBits>(rcx);
if (FLAG_debug_code) {
Label done;
__ cmpl(rcx, Immediate(PACKED_ELEMENTS));
__ j(equal, &done);
__ cmpl(rcx, Immediate(HOLEY_ELEMENTS));
__ Assert(
equal,
AbortReason::kInvalidElementsKindForInternalArrayOrInternalPackedArray);
__ bind(&done);
}
Label fast_elements_case;
__ cmpl(rcx, Immediate(PACKED_ELEMENTS));
__ j(equal, &fast_elements_case);
GenerateInternalArrayConstructorCase(masm, HOLEY_ELEMENTS);
__ bind(&fast_elements_case);
GenerateInternalArrayConstructorCase(masm, PACKED_ELEMENTS);
}
void Builtins::Generate_ArrayNArgumentsConstructor(MacroAssembler* masm) {
__ popq(rcx);
__ movq(MemOperand(rsp, rax, times_8, 0), rdi);
......
......@@ -592,9 +592,6 @@ TF_STUB(InternalArraySingleArgumentConstructorStub, ArrayConstructorAssembler) {
stub->elements_kind(), DONT_TRACK_ALLOCATION_SITE);
}
InternalArrayConstructorStub::InternalArrayConstructorStub(Isolate* isolate)
: PlatformCodeStub(isolate) {}
CommonArrayConstructorStub::CommonArrayConstructorStub(
Isolate* isolate, ElementsKind kind,
AllocationSiteOverrideMode override_mode)
......
......@@ -30,7 +30,6 @@ class Node;
/* --- PlatformCodeStubs --- */ \
V(CallApiCallback) \
V(CallApiGetter) \
V(InternalArrayConstructor) \
V(JSEntry) \
V(ProfileEntryHook) \
/* --- TurboFanCodeStubs --- */ \
......@@ -484,18 +483,6 @@ enum AllocationSiteOverrideMode {
LAST_ALLOCATION_SITE_OVERRIDE_MODE = DISABLE_ALLOCATION_SITES
};
// TODO(jgruber): Convert this stub into a builtin.
class InternalArrayConstructorStub: public PlatformCodeStub {
public:
explicit InternalArrayConstructorStub(Isolate* isolate);
private:
void GenerateCase(MacroAssembler* masm, ElementsKind kind);
DEFINE_CALL_INTERFACE_DESCRIPTOR(ArrayNArgumentsConstructor);
DEFINE_PLATFORM_CODE_STUB(InternalArrayConstructor, PlatformCodeStub);
};
// TODO(jgruber): Convert this stub into a builtin.
class KeyedLoadSloppyArgumentsStub : public TurboFanCodeStub {
public:
......
......@@ -194,92 +194,6 @@ void CommonArrayConstructorStub::GenerateStubsAheadOfTime(Isolate* isolate) {
}
}
void InternalArrayConstructorStub::GenerateCase(
MacroAssembler* masm, ElementsKind kind) {
Label not_zero_case, not_one_case;
Label normal_sequence;
__ test(eax, eax);
__ j(not_zero, &not_zero_case);
InternalArrayNoArgumentConstructorStub stub0(isolate(), kind);
__ TailCallStub(&stub0);
__ bind(&not_zero_case);
__ cmp(eax, 1);
__ j(greater, &not_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(isolate(), GetHoleyElementsKind(kind));
__ TailCallStub(&stub1_holey);
}
__ bind(&normal_sequence);
InternalArraySingleArgumentConstructorStub stub1(isolate(), kind);
__ TailCallStub(&stub1);
__ bind(&not_one_case);
__ Jump(BUILTIN_CODE(masm->isolate(), ArrayNArgumentsConstructor),
RelocInfo::CODE_TARGET);
}
void InternalArrayConstructorStub::Generate(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- eax : argc
// -- 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 nullptr and a Smi.
__ test(ecx, Immediate(kSmiTagMask));
__ Assert(not_zero, AbortReason::kUnexpectedInitialMapForArrayFunction);
__ CmpObjectType(ecx, MAP_TYPE, ecx);
__ Assert(equal, AbortReason::kUnexpectedInitialMapForArrayFunction);
}
// 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.
__ DecodeField<Map::ElementsKindBits>(ecx);
if (FLAG_debug_code) {
Label done;
__ cmp(ecx, Immediate(PACKED_ELEMENTS));
__ j(equal, &done);
__ cmp(ecx, Immediate(HOLEY_ELEMENTS));
__ Assert(
equal,
AbortReason::kInvalidElementsKindForInternalArrayOrInternalPackedArray);
__ bind(&done);
}
Label fast_elements_case;
__ cmp(ecx, Immediate(PACKED_ELEMENTS));
__ j(equal, &fast_elements_case);
GenerateCase(masm, HOLEY_ELEMENTS);
__ bind(&fast_elements_case);
GenerateCase(masm, PACKED_ELEMENTS);
}
// Generates an Operand for saving parameters after PrepareCallApiFunction.
static Operand ApiParameterOperand(int index) {
return Operand(esp, index * kPointerSize);
......
......@@ -342,80 +342,6 @@ void CommonArrayConstructorStub::GenerateStubsAheadOfTime(Isolate* isolate) {
}
}
void InternalArrayConstructorStub::GenerateCase(
MacroAssembler* masm, ElementsKind kind) {
InternalArrayNoArgumentConstructorStub stub0(isolate(), kind);
__ TailCallStub(&stub0, lo, a0, Operand(1));
__ Jump(BUILTIN_CODE(masm->isolate(), ArrayNArgumentsConstructor),
RelocInfo::CODE_TARGET, hi, a0, Operand(1));
if (IsFastPackedElementsKind(kind)) {
// We might need to create a holey array
// look at the first argument.
__ lw(kScratchReg, MemOperand(sp, 0));
InternalArraySingleArgumentConstructorStub
stub1_holey(isolate(), GetHoleyElementsKind(kind));
__ TailCallStub(&stub1_holey, ne, kScratchReg, Operand(zero_reg));
}
InternalArraySingleArgumentConstructorStub stub1(isolate(), kind);
__ TailCallStub(&stub1);
}
void InternalArrayConstructorStub::Generate(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- a0 : argc
// -- a1 : 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.
__ lw(a3, FieldMemOperand(a1, JSFunction::kPrototypeOrInitialMapOffset));
// Will both indicate a nullptr and a Smi.
__ SmiTst(a3, kScratchReg);
__ Assert(ne, AbortReason::kUnexpectedInitialMapForArrayFunction,
kScratchReg, Operand(zero_reg));
__ GetObjectType(a3, a3, t0);
__ Assert(eq, AbortReason::kUnexpectedInitialMapForArrayFunction, t0,
Operand(MAP_TYPE));
}
// Figure out the right elements kind.
__ lw(a3, FieldMemOperand(a1, JSFunction::kPrototypeOrInitialMapOffset));
// Load the map's "bit field 2" into a3. We only need the first byte,
// but the following bit field extraction takes care of that anyway.
__ lbu(a3, FieldMemOperand(a3, Map::kBitField2Offset));
// Retrieve elements_kind from bit field 2.
__ DecodeField<Map::ElementsKindBits>(a3);
if (FLAG_debug_code) {
Label done;
__ Branch(&done, eq, a3, Operand(PACKED_ELEMENTS));
__ Assert(
eq,
AbortReason::kInvalidElementsKindForInternalArrayOrInternalPackedArray,
a3, Operand(HOLEY_ELEMENTS));
__ bind(&done);
}
Label fast_elements_case;
__ Branch(&fast_elements_case, eq, a3, Operand(PACKED_ELEMENTS));
GenerateCase(masm, HOLEY_ELEMENTS);
__ bind(&fast_elements_case);
GenerateCase(masm, PACKED_ELEMENTS);
}
static int AddressOffset(ExternalReference ref0, ExternalReference ref1) {
return ref0.address() - ref1.address();
}
......
......@@ -344,81 +344,6 @@ void CommonArrayConstructorStub::GenerateStubsAheadOfTime(Isolate* isolate) {
}
}
void InternalArrayConstructorStub::GenerateCase(
MacroAssembler* masm, ElementsKind kind) {
InternalArrayNoArgumentConstructorStub stub0(isolate(), kind);
__ TailCallStub(&stub0, lo, a0, Operand(1));
__ Jump(BUILTIN_CODE(masm->isolate(), ArrayNArgumentsConstructor),
RelocInfo::CODE_TARGET, hi, a0, Operand(1));
if (IsFastPackedElementsKind(kind)) {
// We might need to create a holey array
// look at the first argument.
__ Ld(kScratchReg, MemOperand(sp, 0));
InternalArraySingleArgumentConstructorStub
stub1_holey(isolate(), GetHoleyElementsKind(kind));
__ TailCallStub(&stub1_holey, ne, kScratchReg, Operand(zero_reg));
}
InternalArraySingleArgumentConstructorStub stub1(isolate(), kind);
__ TailCallStub(&stub1);
}
void InternalArrayConstructorStub::Generate(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- a0 : argc
// -- a1 : 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.
__ Ld(a3, FieldMemOperand(a1, JSFunction::kPrototypeOrInitialMapOffset));
// Will both indicate a nullptr and a Smi.
__ SmiTst(a3, kScratchReg);
__ Assert(ne, AbortReason::kUnexpectedInitialMapForArrayFunction,
kScratchReg, Operand(zero_reg));
__ GetObjectType(a3, a3, a4);
__ Assert(eq, AbortReason::kUnexpectedInitialMapForArrayFunction, a4,
Operand(MAP_TYPE));
}
// Figure out the right elements kind.
__ Ld(a3, FieldMemOperand(a1, JSFunction::kPrototypeOrInitialMapOffset));
// Load the map's "bit field 2" into a3. We only need the first byte,
// but the following bit field extraction takes care of that anyway.
__ Lbu(a3, FieldMemOperand(a3, Map::kBitField2Offset));
// Retrieve elements_kind from bit field 2.
__ DecodeField<Map::ElementsKindBits>(a3);
if (FLAG_debug_code) {
Label done;
__ Branch(&done, eq, a3, Operand(PACKED_ELEMENTS));
__ Assert(
eq,
AbortReason::kInvalidElementsKindForInternalArrayOrInternalPackedArray,
a3, Operand(HOLEY_ELEMENTS));
__ bind(&done);
}
Label fast_elements_case;
__ Branch(&fast_elements_case, eq, a3, Operand(PACKED_ELEMENTS));
GenerateCase(masm, HOLEY_ELEMENTS);
__ bind(&fast_elements_case);
GenerateCase(masm, PACKED_ELEMENTS);
}
static int AddressOffset(ExternalReference ref0, ExternalReference ref1) {
int64_t offset = (ref0.address() - ref1.address());
DCHECK(static_cast<int>(offset) == offset);
......
......@@ -261,94 +261,6 @@ void CommonArrayConstructorStub::GenerateStubsAheadOfTime(Isolate* isolate) {
}
}
void InternalArrayConstructorStub::GenerateCase(
MacroAssembler* masm, ElementsKind kind) {
Label not_zero_case, not_one_case;
Label normal_sequence;
__ testp(rax, rax);
__ j(not_zero, &not_zero_case);
InternalArrayNoArgumentConstructorStub stub0(isolate(), kind);
__ TailCallStub(&stub0);
__ bind(&not_zero_case);
__ cmpl(rax, Immediate(1));
__ j(greater, &not_one_case);
if (IsFastPackedElementsKind(kind)) {
// We might need to create a holey array
// look at the first argument
StackArgumentsAccessor args(rsp, 1, ARGUMENTS_DONT_CONTAIN_RECEIVER);
__ movp(rcx, args.GetArgumentOperand(0));
__ testp(rcx, rcx);
__ j(zero, &normal_sequence);
InternalArraySingleArgumentConstructorStub
stub1_holey(isolate(), GetHoleyElementsKind(kind));
__ TailCallStub(&stub1_holey);
}
__ bind(&normal_sequence);
InternalArraySingleArgumentConstructorStub stub1(isolate(), kind);
__ TailCallStub(&stub1);
__ bind(&not_one_case);
__ Jump(BUILTIN_CODE(masm->isolate(), ArrayNArgumentsConstructor),
RelocInfo::CODE_TARGET);
}
void InternalArrayConstructorStub::Generate(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- rax : argc
// -- rdi : constructor
// -- rsp[0] : return address
// -- rsp[8] : 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.
__ movp(rcx, FieldOperand(rdi, JSFunction::kPrototypeOrInitialMapOffset));
// Will both indicate a nullptr and a Smi.
STATIC_ASSERT(kSmiTag == 0);
Condition not_smi = NegateCondition(masm->CheckSmi(rcx));
__ Check(not_smi, AbortReason::kUnexpectedInitialMapForArrayFunction);
__ CmpObjectType(rcx, MAP_TYPE, rcx);
__ Check(equal, AbortReason::kUnexpectedInitialMapForArrayFunction);
}
// Figure out the right elements kind
__ movp(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.
__ movzxbp(rcx, FieldOperand(rcx, Map::kBitField2Offset));
// Retrieve elements_kind from bit field 2.
__ DecodeField<Map::ElementsKindBits>(rcx);
if (FLAG_debug_code) {
Label done;
__ cmpl(rcx, Immediate(PACKED_ELEMENTS));
__ j(equal, &done);
__ cmpl(rcx, Immediate(HOLEY_ELEMENTS));
__ Assert(
equal,
AbortReason::kInvalidElementsKindForInternalArrayOrInternalPackedArray);
__ bind(&done);
}
Label fast_elements_case;
__ cmpl(rcx, Immediate(PACKED_ELEMENTS));
__ j(equal, &fast_elements_case);
GenerateCase(masm, HOLEY_ELEMENTS);
__ bind(&fast_elements_case);
GenerateCase(masm, PACKED_ELEMENTS);
}
static int Offset(ExternalReference ref0, ExternalReference ref1) {
int64_t offset = (ref0.address() - ref1.address());
// Check that fits into int.
......
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