[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/1072608 Reviewed-by: Igor Sheludko <ishell@chromium.org> Commit-Queue: Jakob Gruber <jgruber@chromium.org> Cr-Commit-Position: refs/heads/master@{#53360}
This commit is contained in:
parent
f83d858750
commit
7d161e4d38
@ -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, ¬_zero_case);
|
||||
InternalArrayNoArgumentConstructorStub stub0(masm->isolate(), 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(
|
||||
masm->isolate(), GetHoleyElementsKind(kind));
|
||||
__ TailCallStub(&stub1_holey);
|
||||
}
|
||||
|
||||
__ bind(&normal_sequence);
|
||||
InternalArraySingleArgumentConstructorStub stub1(masm->isolate(), kind);
|
||||
__ TailCallStub(&stub1);
|
||||
|
||||
__ bind(¬_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, ¬_zero_case);
|
||||
InternalArrayNoArgumentConstructorStub stub0(masm->isolate(), 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
|
||||
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(¬_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, ¬_zero_case);
|
||||
InternalArrayNoArgumentConstructorStub stub0(isolate(), 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(isolate(), GetHoleyElementsKind(kind));
|
||||
__ TailCallStub(&stub1_holey);
|
||||
}
|
||||
|
||||
__ bind(&normal_sequence);
|
||||
InternalArraySingleArgumentConstructorStub stub1(isolate(), kind);
|
||||
__ TailCallStub(&stub1);
|
||||
|
||||
__ bind(¬_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, ¬_zero_case);
|
||||
InternalArrayNoArgumentConstructorStub stub0(isolate(), 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
|
||||
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(¬_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.
|
||||
|
Loading…
Reference in New Issue
Block a user