Bugfix: array constructors that expect a type feedback cell that points

to an AllocationSite were being passed the undefined object in some
cases. Clearly separate the cases where we have an AllocationSite and
where we don't in the general ArrayConstructorStub.

BUG=
R=mstarzinger@chromium.org

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@16693 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent ff412d8c
...@@ -6837,90 +6837,128 @@ void ProfileEntryHookStub::Generate(MacroAssembler* masm) { ...@@ -6837,90 +6837,128 @@ void ProfileEntryHookStub::Generate(MacroAssembler* masm) {
template<class T> template<class T>
static void CreateArrayDispatch(MacroAssembler* masm) { static void CreateArrayDispatch(MacroAssembler* masm,
int last_index = GetSequenceIndexFromFastElementsKind( AllocationSiteOverrideMode mode) {
TERMINAL_FAST_ELEMENTS_KIND); if (mode == DISABLE_ALLOCATION_SITES) {
for (int i = 0; i <= last_index; ++i) { T stub(GetInitialFastElementsKind(),
Label next; CONTEXT_CHECK_REQUIRED,
ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); mode);
__ cmp(r3, Operand(kind));
__ b(ne, &next);
T stub(kind);
__ TailCallStub(&stub); __ TailCallStub(&stub);
__ bind(&next); } else if (mode == DONT_OVERRIDE) {
} int last_index = GetSequenceIndexFromFastElementsKind(
TERMINAL_FAST_ELEMENTS_KIND);
for (int i = 0; i <= last_index; ++i) {
Label next;
ElementsKind kind = GetFastElementsKindFromSequenceIndex(i);
__ cmp(r3, Operand(kind));
__ b(ne, &next);
T stub(kind);
__ TailCallStub(&stub);
__ bind(&next);
}
// If we reached this point there is a problem. // If we reached this point there is a problem.
__ Abort(kUnexpectedElementsKindInArrayConstructor); __ Abort(kUnexpectedElementsKindInArrayConstructor);
} else {
UNREACHABLE();
}
} }
static void CreateArrayDispatchOneArgument(MacroAssembler* masm) { static void CreateArrayDispatchOneArgument(MacroAssembler* masm,
// r2 - type info cell AllocationSiteOverrideMode mode) {
// r3 - kind // r2 - type info cell (if mode != DISABLE_ALLOCATION_SITES)
// r3 - kind (if mode != DISABLE_ALLOCATION_SITES)
// r0 - number of arguments // r0 - number of arguments
// r1 - constructor? // r1 - constructor?
// sp[0] - last argument // sp[0] - last argument
ASSERT(FAST_SMI_ELEMENTS == 0);
ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1);
ASSERT(FAST_ELEMENTS == 2);
ASSERT(FAST_HOLEY_ELEMENTS == 3);
ASSERT(FAST_DOUBLE_ELEMENTS == 4);
ASSERT(FAST_HOLEY_DOUBLE_ELEMENTS == 5);
// is the low bit set? If so, we are holey and that is good.
__ tst(r3, Operand(1));
Label normal_sequence; Label normal_sequence;
__ b(ne, &normal_sequence); if (mode == DONT_OVERRIDE) {
ASSERT(FAST_SMI_ELEMENTS == 0);
ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1);
ASSERT(FAST_ELEMENTS == 2);
ASSERT(FAST_HOLEY_ELEMENTS == 3);
ASSERT(FAST_DOUBLE_ELEMENTS == 4);
ASSERT(FAST_HOLEY_DOUBLE_ELEMENTS == 5);
// is the low bit set? If so, we are holey and that is good.
__ tst(r3, Operand(1));
__ b(ne, &normal_sequence);
}
// look at the first argument // look at the first argument
__ ldr(r5, MemOperand(sp, 0)); __ ldr(r5, MemOperand(sp, 0));
__ cmp(r5, Operand::Zero()); __ cmp(r5, Operand::Zero());
__ b(eq, &normal_sequence); __ b(eq, &normal_sequence);
// We are going to create a holey array, but our kind is non-holey. if (mode == DISABLE_ALLOCATION_SITES) {
// Fix kind and retry (only if we have an allocation site in the cell). ElementsKind initial = GetInitialFastElementsKind();
__ add(r3, r3, Operand(1)); ElementsKind holey_initial = GetHoleyElementsKind(initial);
__ CompareRoot(r2, Heap::kUndefinedValueRootIndex);
__ b(eq, &normal_sequence);
__ ldr(r5, FieldMemOperand(r2, Cell::kValueOffset));
__ ldr(r5, FieldMemOperand(r5, 0));
__ CompareRoot(r5, Heap::kAllocationSiteMapRootIndex);
__ b(ne, &normal_sequence);
// Save the resulting elements kind in type info ArraySingleArgumentConstructorStub stub_holey(holey_initial,
__ SmiTag(r3); CONTEXT_CHECK_REQUIRED,
__ ldr(r5, FieldMemOperand(r2, Cell::kValueOffset)); DISABLE_ALLOCATION_SITES);
__ str(r3, FieldMemOperand(r5, AllocationSite::kTransitionInfoOffset)); __ TailCallStub(&stub_holey);
__ SmiUntag(r3);
__ bind(&normal_sequence); __ bind(&normal_sequence);
int last_index = GetSequenceIndexFromFastElementsKind( ArraySingleArgumentConstructorStub stub(initial,
TERMINAL_FAST_ELEMENTS_KIND); CONTEXT_CHECK_REQUIRED,
for (int i = 0; i <= last_index; ++i) { DISABLE_ALLOCATION_SITES);
Label next;
ElementsKind kind = GetFastElementsKindFromSequenceIndex(i);
__ cmp(r3, Operand(kind));
__ b(ne, &next);
ArraySingleArgumentConstructorStub stub(kind);
__ TailCallStub(&stub); __ TailCallStub(&stub);
__ bind(&next); } else if (mode == DONT_OVERRIDE) {
} // 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 cell).
__ add(r3, r3, Operand(1));
__ ldr(r5, FieldMemOperand(r2, Cell::kValueOffset));
if (FLAG_debug_code) {
__ ldr(r5, FieldMemOperand(r5, 0));
__ CompareRoot(r5, Heap::kAllocationSiteMapRootIndex);
__ Assert(eq, kExpectedAllocationSiteInCell);
__ ldr(r5, FieldMemOperand(r2, Cell::kValueOffset));
}
// If we reached this point there is a problem. // Save the resulting elements kind in type info
__ Abort(kUnexpectedElementsKindInArrayConstructor); __ SmiTag(r3);
__ ldr(r5, FieldMemOperand(r2, Cell::kValueOffset));
__ str(r3, FieldMemOperand(r5, AllocationSite::kTransitionInfoOffset));
__ SmiUntag(r3);
__ bind(&normal_sequence);
int last_index = GetSequenceIndexFromFastElementsKind(
TERMINAL_FAST_ELEMENTS_KIND);
for (int i = 0; i <= last_index; ++i) {
Label next;
ElementsKind kind = GetFastElementsKindFromSequenceIndex(i);
__ cmp(r3, Operand(kind));
__ b(ne, &next);
ArraySingleArgumentConstructorStub stub(kind);
__ TailCallStub(&stub);
__ bind(&next);
}
// If we reached this point there is a problem.
__ Abort(kUnexpectedElementsKindInArrayConstructor);
} else {
UNREACHABLE();
}
} }
template<class T> template<class T>
static void ArrayConstructorStubAheadOfTimeHelper(Isolate* isolate) { static void ArrayConstructorStubAheadOfTimeHelper(Isolate* isolate) {
ElementsKind initial_kind = GetInitialFastElementsKind();
ElementsKind initial_holey_kind = GetHoleyElementsKind(initial_kind);
int to_index = GetSequenceIndexFromFastElementsKind( int to_index = GetSequenceIndexFromFastElementsKind(
TERMINAL_FAST_ELEMENTS_KIND); TERMINAL_FAST_ELEMENTS_KIND);
for (int i = 0; i <= to_index; ++i) { for (int i = 0; i <= to_index; ++i) {
ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); ElementsKind kind = GetFastElementsKindFromSequenceIndex(i);
T stub(kind); T stub(kind);
stub.GetCode(isolate)->set_is_pregenerated(true); stub.GetCode(isolate)->set_is_pregenerated(true);
if (AllocationSite::GetMode(kind) != DONT_TRACK_ALLOCATION_SITE) { if (AllocationSite::GetMode(kind) != DONT_TRACK_ALLOCATION_SITE ||
(!FLAG_track_allocation_sites &&
(kind == initial_kind || kind == initial_holey_kind))) {
T stub1(kind, CONTEXT_CHECK_REQUIRED, DISABLE_ALLOCATION_SITES); T stub1(kind, CONTEXT_CHECK_REQUIRED, DISABLE_ALLOCATION_SITES);
stub1.GetCode(isolate)->set_is_pregenerated(true); stub1.GetCode(isolate)->set_is_pregenerated(true);
} }
...@@ -6953,6 +6991,34 @@ void InternalArrayConstructorStubBase::GenerateStubsAheadOfTime( ...@@ -6953,6 +6991,34 @@ void InternalArrayConstructorStubBase::GenerateStubsAheadOfTime(
} }
void ArrayConstructorStub::GenerateDispatchToArrayStub(
MacroAssembler* masm,
AllocationSiteOverrideMode mode) {
if (argument_count_ == ANY) {
Label not_zero_case, not_one_case;
__ tst(r0, r0);
__ b(ne, &not_zero_case);
CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm, mode);
__ bind(&not_zero_case);
__ cmp(r0, Operand(1));
__ b(gt, &not_one_case);
CreateArrayDispatchOneArgument(masm, mode);
__ bind(&not_one_case);
CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm, mode);
} else if (argument_count_ == NONE) {
CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm, mode);
} else if (argument_count_ == ONE) {
CreateArrayDispatchOneArgument(masm, mode);
} else if (argument_count_ == MORE_THAN_ONE) {
CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm, mode);
} else {
UNREACHABLE();
}
}
void ArrayConstructorStub::Generate(MacroAssembler* masm) { void ArrayConstructorStub::Generate(MacroAssembler* masm) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- r0 : argc (only if argument_count_ == ANY) // -- r0 : argc (only if argument_count_ == ANY)
...@@ -6984,50 +7050,24 @@ void ArrayConstructorStub::Generate(MacroAssembler* masm) { ...@@ -6984,50 +7050,24 @@ void ArrayConstructorStub::Generate(MacroAssembler* masm) {
__ bind(&okay_here); __ bind(&okay_here);
} }
Label no_info, switch_ready; Label no_info;
// Get the elements kind and case on that. // Get the elements kind and case on that.
__ CompareRoot(r2, Heap::kUndefinedValueRootIndex); __ CompareRoot(r2, Heap::kUndefinedValueRootIndex);
__ b(eq, &no_info); __ b(eq, &no_info);
__ ldr(r3, FieldMemOperand(r2, Cell::kValueOffset)); __ ldr(r3, FieldMemOperand(r2, Cell::kValueOffset));
// The type cell may have undefined in its value. // If the type cell is undefined, or contains anything other than an
__ CompareRoot(r3, Heap::kUndefinedValueRootIndex); // AllocationSite, call an array constructor that doesn't use AllocationSites.
__ b(eq, &no_info);
// The type cell has either an AllocationSite or a JSFunction
__ ldr(r4, FieldMemOperand(r3, 0)); __ ldr(r4, FieldMemOperand(r3, 0));
__ CompareRoot(r4, Heap::kAllocationSiteMapRootIndex); __ CompareRoot(r4, Heap::kAllocationSiteMapRootIndex);
__ b(ne, &no_info); __ b(ne, &no_info);
__ ldr(r3, FieldMemOperand(r3, AllocationSite::kTransitionInfoOffset)); __ ldr(r3, FieldMemOperand(r3, AllocationSite::kTransitionInfoOffset));
__ SmiUntag(r3); __ SmiUntag(r3);
__ jmp(&switch_ready); GenerateDispatchToArrayStub(masm, DONT_OVERRIDE);
__ bind(&no_info);
__ mov(r3, Operand(GetInitialFastElementsKind()));
__ bind(&switch_ready);
if (argument_count_ == ANY) { __ bind(&no_info);
Label not_zero_case, not_one_case; GenerateDispatchToArrayStub(masm, DISABLE_ALLOCATION_SITES);
__ tst(r0, r0);
__ b(ne, &not_zero_case);
CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm);
__ bind(&not_zero_case);
__ cmp(r0, Operand(1));
__ b(gt, &not_one_case);
CreateArrayDispatchOneArgument(masm);
__ bind(&not_one_case);
CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm);
} else if (argument_count_ == NONE) {
CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm);
} else if (argument_count_ == ONE) {
CreateArrayDispatchOneArgument(masm);
} else if (argument_count_ == MORE_THAN_ONE) {
CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm);
} else {
UNREACHABLE();
}
} }
......
...@@ -736,6 +736,13 @@ class InstanceofStub: public PlatformCodeStub { ...@@ -736,6 +736,13 @@ class InstanceofStub: public PlatformCodeStub {
}; };
enum AllocationSiteOverrideMode {
DONT_OVERRIDE,
DISABLE_ALLOCATION_SITES,
LAST_ALLOCATION_SITE_OVERRIDE_MODE = DISABLE_ALLOCATION_SITES
};
class ArrayConstructorStub: public PlatformCodeStub { class ArrayConstructorStub: public PlatformCodeStub {
public: public:
enum ArgumentCountKey { ANY, NONE, ONE, MORE_THAN_ONE }; enum ArgumentCountKey { ANY, NONE, ONE, MORE_THAN_ONE };
...@@ -745,6 +752,9 @@ class ArrayConstructorStub: public PlatformCodeStub { ...@@ -745,6 +752,9 @@ class ArrayConstructorStub: public PlatformCodeStub {
void Generate(MacroAssembler* masm); void Generate(MacroAssembler* masm);
private: private:
void GenerateDispatchToArrayStub(MacroAssembler* masm,
AllocationSiteOverrideMode mode);
virtual CodeStub::Major MajorKey() { return ArrayConstructor; } virtual CodeStub::Major MajorKey() { return ArrayConstructor; }
virtual int MinorKey() { return argument_count_; } virtual int MinorKey() { return argument_count_; }
...@@ -1863,13 +1873,6 @@ enum ContextCheckMode { ...@@ -1863,13 +1873,6 @@ enum ContextCheckMode {
}; };
enum AllocationSiteOverrideMode {
DONT_OVERRIDE,
DISABLE_ALLOCATION_SITES,
LAST_ALLOCATION_SITE_OVERRIDE_MODE = DISABLE_ALLOCATION_SITES
};
class ArrayConstructorStubBase : public HydrogenCodeStub { class ArrayConstructorStubBase : public HydrogenCodeStub {
public: public:
ArrayConstructorStubBase(ElementsKind kind, ContextCheckMode context_mode, ArrayConstructorStubBase(ElementsKind kind, ContextCheckMode context_mode,
...@@ -1877,7 +1880,8 @@ class ArrayConstructorStubBase : public HydrogenCodeStub { ...@@ -1877,7 +1880,8 @@ class ArrayConstructorStubBase : public HydrogenCodeStub {
// It only makes sense to override local allocation site behavior // It only makes sense to override local allocation site behavior
// if there is a difference between the global allocation site policy // if there is a difference between the global allocation site policy
// for an ElementsKind and the desired usage of the stub. // for an ElementsKind and the desired usage of the stub.
ASSERT(override_mode != DISABLE_ALLOCATION_SITES || ASSERT(!(FLAG_track_allocation_sites &&
override_mode == DISABLE_ALLOCATION_SITES) ||
AllocationSite::GetMode(kind) == TRACK_ALLOCATION_SITE); AllocationSite::GetMode(kind) == TRACK_ALLOCATION_SITE);
bit_field_ = ElementsKindBits::encode(kind) | bit_field_ = ElementsKindBits::encode(kind) |
AllocationSiteOverrideModeBits::encode(override_mode) | AllocationSiteOverrideModeBits::encode(override_mode) |
......
...@@ -7225,96 +7225,128 @@ void ProfileEntryHookStub::Generate(MacroAssembler* masm) { ...@@ -7225,96 +7225,128 @@ void ProfileEntryHookStub::Generate(MacroAssembler* masm) {
template<class T> template<class T>
static void CreateArrayDispatch(MacroAssembler* masm) { static void CreateArrayDispatch(MacroAssembler* masm,
int last_index = GetSequenceIndexFromFastElementsKind( AllocationSiteOverrideMode mode) {
TERMINAL_FAST_ELEMENTS_KIND); if (mode == DISABLE_ALLOCATION_SITES) {
for (int i = 0; i <= last_index; ++i) { T stub(GetInitialFastElementsKind(),
Label next; CONTEXT_CHECK_REQUIRED,
ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); mode);
__ cmp(edx, kind);
__ j(not_equal, &next);
T stub(kind);
__ TailCallStub(&stub); __ TailCallStub(&stub);
__ bind(&next); } else if (mode == DONT_OVERRIDE) {
} int last_index = GetSequenceIndexFromFastElementsKind(
TERMINAL_FAST_ELEMENTS_KIND);
for (int i = 0; i <= last_index; ++i) {
Label next;
ElementsKind kind = GetFastElementsKindFromSequenceIndex(i);
__ cmp(edx, kind);
__ j(not_equal, &next);
T stub(kind);
__ TailCallStub(&stub);
__ bind(&next);
}
// If we reached this point there is a problem. // If we reached this point there is a problem.
__ Abort(kUnexpectedElementsKindInArrayConstructor); __ Abort(kUnexpectedElementsKindInArrayConstructor);
} else {
UNREACHABLE();
}
} }
static void CreateArrayDispatchOneArgument(MacroAssembler* masm) { static void CreateArrayDispatchOneArgument(MacroAssembler* masm,
// ebx - type info cell AllocationSiteOverrideMode mode) {
// edx - kind // ebx - type info cell (if mode != DISABLE_ALLOCATION_SITES)
// edx - kind (if mode != DISABLE_ALLOCATION_SITES)
// eax - number of arguments // eax - number of arguments
// edi - constructor? // edi - constructor?
// esp[0] - return address // esp[0] - return address
// esp[4] - last argument // esp[4] - last argument
ASSERT(FAST_SMI_ELEMENTS == 0);
ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1);
ASSERT(FAST_ELEMENTS == 2);
ASSERT(FAST_HOLEY_ELEMENTS == 3);
ASSERT(FAST_DOUBLE_ELEMENTS == 4);
ASSERT(FAST_HOLEY_DOUBLE_ELEMENTS == 5);
Handle<Object> undefined_sentinel(
masm->isolate()->heap()->undefined_value(),
masm->isolate());
// is the low bit set? If so, we are holey and that is good.
__ test_b(edx, 1);
Label normal_sequence; Label normal_sequence;
__ j(not_zero, &normal_sequence); if (mode == DONT_OVERRIDE) {
ASSERT(FAST_SMI_ELEMENTS == 0);
ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1);
ASSERT(FAST_ELEMENTS == 2);
ASSERT(FAST_HOLEY_ELEMENTS == 3);
ASSERT(FAST_DOUBLE_ELEMENTS == 4);
ASSERT(FAST_HOLEY_DOUBLE_ELEMENTS == 5);
// is the low bit set? If so, we are holey and that is good.
__ test_b(edx, 1);
__ j(not_zero, &normal_sequence);
}
// look at the first argument // look at the first argument
__ mov(ecx, Operand(esp, kPointerSize)); __ mov(ecx, Operand(esp, kPointerSize));
__ test(ecx, ecx); __ test(ecx, ecx);
__ j(zero, &normal_sequence); __ j(zero, &normal_sequence);
// We are going to create a holey array, but our kind is non-holey. if (mode == DISABLE_ALLOCATION_SITES) {
// Fix kind and retry (only if we have an allocation site in the cell). ElementsKind initial = GetInitialFastElementsKind();
__ inc(edx); ElementsKind holey_initial = GetHoleyElementsKind(initial);
__ cmp(ebx, Immediate(undefined_sentinel));
__ j(equal, &normal_sequence);
__ mov(ecx, FieldOperand(ebx, Cell::kValueOffset));
Handle<Map> allocation_site_map(
masm->isolate()->heap()->allocation_site_map(),
masm->isolate());
__ cmp(FieldOperand(ecx, 0), Immediate(allocation_site_map));
__ j(not_equal, &normal_sequence);
// Save the resulting elements kind in type info ArraySingleArgumentConstructorStub stub_holey(holey_initial,
__ SmiTag(edx); CONTEXT_CHECK_REQUIRED,
__ mov(FieldOperand(ecx, AllocationSite::kTransitionInfoOffset), edx); DISABLE_ALLOCATION_SITES);
__ SmiUntag(edx); __ TailCallStub(&stub_holey);
__ bind(&normal_sequence); __ bind(&normal_sequence);
int last_index = GetSequenceIndexFromFastElementsKind( ArraySingleArgumentConstructorStub stub(initial,
TERMINAL_FAST_ELEMENTS_KIND); CONTEXT_CHECK_REQUIRED,
for (int i = 0; i <= last_index; ++i) { DISABLE_ALLOCATION_SITES);
Label next;
ElementsKind kind = GetFastElementsKindFromSequenceIndex(i);
__ cmp(edx, kind);
__ j(not_equal, &next);
ArraySingleArgumentConstructorStub stub(kind);
__ TailCallStub(&stub); __ TailCallStub(&stub);
__ bind(&next); } else if (mode == DONT_OVERRIDE) {
} // We are going to create a holey array, but our kind is non-holey.
// Fix kind and retry.
__ inc(edx);
__ mov(ecx, FieldOperand(ebx, Cell::kValueOffset));
if (FLAG_debug_code) {
Handle<Map> allocation_site_map(
masm->isolate()->heap()->allocation_site_map(),
masm->isolate());
__ cmp(FieldOperand(ecx, 0), Immediate(allocation_site_map));
__ Assert(equal, kExpectedAllocationSiteInCell);
}
// If we reached this point there is a problem. // Save the resulting elements kind in type info
__ Abort(kUnexpectedElementsKindInArrayConstructor); __ SmiTag(edx);
__ mov(FieldOperand(ecx, AllocationSite::kTransitionInfoOffset), edx);
__ SmiUntag(edx);
__ bind(&normal_sequence);
int last_index = GetSequenceIndexFromFastElementsKind(
TERMINAL_FAST_ELEMENTS_KIND);
for (int i = 0; i <= last_index; ++i) {
Label next;
ElementsKind kind = GetFastElementsKindFromSequenceIndex(i);
__ cmp(edx, kind);
__ j(not_equal, &next);
ArraySingleArgumentConstructorStub stub(kind);
__ TailCallStub(&stub);
__ bind(&next);
}
// If we reached this point there is a problem.
__ Abort(kUnexpectedElementsKindInArrayConstructor);
} else {
UNREACHABLE();
}
} }
template<class T> template<class T>
static void ArrayConstructorStubAheadOfTimeHelper(Isolate* isolate) { static void ArrayConstructorStubAheadOfTimeHelper(Isolate* isolate) {
ElementsKind initial_kind = GetInitialFastElementsKind();
ElementsKind initial_holey_kind = GetHoleyElementsKind(initial_kind);
int to_index = GetSequenceIndexFromFastElementsKind( int to_index = GetSequenceIndexFromFastElementsKind(
TERMINAL_FAST_ELEMENTS_KIND); TERMINAL_FAST_ELEMENTS_KIND);
for (int i = 0; i <= to_index; ++i) { for (int i = 0; i <= to_index; ++i) {
ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); ElementsKind kind = GetFastElementsKindFromSequenceIndex(i);
T stub(kind); T stub(kind);
stub.GetCode(isolate)->set_is_pregenerated(true); stub.GetCode(isolate)->set_is_pregenerated(true);
if (AllocationSite::GetMode(kind) != DONT_TRACK_ALLOCATION_SITE) { if (AllocationSite::GetMode(kind) != DONT_TRACK_ALLOCATION_SITE ||
(!FLAG_track_allocation_sites &&
(kind == initial_kind || kind == initial_holey_kind))) {
T stub1(kind, CONTEXT_CHECK_REQUIRED, DISABLE_ALLOCATION_SITES); T stub1(kind, CONTEXT_CHECK_REQUIRED, DISABLE_ALLOCATION_SITES);
stub1.GetCode(isolate)->set_is_pregenerated(true); stub1.GetCode(isolate)->set_is_pregenerated(true);
} }
...@@ -7347,6 +7379,34 @@ void InternalArrayConstructorStubBase::GenerateStubsAheadOfTime( ...@@ -7347,6 +7379,34 @@ void InternalArrayConstructorStubBase::GenerateStubsAheadOfTime(
} }
void ArrayConstructorStub::GenerateDispatchToArrayStub(
MacroAssembler* masm,
AllocationSiteOverrideMode mode) {
if (argument_count_ == ANY) {
Label not_zero_case, not_one_case;
__ test(eax, eax);
__ j(not_zero, &not_zero_case);
CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm, mode);
__ bind(&not_zero_case);
__ cmp(eax, 1);
__ j(greater, &not_one_case);
CreateArrayDispatchOneArgument(masm, mode);
__ bind(&not_one_case);
CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm, mode);
} else if (argument_count_ == NONE) {
CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm, mode);
} else if (argument_count_ == ONE) {
CreateArrayDispatchOneArgument(masm, mode);
} else if (argument_count_ == MORE_THAN_ONE) {
CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm, mode);
} else {
UNREACHABLE();
}
}
void ArrayConstructorStub::Generate(MacroAssembler* masm) { void ArrayConstructorStub::Generate(MacroAssembler* masm) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- eax : argc (only if argument_count_ == ANY) // -- eax : argc (only if argument_count_ == ANY)
...@@ -7381,50 +7441,22 @@ void ArrayConstructorStub::Generate(MacroAssembler* masm) { ...@@ -7381,50 +7441,22 @@ void ArrayConstructorStub::Generate(MacroAssembler* masm) {
__ bind(&okay_here); __ bind(&okay_here);
} }
Label no_info, switch_ready; Label no_info;
// Get the elements kind and case on that. // If the type cell is undefined, or contains anything other than an
// AllocationSite, call an array constructor that doesn't use AllocationSites.
__ cmp(ebx, Immediate(undefined_sentinel)); __ cmp(ebx, Immediate(undefined_sentinel));
__ j(equal, &no_info); __ j(equal, &no_info);
__ mov(edx, FieldOperand(ebx, Cell::kValueOffset)); __ mov(edx, FieldOperand(ebx, Cell::kValueOffset));
// The type cell may have undefined in its value.
__ cmp(edx, Immediate(undefined_sentinel));
__ j(equal, &no_info);
// The type cell has either an AllocationSite or a JSFunction
__ cmp(FieldOperand(edx, 0), Immediate(Handle<Map>( __ cmp(FieldOperand(edx, 0), Immediate(Handle<Map>(
masm->isolate()->heap()->allocation_site_map()))); masm->isolate()->heap()->allocation_site_map())));
__ j(not_equal, &no_info); __ j(not_equal, &no_info);
__ mov(edx, FieldOperand(edx, AllocationSite::kTransitionInfoOffset)); __ mov(edx, FieldOperand(edx, AllocationSite::kTransitionInfoOffset));
__ SmiUntag(edx); __ SmiUntag(edx);
__ jmp(&switch_ready); GenerateDispatchToArrayStub(masm, DONT_OVERRIDE);
__ bind(&no_info);
__ mov(edx, Immediate(GetInitialFastElementsKind()));
__ bind(&switch_ready);
if (argument_count_ == ANY) {
Label not_zero_case, not_one_case;
__ test(eax, eax);
__ j(not_zero, &not_zero_case);
CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm);
__ bind(&not_zero_case); __ bind(&no_info);
__ cmp(eax, 1); GenerateDispatchToArrayStub(masm, DISABLE_ALLOCATION_SITES);
__ j(greater, &not_one_case);
CreateArrayDispatchOneArgument(masm);
__ bind(&not_one_case);
CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm);
} else if (argument_count_ == NONE) {
CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm);
} else if (argument_count_ == ONE) {
CreateArrayDispatchOneArgument(masm);
} else if (argument_count_ == MORE_THAN_ONE) {
CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm);
} else {
UNREACHABLE();
}
} }
......
...@@ -1113,6 +1113,8 @@ class MaybeObject BASE_EMBEDDED { ...@@ -1113,6 +1113,8 @@ class MaybeObject BASE_EMBEDDED {
V(kEval, "eval") \ V(kEval, "eval") \
V(kExpected0AsASmiSentinel, "Expected 0 as a Smi sentinel") \ V(kExpected0AsASmiSentinel, "Expected 0 as a Smi sentinel") \
V(kExpectedAlignmentMarker, "expected alignment marker") \ V(kExpectedAlignmentMarker, "expected alignment marker") \
V(kExpectedAllocationSiteInCell, \
"Expected AllocationSite in property cell") \
V(kExpectedPropertyCellInRegisterA2, \ V(kExpectedPropertyCellInRegisterA2, \
"Expected property cell in register a2") \ "Expected property cell in register a2") \
V(kExpectedPropertyCellInRegisterEbx, \ V(kExpectedPropertyCellInRegisterEbx, \
......
This diff is collapsed.
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