Commit dea16c9a authored by machenbach's avatar machenbach Committed by Commit bot

Revert of [Interpreter] Collect type feedback for 'new' in the bytecode...

Revert of [Interpreter] Collect type feedback for 'new' in the bytecode handler (patchset #6 id:100001 of https://codereview.chromium.org/2190293003/ )

Reason for revert:
[Sheriff] Fails on nosnap debug:
https://build.chromium.org/p/client.v8/builders/V8%20Linux%20-%20nosnap%20-%20debug/builds/8403

Original issue's description:
> [Interpreter] Collect type feedback for 'new' in the bytecode handler
>
> Collect type feedback in the bytecode handler for 'new' bytecode. The
> earlier cl (https://codereview.chromium.org/2153433002/) was reverted
> because that implementation did not collect allocation site feedback.
> This regressed delta blue by an order of magnitude. This implementation
> includes collection of allocation site feedback.
>
> BUG=v8:4280, v8:4780
> LOG=N
>
> Committed: https://crrev.com/9d5e6129c4c7f9cbfe81a5fad2a470f219fe137c
> Cr-Commit-Position: refs/heads/master@{#38364}

TBR=bmeurer@chromium.org,rmcilroy@chromium.org,balazs.kilvady@imgtec.com,mythria@chromium.org
# Skipping CQ checks because original CL landed less than 1 days ago.
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true
BUG=v8:4280, v8:4780

Review-Url: https://codereview.chromium.org/2212343002
Cr-Commit-Position: refs/heads/master@{#38368}
parent 2648162d
...@@ -403,8 +403,7 @@ void InterpreterPushArgsAndConstructDescriptor::InitializePlatformSpecific( ...@@ -403,8 +403,7 @@ void InterpreterPushArgsAndConstructDescriptor::InitializePlatformSpecific(
r0, // argument count (not including receiver) r0, // argument count (not including receiver)
r3, // new target r3, // new target
r1, // constructor to call r1, // constructor to call
r2, // allocation site feedback if available, undefined otherwise r2 // address of the first argument
r4 // address of the first argument
}; };
data->InitializePlatformSpecific(arraysize(registers), registers); data->InitializePlatformSpecific(arraysize(registers), registers);
} }
......
...@@ -435,8 +435,7 @@ void InterpreterPushArgsAndConstructDescriptor::InitializePlatformSpecific( ...@@ -435,8 +435,7 @@ void InterpreterPushArgsAndConstructDescriptor::InitializePlatformSpecific(
x0, // argument count (not including receiver) x0, // argument count (not including receiver)
x3, // new target x3, // new target
x1, // constructor to call x1, // constructor to call
x2, // allocation site feedback if available, undefined otherwise x2 // address of the first argument
x4 // address of the first argument
}; };
data->InitializePlatformSpecific(arraysize(registers), registers); data->InitializePlatformSpecific(arraysize(registers), registers);
} }
......
...@@ -1189,7 +1189,6 @@ void Builtins::Generate_InterpreterPushArgsAndCallImpl( ...@@ -1189,7 +1189,6 @@ void Builtins::Generate_InterpreterPushArgsAndCallImpl(
__ mov(r3, Operand(r3, LSL, kPointerSizeLog2)); __ mov(r3, Operand(r3, LSL, kPointerSizeLog2));
__ sub(r3, r2, r3); __ sub(r3, r2, r3);
// TODO(mythria): Add a stack check before pushing arguments.
// Push the arguments. // Push the arguments.
Generate_InterpreterPushArgs(masm, r2, r3, r4); Generate_InterpreterPushArgs(masm, r2, r3, r4);
...@@ -1207,44 +1206,27 @@ void Builtins::Generate_InterpreterPushArgsAndCallImpl( ...@@ -1207,44 +1206,27 @@ void Builtins::Generate_InterpreterPushArgsAndCallImpl(
} }
// static // static
void Builtins::Generate_InterpreterPushArgsAndConstructImpl( void Builtins::Generate_InterpreterPushArgsAndConstruct(MacroAssembler* masm) {
MacroAssembler* masm, CallableType construct_type) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- r0 : argument count (not including receiver) // -- r0 : argument count (not including receiver)
// -- r3 : new target // -- r3 : new target
// -- r1 : constructor to call // -- r1 : constructor to call
// -- r2 : allocation site feedback if available, undefined otherwise. // -- r2 : address of the first argument
// -- r4 : address of the first argument
// ----------------------------------- // -----------------------------------
// Find the address of the last argument. // Find the address of the last argument.
__ mov(r5, Operand(r0, LSL, kPointerSizeLog2)); __ mov(r4, Operand(r0, LSL, kPointerSizeLog2));
__ sub(r5, r4, r5); __ sub(r4, r2, r4);
// Push a slot for the receiver to be constructed. // Push a slot for the receiver to be constructed.
__ mov(ip, Operand::Zero()); __ mov(ip, Operand::Zero());
__ push(ip); __ push(ip);
// TODO(mythria): Add a stack check before pushing arguments.
// Push the arguments. // Push the arguments.
Generate_InterpreterPushArgs(masm, r4, r5, r6); Generate_InterpreterPushArgs(masm, r2, r4, r5);
__ AssertUndefinedOrAllocationSite(r2, r5); // Call the constructor with r0, r1, and r3 unmodified.
if (construct_type == CallableType::kJSFunction) { __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET);
__ AssertFunction(r1);
// Tail call to the function-specific construct stub (still in the caller
// context at this point).
__ ldr(r4, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
__ ldr(r4, FieldMemOperand(r4, SharedFunctionInfo::kConstructStubOffset));
// Jump to the construct function.
__ add(pc, r4, Operand(Code::kHeaderSize - kHeapObjectTag));
} else {
DCHECK_EQ(construct_type, CallableType::kAny);
// Call the constructor with r0, r1, and r3 unmodified.
__ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET);
}
} }
void Builtins::Generate_InterpreterEnterBytecodeDispatch(MacroAssembler* masm) { void Builtins::Generate_InterpreterEnterBytecodeDispatch(MacroAssembler* masm) {
......
...@@ -1186,7 +1186,6 @@ void Builtins::Generate_InterpreterPushArgsAndCallImpl( ...@@ -1186,7 +1186,6 @@ void Builtins::Generate_InterpreterPushArgsAndCallImpl(
__ lsl(x3, x3, kPointerSizeLog2); __ lsl(x3, x3, kPointerSizeLog2);
__ sub(x4, x2, x3); __ sub(x4, x2, x3);
// TODO(mythria): Add a stack check before pushing arguments.
// Push the arguments. // Push the arguments.
Label loop_header, loop_check; Label loop_header, loop_check;
__ Mov(x5, jssp); __ Mov(x5, jssp);
...@@ -1214,14 +1213,12 @@ void Builtins::Generate_InterpreterPushArgsAndCallImpl( ...@@ -1214,14 +1213,12 @@ void Builtins::Generate_InterpreterPushArgsAndCallImpl(
} }
// static // static
void Builtins::Generate_InterpreterPushArgsAndConstructImpl( void Builtins::Generate_InterpreterPushArgsAndConstruct(MacroAssembler* masm) {
MacroAssembler* masm, CallableType construct_type) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- x0 : argument count (not including receiver) // -- x0 : argument count (not including receiver)
// -- x3 : new target // -- x3 : new target
// -- x1 : constructor to call // -- x1 : constructor to call
// -- x2 : allocation site feedback if available, undefined otherwise // -- x2 : address of the first argument
// -- x4 : address of the first argument
// ----------------------------------- // -----------------------------------
// Find the address of the last argument. // Find the address of the last argument.
...@@ -1231,38 +1228,24 @@ void Builtins::Generate_InterpreterPushArgsAndConstructImpl( ...@@ -1231,38 +1228,24 @@ void Builtins::Generate_InterpreterPushArgsAndConstructImpl(
// Set stack pointer and where to stop. // Set stack pointer and where to stop.
__ Mov(x6, jssp); __ Mov(x6, jssp);
__ Claim(x5, 1); __ Claim(x5, 1);
__ sub(x7, x6, x5); __ sub(x4, x6, x5);
// Push a slot for the receiver. // Push a slot for the receiver.
__ Str(xzr, MemOperand(x6, -kPointerSize, PreIndex)); __ Str(xzr, MemOperand(x6, -kPointerSize, PreIndex));
Label loop_header, loop_check; Label loop_header, loop_check;
// TODO(mythria): Add a stack check before pushing arguments.
// Push the arguments. // Push the arguments.
__ B(&loop_check); __ B(&loop_check);
__ Bind(&loop_header); __ Bind(&loop_header);
// TODO(rmcilroy): Push two at a time once we ensure we keep stack aligned. // TODO(rmcilroy): Push two at a time once we ensure we keep stack aligned.
__ Ldr(x5, MemOperand(x4, -kPointerSize, PostIndex)); __ Ldr(x5, MemOperand(x2, -kPointerSize, PostIndex));
__ Str(x5, MemOperand(x6, -kPointerSize, PreIndex)); __ Str(x5, MemOperand(x6, -kPointerSize, PreIndex));
__ Bind(&loop_check); __ Bind(&loop_check);
__ Cmp(x6, x7); __ Cmp(x6, x4);
__ B(gt, &loop_header); __ B(gt, &loop_header);
__ AssertUndefinedOrAllocationSite(x2, x6); // Call the constructor with x0, x1, and x3 unmodified.
if (construct_type == CallableType::kJSFunction) { __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET);
__ AssertFunction(x1);
// Tail call to the function-specific construct stub (still in the caller
// context at this point).
__ Ldr(x4, FieldMemOperand(x1, JSFunction::kSharedFunctionInfoOffset));
__ Ldr(x4, FieldMemOperand(x4, SharedFunctionInfo::kConstructStubOffset));
__ Add(x4, x4, Code::kHeaderSize - kHeapObjectTag);
__ Br(x4);
} else {
DCHECK_EQ(construct_type, CallableType::kAny);
// Call the constructor with x0, x1, and x3 unmodified.
__ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET);
}
} }
void Builtins::Generate_InterpreterEnterBytecodeDispatch(MacroAssembler* masm) { void Builtins::Generate_InterpreterEnterBytecodeDispatch(MacroAssembler* masm) {
......
...@@ -50,27 +50,5 @@ void Builtins::Generate_InterpreterPushArgsAndTailCallFunction( ...@@ -50,27 +50,5 @@ void Builtins::Generate_InterpreterPushArgsAndTailCallFunction(
CallableType::kJSFunction); CallableType::kJSFunction);
} }
Handle<Code> Builtins::InterpreterPushArgsAndConstruct(
CallableType function_type) {
switch (function_type) {
case CallableType::kJSFunction:
return InterpreterPushArgsAndConstructFunction();
case CallableType::kAny:
return InterpreterPushArgsAndConstruct();
}
UNREACHABLE();
return Handle<Code>::null();
}
void Builtins::Generate_InterpreterPushArgsAndConstruct(MacroAssembler* masm) {
return Generate_InterpreterPushArgsAndConstructImpl(masm, CallableType::kAny);
}
void Builtins::Generate_InterpreterPushArgsAndConstructFunction(
MacroAssembler* masm) {
return Generate_InterpreterPushArgsAndConstructImpl(
masm, CallableType::kJSFunction);
}
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
...@@ -126,10 +126,9 @@ namespace internal { ...@@ -126,10 +126,9 @@ namespace internal {
ASM(InterpreterMarkBaselineOnReturn) \ ASM(InterpreterMarkBaselineOnReturn) \
ASM(InterpreterPushArgsAndCall) \ ASM(InterpreterPushArgsAndCall) \
ASM(InterpreterPushArgsAndCallFunction) \ ASM(InterpreterPushArgsAndCallFunction) \
ASM(InterpreterPushArgsAndConstruct) \
ASM(InterpreterPushArgsAndTailCall) \ ASM(InterpreterPushArgsAndTailCall) \
ASM(InterpreterPushArgsAndTailCallFunction) \ ASM(InterpreterPushArgsAndTailCallFunction) \
ASM(InterpreterPushArgsAndConstruct) \
ASM(InterpreterPushArgsAndConstructFunction) \
ASM(InterpreterEnterBytecodeDispatch) \ ASM(InterpreterEnterBytecodeDispatch) \
ASM(InterpreterOnStackReplacement) \ ASM(InterpreterOnStackReplacement) \
\ \
...@@ -582,7 +581,6 @@ class Builtins { ...@@ -582,7 +581,6 @@ class Builtins {
Handle<Code> InterpreterPushArgsAndCall( Handle<Code> InterpreterPushArgsAndCall(
TailCallMode tail_call_mode, TailCallMode tail_call_mode,
CallableType function_type = CallableType::kAny); CallableType function_type = CallableType::kAny);
Handle<Code> InterpreterPushArgsAndConstruct(CallableType function_type);
Code* builtin(Name name) { Code* builtin(Name name) {
// Code::cast cannot be used here since we access builtins // Code::cast cannot be used here since we access builtins
...@@ -627,9 +625,6 @@ class Builtins { ...@@ -627,9 +625,6 @@ class Builtins {
MacroAssembler* masm, TailCallMode tail_call_mode, MacroAssembler* masm, TailCallMode tail_call_mode,
CallableType function_type); CallableType function_type);
static void Generate_InterpreterPushArgsAndConstructImpl(
MacroAssembler* masm, CallableType function_type);
static void Generate_DatePrototype_GetField(MacroAssembler* masm, static void Generate_DatePrototype_GetField(MacroAssembler* masm,
int field_index); int field_index);
......
...@@ -702,20 +702,19 @@ void Builtins::Generate_InterpreterMarkBaselineOnReturn(MacroAssembler* masm) { ...@@ -702,20 +702,19 @@ void Builtins::Generate_InterpreterMarkBaselineOnReturn(MacroAssembler* masm) {
} }
static void Generate_InterpreterPushArgs(MacroAssembler* masm, static void Generate_InterpreterPushArgs(MacroAssembler* masm,
Register array_limit, Register array_limit) {
Register start_address) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- start_address : Pointer to the last argument in the args array. // -- ebx : Pointer to the last argument in the args array.
// -- array_limit : Pointer to one before the first argument in the // -- array_limit : Pointer to one before the first argument in the
// args array. // args array.
// ----------------------------------- // -----------------------------------
Label loop_header, loop_check; Label loop_header, loop_check;
__ jmp(&loop_check); __ jmp(&loop_check);
__ bind(&loop_header); __ bind(&loop_header);
__ Push(Operand(start_address, 0)); __ Push(Operand(ebx, 0));
__ sub(start_address, Immediate(kPointerSize)); __ sub(ebx, Immediate(kPointerSize));
__ bind(&loop_check); __ bind(&loop_check);
__ cmp(start_address, array_limit); __ cmp(ebx, array_limit);
__ j(greater, &loop_header, Label::kNear); __ j(greater, &loop_header, Label::kNear);
} }
...@@ -741,8 +740,7 @@ void Builtins::Generate_InterpreterPushArgsAndCallImpl( ...@@ -741,8 +740,7 @@ void Builtins::Generate_InterpreterPushArgsAndCallImpl(
__ neg(ecx); __ neg(ecx);
__ add(ecx, ebx); __ add(ecx, ebx);
// TODO(mythria): Add a stack check before pushing the arguments. Generate_InterpreterPushArgs(masm, ecx);
Generate_InterpreterPushArgs(masm, ecx, ebx);
// Call the target. // Call the target.
__ Push(edx); // Re-push return address. __ Push(edx); // Re-push return address.
...@@ -760,115 +758,40 @@ void Builtins::Generate_InterpreterPushArgsAndCallImpl( ...@@ -760,115 +758,40 @@ void Builtins::Generate_InterpreterPushArgsAndCallImpl(
} }
// static // static
void Builtins::Generate_InterpreterPushArgsAndConstructImpl( void Builtins::Generate_InterpreterPushArgsAndConstruct(MacroAssembler* masm) {
MacroAssembler* masm, CallableType construct_type) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- eax : the number of arguments (not including the receiver) // -- eax : the number of arguments (not including the receiver)
// -- edx : the new target // -- edx : the new target
// -- edi : the constructor // -- edi : the constructor
// -- ebx : allocation site feedback (if available or undefined) // -- ebx : the address of the first argument to be pushed. Subsequent
// -- ecx : the address of the first argument to be pushed. Subsequent
// arguments should be consecutive above this, in the same order as // arguments should be consecutive above this, in the same order as
// they are to be pushed onto the stack. // they are to be pushed onto the stack.
// ----------------------------------- // -----------------------------------
// Store edi, edx onto the stack. We need two extra registers // Pop return address to allow tail-call after pushing arguments.
// so store edi, edx temporarily on stack. __ Pop(ecx);
// Push edi in the slot meant for receiver. We need an extra register
// so store edi temporarily on stack.
__ Push(edi); __ Push(edi);
__ Push(edx);
// We have to pop return address and the two temporary registers before we // Find the address of the last argument.
// can push arguments onto the stack. we do not have any free registers so __ mov(edi, eax);
// update the stack and copy them into the correct places on the stack. __ neg(edi);
// current stack =====> required stack layout __ shl(edi, kPointerSizeLog2);
// | | | edx | (2) <-- esp(1) __ add(edi, ebx);
// | | | edi | (3)
// | | | return addr | (4)
// | | | arg N | (5)
// | edx | <-- esp | .... |
// | edi | | arg 0 |
// | return addr | | receiver slot |
// First increment the stack pointer to the correct location.
// we need additional slots for arguments and the receiver.
// Step 1 - compute the required increment to the stack.
__ mov(edx, eax);
__ shl(edx, kPointerSizeLog2);
__ add(edx, Immediate(kPointerSize));
#ifdef _MSC_VER
// TODO(mythria): Move it to macro assembler.
// In windows, we cannot increment the stack size by more than one page
// (mimimum page size is 4KB) without accessing at least one byte on the
// page. Check this:
// https://msdn.microsoft.com/en-us/library/aa227153(v=vs.60).aspx.
const int page_size = 4 * 1024;
Label check_offset, update_stack_pointer;
__ bind(&check_offset);
__ cmp(edx, page_size);
__ j(less, &update_stack_pointer);
__ sub(esp, Immediate(page_size));
// Just to touch the page, before we increment further.
__ mov(Operand(esp, 0), Immediate(0));
__ sub(edx, Immediate(page_size));
__ jmp(&check_offset);
__ bind(&update_stack_pointer);
#endif
// TODO(mythria): Add a stack check before updating the stack pointer.
// Step 1 - Update the stack pointer.
__ sub(esp, edx);
// Step 2 move edx to the correct location. Move edx first otherwise
// we may overwrite when eax = 0 or 1, basically when the source and
// destination overlap. We at least need one extra slot for receiver,
// so no extra checks are required to avoid copy.
__ mov(edi, Operand(esp, eax, times_pointer_size, 1 * kPointerSize));
__ mov(Operand(esp, 0), edi);
// Step 3 move edi to the correct location
__ mov(edi, Operand(esp, eax, times_pointer_size, 2 * kPointerSize));
__ mov(Operand(esp, 1 * kPointerSize), edi);
// Step 4 move return address to the correct location
__ mov(edi, Operand(esp, eax, times_pointer_size, 3 * kPointerSize));
__ mov(Operand(esp, 2 * kPointerSize), edi);
// Step 5 copy arguments to correct locations.
__ mov(edx, eax);
Label loop_header, loop_check; Generate_InterpreterPushArgs(masm, edi);
__ jmp(&loop_check);
__ bind(&loop_header);
__ mov(edi, Operand(ecx, 0));
__ mov(Operand(esp, edx, times_pointer_size, 2 * kPointerSize), edi);
__ sub(ecx, Immediate(kPointerSize));
__ sub(edx, Immediate(1));
__ bind(&loop_check);
__ cmp(edx, Immediate(0));
__ j(greater, &loop_header, Label::kNear);
// Restore edi and edx. // Restore the constructor from slot on stack. It was pushed at the slot
__ Pop(edx); // meant for receiver.
__ Pop(edi); __ mov(edi, Operand(esp, eax, times_pointer_size, 0));
__ AssertUndefinedOrAllocationSite(ebx);
if (construct_type == CallableType::kJSFunction) {
// Tail call to the function-specific construct stub (still in the caller
// context at this point).
__ AssertFunction(edi);
__ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
__ mov(ecx, FieldOperand(ecx, SharedFunctionInfo::kConstructStubOffset));
__ lea(ecx, FieldOperand(ecx, Code::kHeaderSize));
__ jmp(ecx);
} else {
DCHECK_EQ(construct_type, CallableType::kAny);
// Call the constructor with unmodified eax, edi, edx values. // Re-push return address.
__ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); __ Push(ecx);
}
// Call the constructor with unmodified eax, edi, ebi values.
__ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET);
} }
void Builtins::Generate_InterpreterEnterBytecodeDispatch(MacroAssembler* masm) { void Builtins::Generate_InterpreterEnterBytecodeDispatch(MacroAssembler* masm) {
......
...@@ -1198,19 +1198,17 @@ void Builtins::Generate_InterpreterPushArgsAndCallImpl( ...@@ -1198,19 +1198,17 @@ void Builtins::Generate_InterpreterPushArgsAndCallImpl(
} }
// static // static
void Builtins::Generate_InterpreterPushArgsAndConstructImpl( void Builtins::Generate_InterpreterPushArgsAndConstruct(MacroAssembler* masm) {
MacroAssembler* masm, CallableType construct_type) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- a0 : argument count (not including receiver) // -- a0 : argument count (not including receiver)
// -- a3 : new target // -- a3 : new target
// -- a1 : constructor to call // -- a1 : constructor to call
// -- a2 : allocation site feedback if available, undefined otherwise. // -- a2 : address of the first argument
// -- t4 : address of the first argument
// ----------------------------------- // -----------------------------------
// Find the address of the last argument. // Find the address of the last argument.
__ sll(t0, a0, kPointerSizeLog2); __ sll(t0, a0, kPointerSizeLog2);
__ Subu(t0, t4, Operand(t0)); __ Subu(t0, a2, Operand(t0));
// Push a slot for the receiver. // Push a slot for the receiver.
__ push(zero_reg); __ push(zero_reg);
...@@ -1219,27 +1217,14 @@ void Builtins::Generate_InterpreterPushArgsAndConstructImpl( ...@@ -1219,27 +1217,14 @@ void Builtins::Generate_InterpreterPushArgsAndConstructImpl(
Label loop_header, loop_check; Label loop_header, loop_check;
__ Branch(&loop_check); __ Branch(&loop_check);
__ bind(&loop_header); __ bind(&loop_header);
__ lw(t1, MemOperand(t4)); __ lw(t1, MemOperand(a2));
__ Addu(t4, t4, Operand(-kPointerSize)); __ Addu(a2, a2, Operand(-kPointerSize));
__ push(t1); __ push(t1);
__ bind(&loop_check); __ bind(&loop_check);
__ Branch(&loop_header, gt, t4, Operand(t0)); __ Branch(&loop_header, gt, a2, Operand(t0));
__ AssertUndefinedOrAllocationSite(a2, t0); // Call the constructor with a0, a1, and a3 unmodified.
if (construct_type == CallableType::kJSFunction) { __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET);
__ AssertFunction(a1);
// Tail call to the function-specific construct stub (still in the caller
// context at this point).
__ lw(t0, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
__ lw(t0, FieldMemOperand(t0, SharedFunctionInfo::kConstructStubOffset));
__ Addu(at, t0, Operand(Code::kHeaderSize - kHeapObjectTag));
__ Jump(at);
} else {
DCHECK_EQ(construct_type, CallableType::kAny);
// Call the constructor with a0, a1, and a3 unmodified.
__ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET);
}
} }
void Builtins::Generate_InterpreterEnterBytecodeDispatch(MacroAssembler* masm) { void Builtins::Generate_InterpreterEnterBytecodeDispatch(MacroAssembler* masm) {
......
...@@ -1190,19 +1190,17 @@ void Builtins::Generate_InterpreterPushArgsAndCallImpl( ...@@ -1190,19 +1190,17 @@ void Builtins::Generate_InterpreterPushArgsAndCallImpl(
} }
// static // static
void Builtins::Generate_InterpreterPushArgsAndConstructImpl( void Builtins::Generate_InterpreterPushArgsAndConstruct(MacroAssembler* masm) {
MacroAssembler* masm, CallableType construct_type) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- a0 : argument count (not including receiver) // -- a0 : argument count (not including receiver)
// -- a3 : new target // -- a3 : new target
// -- a1 : constructor to call // -- a1 : constructor to call
// -- a2 : allocation site feedback if available, undefined otherwise. // -- a2 : address of the first argument
// -- a4 : address of the first argument
// ----------------------------------- // -----------------------------------
// Find the address of the last argument. // Find the address of the last argument.
__ dsll(t0, a0, kPointerSizeLog2); __ dsll(t0, a0, kPointerSizeLog2);
__ Dsubu(t0, a4, Operand(t0)); __ Dsubu(t0, a2, Operand(t0));
// Push a slot for the receiver. // Push a slot for the receiver.
__ push(zero_reg); __ push(zero_reg);
...@@ -1211,27 +1209,14 @@ void Builtins::Generate_InterpreterPushArgsAndConstructImpl( ...@@ -1211,27 +1209,14 @@ void Builtins::Generate_InterpreterPushArgsAndConstructImpl(
Label loop_header, loop_check; Label loop_header, loop_check;
__ Branch(&loop_check); __ Branch(&loop_check);
__ bind(&loop_header); __ bind(&loop_header);
__ ld(t1, MemOperand(a4)); __ ld(t1, MemOperand(a2));
__ Daddu(a4, a4, Operand(-kPointerSize)); __ Daddu(a2, a2, Operand(-kPointerSize));
__ push(t1); __ push(t1);
__ bind(&loop_check); __ bind(&loop_check);
__ Branch(&loop_header, gt, a4, Operand(t0)); __ Branch(&loop_header, gt, a2, Operand(t0));
__ AssertUndefinedOrAllocationSite(a2, t0); // Call the constructor with a0, a1, and a3 unmodified.
if (construct_type == CallableType::kJSFunction) { __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET);
__ AssertFunction(a1);
// Tail call to the function-specific construct stub (still in the caller
// context at this point).
__ ld(a4, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
__ ld(a4, FieldMemOperand(a4, SharedFunctionInfo::kConstructStubOffset));
__ Daddu(at, a4, Operand(Code::kHeaderSize - kHeapObjectTag));
__ Jump(at);
} else {
DCHECK_EQ(construct_type, CallableType::kAny);
// Call the constructor with a0, a1, and a3 unmodified.
__ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET);
}
} }
void Builtins::Generate_InterpreterEnterBytecodeDispatch(MacroAssembler* masm) { void Builtins::Generate_InterpreterEnterBytecodeDispatch(MacroAssembler* masm) {
......
...@@ -778,9 +778,7 @@ void Builtins::Generate_InterpreterMarkBaselineOnReturn(MacroAssembler* masm) { ...@@ -778,9 +778,7 @@ void Builtins::Generate_InterpreterMarkBaselineOnReturn(MacroAssembler* masm) {
} }
static void Generate_InterpreterPushArgs(MacroAssembler* masm, static void Generate_InterpreterPushArgs(MacroAssembler* masm,
Register num_args, bool push_receiver) {
Register start_address,
Register scratch, bool push_receiver) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- rax : the number of arguments (not including the receiver) // -- rax : the number of arguments (not including the receiver)
// -- rbx : the address of the first argument to be pushed. Subsequent // -- rbx : the address of the first argument to be pushed. Subsequent
...@@ -789,23 +787,23 @@ static void Generate_InterpreterPushArgs(MacroAssembler* masm, ...@@ -789,23 +787,23 @@ static void Generate_InterpreterPushArgs(MacroAssembler* masm,
// ----------------------------------- // -----------------------------------
// Find the address of the last argument. // Find the address of the last argument.
__ movp(scratch, num_args); __ movp(rcx, rax);
if (push_receiver) { if (push_receiver) {
__ addp(scratch, Immediate(1)); // Add one for receiver. __ addp(rcx, Immediate(1)); // Add one for receiver.
} }
__ shlp(scratch, Immediate(kPointerSizeLog2)); __ shlp(rcx, Immediate(kPointerSizeLog2));
__ negp(scratch); __ negp(rcx);
__ addp(scratch, start_address); __ addp(rcx, rbx);
// Push the arguments. // Push the arguments.
Label loop_header, loop_check; Label loop_header, loop_check;
__ j(always, &loop_check); __ j(always, &loop_check);
__ bind(&loop_header); __ bind(&loop_header);
__ Push(Operand(start_address, 0)); __ Push(Operand(rbx, 0));
__ subp(start_address, Immediate(kPointerSize)); __ subp(rbx, Immediate(kPointerSize));
__ bind(&loop_check); __ bind(&loop_check);
__ cmpp(start_address, scratch); __ cmpp(rbx, rcx);
__ j(greater, &loop_header, Label::kNear); __ j(greater, &loop_header, Label::kNear);
} }
...@@ -824,9 +822,7 @@ void Builtins::Generate_InterpreterPushArgsAndCallImpl( ...@@ -824,9 +822,7 @@ void Builtins::Generate_InterpreterPushArgsAndCallImpl(
// Pop return address to allow tail-call after pushing arguments. // Pop return address to allow tail-call after pushing arguments.
__ PopReturnAddressTo(kScratchRegister); __ PopReturnAddressTo(kScratchRegister);
// TODO(mythria): Add a stack check before pushing arguments. Generate_InterpreterPushArgs(masm, true);
// rax is readonly rcx and r8 will be modified.
Generate_InterpreterPushArgs(masm, rax, rbx, rcx, true);
// Call the target. // Call the target.
__ PushReturnAddressFrom(kScratchRegister); // Re-push return address. __ PushReturnAddressFrom(kScratchRegister); // Re-push return address.
...@@ -844,15 +840,13 @@ void Builtins::Generate_InterpreterPushArgsAndCallImpl( ...@@ -844,15 +840,13 @@ void Builtins::Generate_InterpreterPushArgsAndCallImpl(
} }
// static // static
void Builtins::Generate_InterpreterPushArgsAndConstructImpl( void Builtins::Generate_InterpreterPushArgsAndConstruct(MacroAssembler* masm) {
MacroAssembler* masm, CallableType construct_type) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- rax : the number of arguments (not including the receiver) // -- rax : the number of arguments (not including the receiver)
// -- rdx : the new target (either the same as the constructor or // -- rdx : the new target (either the same as the constructor or
// the JSFunction on which new was invoked initially) // the JSFunction on which new was invoked initially)
// -- rdi : the constructor to call (can be any Object) // -- rdi : the constructor to call (can be any Object)
// -- rbx : the allocation site feedback if available, undefined otherwise // -- rbx : the address of the first argument to be pushed. Subsequent
// -- rcx : the address of the first argument to be pushed. Subsequent
// arguments should be consecutive above this, in the same order as // arguments should be consecutive above this, in the same order as
// they are to be pushed onto the stack. // they are to be pushed onto the stack.
// ----------------------------------- // -----------------------------------
...@@ -863,29 +857,13 @@ void Builtins::Generate_InterpreterPushArgsAndConstructImpl( ...@@ -863,29 +857,13 @@ void Builtins::Generate_InterpreterPushArgsAndConstructImpl(
// Push slot for the receiver to be constructed. // Push slot for the receiver to be constructed.
__ Push(Immediate(0)); __ Push(Immediate(0));
// TODO(mythria): Add a stack check before pushing arguments. Generate_InterpreterPushArgs(masm, false);
// rax is readonly rcx and r8 will be modified.
Generate_InterpreterPushArgs(masm, rax, rcx, r8, false);
// Push return address in preparation for the tail-call. // Push return address in preparation for the tail-call.
__ PushReturnAddressFrom(kScratchRegister); __ PushReturnAddressFrom(kScratchRegister);
__ AssertUndefinedOrAllocationSite(rbx); // Call the constructor (rax, rdx, rdi passed on).
if (construct_type == CallableType::kJSFunction) { __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET);
// Tail call to the function-specific construct stub (still in the caller
// context at this point).
__ AssertFunction(rdi);
__ movp(rcx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset));
__ movp(rcx, FieldOperand(rcx, SharedFunctionInfo::kConstructStubOffset));
__ leap(rcx, FieldOperand(rcx, Code::kHeaderSize));
// Jump to the constructor function (rax, rbx, rdx passed on).
__ jmp(rcx);
} else {
DCHECK_EQ(construct_type, CallableType::kAny);
// Call the constructor (rax, rdx, rdi passed on).
__ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET);
}
} }
void Builtins::Generate_InterpreterEnterBytecodeDispatch(MacroAssembler* masm) { void Builtins::Generate_InterpreterEnterBytecodeDispatch(MacroAssembler* masm) {
......
...@@ -576,11 +576,9 @@ Callable CodeFactory::InterpreterPushArgsAndCall(Isolate* isolate, ...@@ -576,11 +576,9 @@ Callable CodeFactory::InterpreterPushArgsAndCall(Isolate* isolate,
} }
// static // static
Callable CodeFactory::InterpreterPushArgsAndConstruct( Callable CodeFactory::InterpreterPushArgsAndConstruct(Isolate* isolate) {
Isolate* isolate, CallableType function_type) { return Callable(isolate->builtins()->InterpreterPushArgsAndConstruct(),
return Callable( InterpreterPushArgsAndConstructDescriptor(isolate));
isolate->builtins()->InterpreterPushArgsAndConstruct(function_type),
InterpreterPushArgsAndConstructDescriptor(isolate));
} }
// static // static
......
...@@ -156,8 +156,7 @@ class CodeFactory final { ...@@ -156,8 +156,7 @@ class CodeFactory final {
static Callable InterpreterPushArgsAndCall( static Callable InterpreterPushArgsAndCall(
Isolate* isolate, TailCallMode tail_call_mode, Isolate* isolate, TailCallMode tail_call_mode,
CallableType function_type = CallableType::kAny); CallableType function_type = CallableType::kAny);
static Callable InterpreterPushArgsAndConstruct( static Callable InterpreterPushArgsAndConstruct(Isolate* isolate);
Isolate* isolate, CallableType function_type = CallableType::kAny);
static Callable InterpreterCEntry(Isolate* isolate, int result_size = 1); static Callable InterpreterCEntry(Isolate* isolate, int result_size = 1);
static Callable InterpreterOnStackReplacement(Isolate* isolate); static Callable InterpreterOnStackReplacement(Isolate* isolate);
}; };
......
...@@ -1094,17 +1094,12 @@ void BytecodeGraphBuilder::VisitNew() { ...@@ -1094,17 +1094,12 @@ void BytecodeGraphBuilder::VisitNew() {
interpreter::Register callee_reg = bytecode_iterator().GetRegisterOperand(0); interpreter::Register callee_reg = bytecode_iterator().GetRegisterOperand(0);
interpreter::Register first_arg = bytecode_iterator().GetRegisterOperand(1); interpreter::Register first_arg = bytecode_iterator().GetRegisterOperand(1);
size_t arg_count = bytecode_iterator().GetRegisterCountOperand(2); size_t arg_count = bytecode_iterator().GetRegisterCountOperand(2);
// Slot index of 0 is used indicate no feedback slot is available. Assert
// the assumption that slot index 0 is never a valid feedback slot.
STATIC_ASSERT(TypeFeedbackVector::kReservedIndexCount > 0);
VectorSlotPair feedback =
CreateVectorSlotPair(bytecode_iterator().GetIndexOperand(3));
Node* new_target = environment()->LookupAccumulator(); Node* new_target = environment()->LookupAccumulator();
Node* callee = environment()->LookupRegister(callee_reg); Node* callee = environment()->LookupRegister(callee_reg);
// TODO(turbofan): Pass the feedback here.
const Operator* call = const Operator* call = javascript()->CallConstruct(
javascript()->CallConstruct(static_cast<int>(arg_count) + 2, feedback); static_cast<int>(arg_count) + 2, VectorSlotPair());
Node* value = ProcessCallNewArguments(call, callee, new_target, first_arg, Node* value = ProcessCallNewArguments(call, callee, new_target, first_arg,
arg_count + 2); arg_count + 2);
environment()->BindAccumulator(value, &states); environment()->BindAccumulator(value, &states);
......
...@@ -389,8 +389,7 @@ void InterpreterPushArgsAndConstructDescriptor::InitializePlatformSpecific( ...@@ -389,8 +389,7 @@ void InterpreterPushArgsAndConstructDescriptor::InitializePlatformSpecific(
eax, // argument count (not including receiver) eax, // argument count (not including receiver)
edx, // new target edx, // new target
edi, // constructor edi, // constructor
ebx, // allocation site feedback ebx, // address of first argument
ecx, // address of first argument
}; };
data->InitializePlatformSpecific(arraysize(registers), registers); data->InitializePlatformSpecific(arraysize(registers), registers);
} }
......
...@@ -588,15 +588,13 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::Call(Register callable, ...@@ -588,15 +588,13 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::Call(Register callable,
BytecodeArrayBuilder& BytecodeArrayBuilder::New(Register constructor, BytecodeArrayBuilder& BytecodeArrayBuilder::New(Register constructor,
Register first_arg, Register first_arg,
size_t arg_count, size_t arg_count) {
int feedback_slot_id) {
if (!first_arg.is_valid()) { if (!first_arg.is_valid()) {
DCHECK_EQ(0u, arg_count); DCHECK_EQ(0u, arg_count);
first_arg = Register(0); first_arg = Register(0);
} }
Output(Bytecode::kNew, RegisterOperand(constructor), Output(Bytecode::kNew, RegisterOperand(constructor),
RegisterOperand(first_arg), UnsignedOperand(arg_count), RegisterOperand(first_arg), UnsignedOperand(arg_count));
UnsignedOperand(feedback_slot_id));
return *this; return *this;
} }
......
...@@ -176,7 +176,7 @@ class BytecodeArrayBuilder final : public ZoneObject { ...@@ -176,7 +176,7 @@ class BytecodeArrayBuilder final : public ZoneObject {
// consecutive arguments starting at |first_arg| for the constuctor // consecutive arguments starting at |first_arg| for the constuctor
// invocation. // invocation.
BytecodeArrayBuilder& New(Register constructor, Register first_arg, BytecodeArrayBuilder& New(Register constructor, Register first_arg,
size_t arg_count, int feedback_slot); size_t arg_count);
// Call the runtime function with |function_id|. The first argument should be // Call the runtime function with |function_id|. The first argument should be
// in |first_arg| and all subsequent arguments should be in registers // in |first_arg| and all subsequent arguments should be in registers
......
...@@ -2619,7 +2619,7 @@ void BytecodeGenerator::VisitCall(Call* expr) { ...@@ -2619,7 +2619,7 @@ void BytecodeGenerator::VisitCall(Call* expr) {
if (expr->CallFeedbackICSlot().IsInvalid()) { if (expr->CallFeedbackICSlot().IsInvalid()) {
DCHECK(call_type == Call::POSSIBLY_EVAL_CALL); DCHECK(call_type == Call::POSSIBLY_EVAL_CALL);
// Valid type feedback slots can only be greater than kReservedIndexCount. // Valid type feedback slots can only be greater than kReservedIndexCount.
// We use 0 to indicate an invalid slot id. Statically assert that 0 cannot // We use 0 to indicate an invalid slot it. Statically assert that 0 cannot
// be a valid slot id. // be a valid slot id.
STATIC_ASSERT(TypeFeedbackVector::kReservedIndexCount > 0); STATIC_ASSERT(TypeFeedbackVector::kReservedIndexCount > 0);
feedback_slot_index = 0; feedback_slot_index = 0;
...@@ -2654,13 +2654,7 @@ void BytecodeGenerator::VisitCallSuper(Call* expr) { ...@@ -2654,13 +2654,7 @@ void BytecodeGenerator::VisitCallSuper(Call* expr) {
// Call construct. // Call construct.
builder()->SetExpressionPosition(expr); builder()->SetExpressionPosition(expr);
// Valid type feedback slots can only be greater than kReservedIndexCount. builder()->New(constructor, first_arg, args->length());
// Assert that 0 cannot be valid a valid slot id.
STATIC_ASSERT(TypeFeedbackVector::kReservedIndexCount > 0);
// Type feedback is not necessary for super constructor calls. The type
// information can be inferred in most cases. Slot id 0 indicates type
// feedback is not required.
builder()->New(constructor, first_arg, args->length(), 0);
execution_result()->SetResultInAccumulator(); execution_result()->SetResultInAccumulator();
} }
...@@ -2677,8 +2671,7 @@ void BytecodeGenerator::VisitCallNew(CallNew* expr) { ...@@ -2677,8 +2671,7 @@ void BytecodeGenerator::VisitCallNew(CallNew* expr) {
// constructor for CallNew. // constructor for CallNew.
builder() builder()
->LoadAccumulatorWithRegister(constructor) ->LoadAccumulatorWithRegister(constructor)
.New(constructor, first_arg, args->length(), .New(constructor, first_arg, args->length());
feedback_index(expr->CallNewFeedbackSlot()));
execution_result()->SetResultInAccumulator(); execution_result()->SetResultInAccumulator();
} }
......
...@@ -197,7 +197,7 @@ namespace interpreter { ...@@ -197,7 +197,7 @@ namespace interpreter {
\ \
/* New operator */ \ /* New operator */ \
V(New, AccumulatorUse::kReadWrite, OperandType::kReg, \ V(New, AccumulatorUse::kReadWrite, OperandType::kReg, \
OperandType::kMaybeReg, OperandType::kRegCount, OperandType::kIdx) \ OperandType::kMaybeReg, OperandType::kRegCount) \
\ \
/* Test Operators */ \ /* Test Operators */ \
V(TestEqual, AccumulatorUse::kReadWrite, OperandType::kReg) \ V(TestEqual, AccumulatorUse::kReadWrite, OperandType::kReg) \
......
...@@ -489,7 +489,7 @@ Node* InterpreterAssembler::CallJSWithFeedback(Node* function, Node* context, ...@@ -489,7 +489,7 @@ Node* InterpreterAssembler::CallJSWithFeedback(Node* function, Node* context,
Node* is_feedback_unavailable = Word32Equal(slot_id, Int32Constant(0)); Node* is_feedback_unavailable = Word32Equal(slot_id, Int32Constant(0));
GotoIf(is_feedback_unavailable, &call); GotoIf(is_feedback_unavailable, &call);
// The checks. First, does function match the recorded monomorphic target? // The checks. First, does rdi match the recorded monomorphic target?
Node* feedback_element = LoadFixedArrayElement(type_feedback_vector, slot_id); Node* feedback_element = LoadFixedArrayElement(type_feedback_vector, slot_id);
Node* feedback_value = LoadWeakCellValue(feedback_element); Node* feedback_value = LoadWeakCellValue(feedback_element);
Node* is_monomorphic = WordEqual(function, feedback_value); Node* is_monomorphic = WordEqual(function, feedback_value);
...@@ -623,202 +623,11 @@ Node* InterpreterAssembler::CallJS(Node* function, Node* context, ...@@ -623,202 +623,11 @@ Node* InterpreterAssembler::CallJS(Node* function, Node* context,
Node* InterpreterAssembler::CallConstruct(Node* constructor, Node* context, Node* InterpreterAssembler::CallConstruct(Node* constructor, Node* context,
Node* new_target, Node* first_arg, Node* new_target, Node* first_arg,
Node* arg_count, Node* slot_id, Node* arg_count) {
Node* type_feedback_vector) { Callable callable = CodeFactory::InterpreterPushArgsAndConstruct(isolate());
Label call_construct(this), js_function(this), end(this); Node* code_target = HeapConstant(callable.code());
Variable return_value(this, MachineRepresentation::kTagged); return CallStub(callable.descriptor(), code_target, context, arg_count,
Variable allocation_feedback(this, MachineRepresentation::kTagged); new_target, constructor, first_arg);
allocation_feedback.Bind(UndefinedConstant());
// Slot id of 0 is used to indicate no type feedback is available.
STATIC_ASSERT(TypeFeedbackVector::kReservedIndexCount > 0);
Node* is_feedback_unavailable = Word32Equal(slot_id, Int32Constant(0));
GotoIf(is_feedback_unavailable, &call_construct);
// Check that the constructor is not a smi.
Node* is_smi = WordIsSmi(constructor);
GotoIf(is_smi, &call_construct);
// Check that constructor is a JSFunction.
Node* instance_type = LoadInstanceType(constructor);
Node* is_js_function =
WordEqual(instance_type, Int32Constant(JS_FUNCTION_TYPE));
BranchIf(is_js_function, &js_function, &call_construct);
Bind(&js_function);
{
// Cache the called function in a feedback vector slot. Cache states
// are uninitialized, monomorphic (indicated by a JSFunction), and
// megamorphic.
// TODO(mythria/v8:5210): Check if it is better to mark extra_checks as a
// deferred block so that call_construct_function will be scheduled just
// after increment_count and in the fast path we can reduce one branch in
// the
// fast path.
Label increment_count(this), extra_checks(this),
call_construct_function(this);
Node* feedback_element =
LoadFixedArrayElement(type_feedback_vector, slot_id);
Node* feedback_value = LoadWeakCellValue(feedback_element);
Node* is_monomorphic = WordEqual(constructor, feedback_value);
BranchIf(is_monomorphic, &increment_count, &extra_checks);
Bind(&extra_checks);
{
Label mark_megamorphic(this), initialize(this),
check_allocation_site(this), check_initialized(this),
set_alloc_feedback_and_inc_count(this);
{
// Check if it is a megamorphic target
Comment("check if megamorphic");
Node* is_megamorphic = WordEqual(
feedback_element,
HeapConstant(TypeFeedbackVector::MegamorphicSentinel(isolate())));
GotoIf(is_megamorphic, &call_construct_function);
Comment("check if weak cell");
Node* is_weak_cell = WordEqual(LoadMap(feedback_element),
LoadRoot(Heap::kWeakCellMapRootIndex));
GotoUnless(is_weak_cell, &check_allocation_site);
// If the weak cell is cleared, we have a new chance to become
// monomorphic.
Comment("check if weak cell is cleared");
Node* is_smi = WordIsSmi(feedback_value);
BranchIf(is_smi, &initialize, &mark_megamorphic);
}
Bind(&check_allocation_site);
{
Comment("check if it is an allocation site");
Node* is_allocation_site =
WordEqual(LoadObjectField(feedback_element, 0),
LoadRoot(Heap::kAllocationSiteMapRootIndex));
GotoUnless(is_allocation_site, &check_initialized);
// Make sure the function is the Array() function
Node* context_slot =
LoadFixedArrayElement(LoadNativeContext(context),
Int32Constant(Context::ARRAY_FUNCTION_INDEX));
Node* is_array_function = WordEqual(context_slot, constructor);
BranchIf(is_array_function, &set_alloc_feedback_and_inc_count,
&mark_megamorphic);
}
Bind(&set_alloc_feedback_and_inc_count);
{
allocation_feedback.Bind(feedback_element);
Goto(&increment_count);
}
Bind(&check_initialized);
{
// Check if it is uninitialized.
Comment("check if uninitialized");
Node* is_uninitialized = WordEqual(
feedback_element, LoadRoot(Heap::kuninitialized_symbolRootIndex));
BranchIf(is_uninitialized, &initialize, &mark_megamorphic);
}
Bind(&initialize);
{
Label initialize_count(this), create_weak_cell(this),
create_allocation_site(this);
Comment("initialize the feedback element");
// Check that it is the Array() function.
Node* context_slot =
LoadFixedArrayElement(LoadNativeContext(context),
Int32Constant(Context::ARRAY_FUNCTION_INDEX));
Node* is_array_function = WordEqual(context_slot, constructor);
BranchIf(is_array_function, &create_allocation_site, &create_weak_cell);
Bind(&create_allocation_site);
{
// TODO(mythria): Inline the creation of allocation site.
CreateAllocationSiteStub create_stub(isolate());
CallStub(create_stub.GetCallInterfaceDescriptor(),
HeapConstant(create_stub.GetCode()), context,
type_feedback_vector, SmiTag(slot_id));
Node* feedback_element =
LoadFixedArrayElement(type_feedback_vector, slot_id);
allocation_feedback.Bind(feedback_element);
Goto(&initialize_count);
}
Bind(&create_weak_cell);
{
CreateWeakCellInFeedbackVector(type_feedback_vector, SmiTag(slot_id),
constructor);
Goto(&initialize_count);
}
Bind(&initialize_count);
{
Node* call_count_slot = IntPtrAdd(slot_id, IntPtrConstant(1));
// Count is Smi, so we don't need a write barrier.
StoreFixedArrayElement(type_feedback_vector, call_count_slot,
SmiTag(Int32Constant(1)), SKIP_WRITE_BARRIER);
Goto(&call_construct_function);
}
}
Bind(&mark_megamorphic);
{
// MegamorphicSentinel is an immortal immovable object so no
// write-barrier
// is needed.
Comment("transition to megamorphic");
DCHECK(
Heap::RootIsImmortalImmovable(Heap::kmegamorphic_symbolRootIndex));
StoreFixedArrayElement(
type_feedback_vector, slot_id,
HeapConstant(TypeFeedbackVector::MegamorphicSentinel(isolate())),
SKIP_WRITE_BARRIER);
Goto(&call_construct_function);
}
}
Bind(&increment_count);
{
// Increment the call count.
Comment("increment call count");
Node* call_count_slot = IntPtrAdd(slot_id, IntPtrConstant(1));
Node* call_count =
LoadFixedArrayElement(type_feedback_vector, call_count_slot);
Node* new_count = SmiAdd(call_count, SmiTag(Int32Constant(1)));
// Count is Smi, so we don't need a write barrier.
StoreFixedArrayElement(type_feedback_vector, call_count_slot, new_count,
SKIP_WRITE_BARRIER);
Goto(&call_construct_function);
}
Bind(&call_construct_function);
{
Comment("call using callConstructFunction");
Callable callable_function = CodeFactory::InterpreterPushArgsAndConstruct(
isolate(), CallableType::kJSFunction);
return_value.Bind(CallStub(callable_function.descriptor(),
HeapConstant(callable_function.code()),
context, arg_count, new_target, constructor,
allocation_feedback.value(), first_arg));
Goto(&end);
}
}
Bind(&call_construct);
{
Comment("call using callConstruct builtin");
Callable callable = CodeFactory::InterpreterPushArgsAndConstruct(
isolate(), CallableType::kAny);
Node* code_target = HeapConstant(callable.code());
return_value.Bind(CallStub(callable.descriptor(), code_target, context,
arg_count, new_target, constructor,
UndefinedConstant(), first_arg));
Goto(&end);
}
Bind(&end);
return return_value.value();
} }
Node* InterpreterAssembler::CallRuntimeN(Node* function_id, Node* context, Node* InterpreterAssembler::CallRuntimeN(Node* function_id, Node* context,
......
...@@ -120,9 +120,7 @@ class InterpreterAssembler : public CodeStubAssembler { ...@@ -120,9 +120,7 @@ class InterpreterAssembler : public CodeStubAssembler {
compiler::Node* context, compiler::Node* context,
compiler::Node* new_target, compiler::Node* new_target,
compiler::Node* first_arg, compiler::Node* first_arg,
compiler::Node* arg_count, compiler::Node* arg_count);
compiler::Node* slot_id,
compiler::Node* type_feedback_vector);
// Call runtime function with |arg_count| arguments and the first argument // Call runtime function with |arg_count| arguments and the first argument
// located at |first_arg|. // located at |first_arg|.
......
...@@ -1305,11 +1305,9 @@ void Interpreter::DoCallConstruct(InterpreterAssembler* assembler) { ...@@ -1305,11 +1305,9 @@ void Interpreter::DoCallConstruct(InterpreterAssembler* assembler) {
Node* first_arg_reg = __ BytecodeOperandReg(1); Node* first_arg_reg = __ BytecodeOperandReg(1);
Node* first_arg = __ RegisterLocation(first_arg_reg); Node* first_arg = __ RegisterLocation(first_arg_reg);
Node* args_count = __ BytecodeOperandCount(2); Node* args_count = __ BytecodeOperandCount(2);
Node* slot_id = __ BytecodeOperandIdx(3);
Node* type_feedback_vector = __ LoadTypeFeedbackVector();
Node* context = __ GetContext(); Node* context = __ GetContext();
Node* result = __ CallConstruct(constructor, context, new_target, first_arg, Node* result =
args_count, slot_id, type_feedback_vector); __ CallConstruct(constructor, context, new_target, first_arg, args_count);
__ SetAccumulator(result); __ SetAccumulator(result);
__ Dispatch(); __ Dispatch();
} }
......
...@@ -381,8 +381,7 @@ void InterpreterPushArgsAndConstructDescriptor::InitializePlatformSpecific( ...@@ -381,8 +381,7 @@ void InterpreterPushArgsAndConstructDescriptor::InitializePlatformSpecific(
a0, // argument count (not including receiver) a0, // argument count (not including receiver)
a3, // new target a3, // new target
a1, // constructor to call a1, // constructor to call
a2, // allocation site feedback if available, undefined otherwise. a2 // address of the first argument
t4 // address of the first argument
}; };
data->InitializePlatformSpecific(arraysize(registers), registers); data->InitializePlatformSpecific(arraysize(registers), registers);
} }
......
...@@ -380,8 +380,7 @@ void InterpreterPushArgsAndConstructDescriptor::InitializePlatformSpecific( ...@@ -380,8 +380,7 @@ void InterpreterPushArgsAndConstructDescriptor::InitializePlatformSpecific(
a0, // argument count (not including receiver) a0, // argument count (not including receiver)
a3, // new target a3, // new target
a1, // constructor to call a1, // constructor to call
a2, // allocation site feedback if available, undefined otherwise. a2 // address of the first argument
a4 // address of the first argument
}; };
data->InitializePlatformSpecific(arraysize(registers), registers); data->InitializePlatformSpecific(arraysize(registers), registers);
} }
......
...@@ -380,8 +380,7 @@ void InterpreterPushArgsAndConstructDescriptor::InitializePlatformSpecific( ...@@ -380,8 +380,7 @@ void InterpreterPushArgsAndConstructDescriptor::InitializePlatformSpecific(
rax, // argument count (not including receiver) rax, // argument count (not including receiver)
rdx, // new target rdx, // new target
rdi, // constructor rdi, // constructor
rbx, // allocation site feedback if available, undefined otherwise rbx, // address of first argument
rcx, // address of first argument
}; };
data->InitializePlatformSpecific(arraysize(registers), registers); data->InitializePlatformSpecific(arraysize(registers), registers);
} }
......
...@@ -130,6 +130,12 @@ ...@@ -130,6 +130,12 @@
# TODO(mythria,4780): Related to type feedback support for Array function. # TODO(mythria,4780): Related to type feedback support for Array function.
'test-feedback-vector/VectorCallFeedbackForArray': [PASS, NO_IGNITION], 'test-feedback-vector/VectorCallFeedbackForArray': [PASS, NO_IGNITION],
# TODO(mythria,4780): Related to type feedback support for constructor.
'test-feedback-vector/VectorConstructCounts': [PASS, NO_IGNITION],
'test-heap/WeakFunctionInConstructor': [PASS, NO_IGNITION],
'test-heap/IncrementalMarkingClearsMonomorphicConstructor': [PASS, NO_IGNITION],
'test-heap/IncrementalMarkingPreservesMonomorphicConstructor': [PASS, NO_IGNITION],
# TODO(mythria,4680): Lack of code-ageing in interpreter. # TODO(mythria,4680): Lack of code-ageing in interpreter.
'test-heap/Regress169209': [PASS, NO_IGNITION], 'test-heap/Regress169209': [PASS, NO_IGNITION],
...@@ -144,8 +150,8 @@ ...@@ -144,8 +150,8 @@
# BUG(4680): Missing type feedback makes optimistic optimizations fail. # BUG(4680): Missing type feedback makes optimistic optimizations fail.
'test-cpu-profiler/DeoptUntrackedFunction': [PASS, NO_IGNITION], 'test-cpu-profiler/DeoptUntrackedFunction': [PASS, NO_IGNITION],
# TODO(mythria, 4780): In interpreter we disable mementos when creating array # BUG(4680): Ignition doesn't support allocation sites currently.
# literals. 'test-heap/EnsureAllocationSiteDependentCodesProcessed': [PASS, NO_IGNITION],
'test-heap/OptimizedPretenuringAllocationFolding': [PASS, NO_IGNITION], 'test-heap/OptimizedPretenuringAllocationFolding': [PASS, NO_IGNITION],
'test-heap/OptimizedPretenuringdoubleArrayLiterals': [PASS, NO_IGNITION], 'test-heap/OptimizedPretenuringdoubleArrayLiterals': [PASS, NO_IGNITION],
'test-heap/OptimizedPretenuringNestedDoubleLiterals': [PASS, NO_IGNITION], 'test-heap/OptimizedPretenuringNestedDoubleLiterals': [PASS, NO_IGNITION],
...@@ -423,6 +429,12 @@ ...@@ -423,6 +429,12 @@
# TODO(mythria,4780): Related to type feedback support for Array function. # TODO(mythria,4780): Related to type feedback support for Array function.
'test-feedback-vector/VectorCallFeedbackForArray': [FAIL], 'test-feedback-vector/VectorCallFeedbackForArray': [FAIL],
# TODO(mythria,4780): Related to type feedback support for constructor.
'test-feedback-vector/VectorConstructCounts': [FAIL],
'test-heap/WeakFunctionInConstructor': [FAIL],
'test-heap/IncrementalMarkingClearsMonomorphicConstructor': [FAIL],
'test-heap/IncrementalMarkingPreservesMonomorphicConstructor': [FAIL],
# TODO(mythria,4680): Lack of code-ageing in interpreter. # TODO(mythria,4680): Lack of code-ageing in interpreter.
'test-heap/Regress169209': [FAIL], 'test-heap/Regress169209': [FAIL],
...@@ -434,8 +446,8 @@ ...@@ -434,8 +446,8 @@
'test-cpu-profiler/CollectDeoptEvents': [FAIL], 'test-cpu-profiler/CollectDeoptEvents': [FAIL],
'test-cpu-profiler/DeoptUntrackedFunction': [FAIL], 'test-cpu-profiler/DeoptUntrackedFunction': [FAIL],
# TODO(mythria, 4780): In interpreter we disable mementos when creating array # BUG(4680): Ignition doesn't support allocation sites currently.
# literals. 'test-heap/EnsureAllocationSiteDependentCodesProcessed': [FAIL],
'test-heap/OptimizedPretenuringAllocationFolding': [FAIL], 'test-heap/OptimizedPretenuringAllocationFolding': [FAIL],
'test-heap/OptimizedPretenuringdoubleArrayLiterals': [FAIL], 'test-heap/OptimizedPretenuringdoubleArrayLiterals': [FAIL],
'test-heap/OptimizedPretenuringNestedDoubleLiterals': [FAIL], 'test-heap/OptimizedPretenuringNestedDoubleLiterals': [FAIL],
......
...@@ -16,12 +16,12 @@ snippet: " ...@@ -16,12 +16,12 @@ snippet: "
" "
frame size: 1 frame size: 1
parameter count: 1 parameter count: 1
bytecode array length: 12 bytecode array length: 11
bytecodes: [ bytecodes: [
/* 45 E> */ B(StackCheck), /* 45 E> */ B(StackCheck),
/* 50 S> */ B(LdrGlobal), U8(3), R(0), /* 50 S> */ B(LdrGlobal), U8(3), R(0),
B(Ldar), R(0), B(Ldar), R(0),
/* 57 E> */ B(New), R(0), R(0), U8(0), U8(1), /* 57 E> */ B(New), R(0), R(0), U8(0),
/* 68 S> */ B(Return), /* 68 S> */ B(Return),
] ]
constant pool: [ constant pool: [
...@@ -37,14 +37,14 @@ snippet: " ...@@ -37,14 +37,14 @@ snippet: "
" "
frame size: 2 frame size: 2
parameter count: 1 parameter count: 1
bytecode array length: 16 bytecode array length: 15
bytecodes: [ bytecodes: [
/* 58 E> */ B(StackCheck), /* 58 E> */ B(StackCheck),
/* 63 S> */ B(LdrGlobal), U8(3), R(0), /* 63 S> */ B(LdrGlobal), U8(3), R(0),
B(LdaSmi), U8(3), B(LdaSmi), U8(3),
B(Star), R(1), B(Star), R(1),
B(Ldar), R(0), B(Ldar), R(0),
/* 70 E> */ B(New), R(0), R(1), U8(1), U8(1), /* 70 E> */ B(New), R(0), R(1), U8(1),
/* 82 S> */ B(Return), /* 82 S> */ B(Return),
] ]
constant pool: [ constant pool: [
...@@ -65,7 +65,7 @@ snippet: " ...@@ -65,7 +65,7 @@ snippet: "
" "
frame size: 4 frame size: 4
parameter count: 1 parameter count: 1
bytecode array length: 24 bytecode array length: 23
bytecodes: [ bytecodes: [
/* 100 E> */ B(StackCheck), /* 100 E> */ B(StackCheck),
/* 105 S> */ B(LdrGlobal), U8(3), R(0), /* 105 S> */ B(LdrGlobal), U8(3), R(0),
...@@ -76,7 +76,7 @@ bytecodes: [ ...@@ -76,7 +76,7 @@ bytecodes: [
B(LdaSmi), U8(5), B(LdaSmi), U8(5),
B(Star), R(3), B(Star), R(3),
B(Ldar), R(0), B(Ldar), R(0),
/* 112 E> */ B(New), R(0), R(1), U8(3), U8(1), /* 112 E> */ B(New), R(0), R(1), U8(3),
/* 130 S> */ B(Return), /* 130 S> */ B(Return),
] ]
constant pool: [ constant pool: [
......
...@@ -127,7 +127,7 @@ snippet: " ...@@ -127,7 +127,7 @@ snippet: "
" "
frame size: 5 frame size: 5
parameter count: 1 parameter count: 1
bytecode array length: 106 bytecode array length: 105
bytecodes: [ bytecodes: [
B(Mov), R(closure), R(1), B(Mov), R(closure), R(1),
B(Mov), R(new_target), R(0), B(Mov), R(new_target), R(0),
...@@ -147,7 +147,7 @@ bytecodes: [ ...@@ -147,7 +147,7 @@ bytecodes: [
B(LdaConstant), U8(1), B(LdaConstant), U8(1),
B(Star), R(4), B(Star), R(4),
/* 118 E> */ B(CallRuntime), U16(Runtime::kThrowReferenceError), R(4), U8(1), /* 118 E> */ B(CallRuntime), U16(Runtime::kThrowReferenceError), R(4), U8(1),
/* 118 E> */ B(New), R(2), R(3), U8(1), U8(0), /* 118 E> */ B(New), R(2), R(3), U8(1),
B(Star), R(2), B(Star), R(2),
B(Ldar), R(this), B(Ldar), R(this),
B(JumpIfNotHole), U8(4), B(JumpIfNotHole), U8(4),
...@@ -195,7 +195,7 @@ snippet: " ...@@ -195,7 +195,7 @@ snippet: "
" "
frame size: 4 frame size: 4
parameter count: 1 parameter count: 1
bytecode array length: 102 bytecode array length: 101
bytecodes: [ bytecodes: [
B(Mov), R(closure), R(1), B(Mov), R(closure), R(1),
B(Mov), R(new_target), R(0), B(Mov), R(new_target), R(0),
...@@ -213,7 +213,7 @@ bytecodes: [ ...@@ -213,7 +213,7 @@ bytecodes: [
B(LdaConstant), U8(1), B(LdaConstant), U8(1),
B(Star), R(3), B(Star), R(3),
/* 117 E> */ B(CallRuntime), U16(Runtime::kThrowReferenceError), R(3), U8(1), /* 117 E> */ B(CallRuntime), U16(Runtime::kThrowReferenceError), R(3), U8(1),
/* 117 E> */ B(New), R(2), R(0), U8(0), U8(0), /* 117 E> */ B(New), R(2), R(0), U8(0),
B(Star), R(2), B(Star), R(2),
B(Ldar), R(this), B(Ldar), R(this),
B(JumpIfNotHole), U8(4), B(JumpIfNotHole), U8(4),
......
...@@ -196,7 +196,7 @@ snippet: " ...@@ -196,7 +196,7 @@ snippet: "
" "
frame size: 8 frame size: 8
parameter count: 1 parameter count: 1
bytecode array length: 73 bytecode array length: 72
bytecodes: [ bytecodes: [
B(CreateFunctionContext), U8(1), B(CreateFunctionContext), U8(1),
B(PushContext), R(3), B(PushContext), R(3),
...@@ -227,7 +227,7 @@ bytecodes: [ ...@@ -227,7 +227,7 @@ bytecodes: [
B(Star), R(5), B(Star), R(5),
B(CallRuntime), U16(Runtime::kThrowReferenceError), R(5), U8(1), B(CallRuntime), U16(Runtime::kThrowReferenceError), R(5), U8(1),
B(Star), R(4), B(Star), R(4),
/* 94 E> */ B(New), R(4), R(0), U8(0), U8(3), /* 94 E> */ B(New), R(4), R(0), U8(0),
/* 103 S> */ B(Return), /* 103 S> */ B(Return),
] ]
constant pool: [ constant pool: [
......
...@@ -223,12 +223,9 @@ ...@@ -223,12 +223,9 @@
############################################################################ ############################################################################
# Ignition # Ignition
# TODO(mythria, 4780): Related to lack of allocation site feedback for calls. # TODO(mythria, 4780): Related to type feedback for calls in interpreter.
'regress/regress-4121': [PASS, NO_IGNITION],
# TODO(mythria, 4780): In interpreter we disable mementos when creating array
# literals.
'array-literal-feedback': [PASS, NO_IGNITION], 'array-literal-feedback': [PASS, NO_IGNITION],
'regress/regress-4121': [PASS, NO_IGNITION],
# TODO(4680): Test doesn't know about three tier compiler pipeline. # TODO(4680): Test doesn't know about three tier compiler pipeline.
'assert-opt-and-deopt': [PASS, NO_IGNITION], 'assert-opt-and-deopt': [PASS, NO_IGNITION],
...@@ -264,6 +261,7 @@ ...@@ -264,6 +261,7 @@
'smi-mul-const': [PASS, NO_IGNITION], 'smi-mul-const': [PASS, NO_IGNITION],
'smi-mul': [PASS, NO_IGNITION], 'smi-mul': [PASS, NO_IGNITION],
'unary-minus-deopt': [PASS, NO_IGNITION], 'unary-minus-deopt': [PASS, NO_IGNITION],
'array-constructor-feedback': [PASS, NO_IGNITION],
'array-feedback': [PASS, NO_IGNITION], 'array-feedback': [PASS, NO_IGNITION],
'allocation-site-info': [PASS, NO_IGNITION], 'allocation-site-info': [PASS, NO_IGNITION],
...@@ -704,14 +702,11 @@ ...@@ -704,14 +702,11 @@
############################################################################## ##############################################################################
['variant == ignition_turbofan', { ['variant == ignition_turbofan', {
# TODO(mythria, 4780): Related to lack of allocation site feedback for calls # TODO(mythria, 4780): Related to type feedback for calls in interpreter.
# in interpreter. 'array-literal-feedback': [FAIL],
'regress/regress-4121': [FAIL], 'regress/regress-4121': [FAIL],
'array-constructor-feedback': [FAIL],
'array-feedback': [FAIL], 'array-feedback': [FAIL],
# TODO(mythria, 4780): In interpreter we disable mementos when creating array
# literals.
'array-literal-feedback': [FAIL],
'allocation-site-info': [FAIL], 'allocation-site-info': [FAIL],
'wasm/asm-wasm-f32': [PASS, ['arch in [arm64]', SKIP]], 'wasm/asm-wasm-f32': [PASS, ['arch in [arm64]', SKIP]],
......
...@@ -166,8 +166,8 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) { ...@@ -166,8 +166,8 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
builder.Delete(reg, LanguageMode::SLOPPY).Delete(reg, LanguageMode::STRICT); builder.Delete(reg, LanguageMode::SLOPPY).Delete(reg, LanguageMode::STRICT);
// Emit new. // Emit new.
builder.New(reg, reg, 0, 1); builder.New(reg, reg, 0);
builder.New(wide, wide, 0, 1); builder.New(wide, wide, 0);
// Emit test operator invocations. // Emit test operator invocations.
builder.CompareOperation(Token::Value::EQ, reg) builder.CompareOperation(Token::Value::EQ, reg)
...@@ -458,7 +458,7 @@ TEST_F(BytecodeArrayBuilderTest, FrameSizesLookGood) { ...@@ -458,7 +458,7 @@ TEST_F(BytecodeArrayBuilderTest, FrameSizesLookGood) {
// Ensure temporaries are used so not optimized away by the // Ensure temporaries are used so not optimized away by the
// register optimizer. // register optimizer.
builder.New(Register(locals + contexts), Register(locals + contexts), builder.New(Register(locals + contexts), Register(locals + contexts),
static_cast<size_t>(temps), 0); static_cast<size_t>(temps));
} }
builder.Return(); builder.Return();
......
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