[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

Review-Url: https://codereview.chromium.org/2190293003
Cr-Commit-Position: refs/heads/master@{#38364}
This commit is contained in:
mythria 2016-08-05 02:57:45 -07:00 committed by Commit bot
parent 4b4c354b91
commit 9d5e6129c4
30 changed files with 540 additions and 138 deletions

View File

@ -403,7 +403,8 @@ void InterpreterPushArgsAndConstructDescriptor::InitializePlatformSpecific(
r0, // argument count (not including receiver)
r3, // new target
r1, // constructor to call
r2 // address of the first argument
r2, // allocation site feedback if available, undefined otherwise
r4 // address of the first argument
};
data->InitializePlatformSpecific(arraysize(registers), registers);
}

View File

@ -435,7 +435,8 @@ void InterpreterPushArgsAndConstructDescriptor::InitializePlatformSpecific(
x0, // argument count (not including receiver)
x3, // new target
x1, // constructor to call
x2 // address of the first argument
x2, // allocation site feedback if available, undefined otherwise
x4 // address of the first argument
};
data->InitializePlatformSpecific(arraysize(registers), registers);
}

View File

@ -1189,6 +1189,7 @@ void Builtins::Generate_InterpreterPushArgsAndCallImpl(
__ mov(r3, Operand(r3, LSL, kPointerSizeLog2));
__ sub(r3, r2, r3);
// TODO(mythria): Add a stack check before pushing arguments.
// Push the arguments.
Generate_InterpreterPushArgs(masm, r2, r3, r4);
@ -1206,27 +1207,44 @@ void Builtins::Generate_InterpreterPushArgsAndCallImpl(
}
// static
void Builtins::Generate_InterpreterPushArgsAndConstruct(MacroAssembler* masm) {
void Builtins::Generate_InterpreterPushArgsAndConstructImpl(
MacroAssembler* masm, CallableType construct_type) {
// ----------- S t a t e -------------
// -- r0 : argument count (not including receiver)
// -- r3 : new target
// -- r1 : constructor to call
// -- r2 : address of the first argument
// -- r2 : allocation site feedback if available, undefined otherwise.
// -- r4 : address of the first argument
// -----------------------------------
// Find the address of the last argument.
__ mov(r4, Operand(r0, LSL, kPointerSizeLog2));
__ sub(r4, r2, r4);
__ mov(r5, Operand(r0, LSL, kPointerSizeLog2));
__ sub(r5, r4, r5);
// Push a slot for the receiver to be constructed.
__ mov(ip, Operand::Zero());
__ push(ip);
// TODO(mythria): Add a stack check before pushing arguments.
// Push the arguments.
Generate_InterpreterPushArgs(masm, r2, r4, r5);
Generate_InterpreterPushArgs(masm, r4, r5, r6);
// Call the constructor with r0, r1, and r3 unmodified.
__ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET);
__ AssertUndefinedOrAllocationSite(r2, r5);
if (construct_type == CallableType::kJSFunction) {
__ 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) {

View File

@ -1186,6 +1186,7 @@ void Builtins::Generate_InterpreterPushArgsAndCallImpl(
__ lsl(x3, x3, kPointerSizeLog2);
__ sub(x4, x2, x3);
// TODO(mythria): Add a stack check before pushing arguments.
// Push the arguments.
Label loop_header, loop_check;
__ Mov(x5, jssp);
@ -1213,12 +1214,14 @@ void Builtins::Generate_InterpreterPushArgsAndCallImpl(
}
// static
void Builtins::Generate_InterpreterPushArgsAndConstruct(MacroAssembler* masm) {
void Builtins::Generate_InterpreterPushArgsAndConstructImpl(
MacroAssembler* masm, CallableType construct_type) {
// ----------- S t a t e -------------
// -- x0 : argument count (not including receiver)
// -- x3 : new target
// -- x1 : constructor to call
// -- x2 : address of the first argument
// -- x2 : allocation site feedback if available, undefined otherwise
// -- x4 : address of the first argument
// -----------------------------------
// Find the address of the last argument.
@ -1228,24 +1231,38 @@ void Builtins::Generate_InterpreterPushArgsAndConstruct(MacroAssembler* masm) {
// Set stack pointer and where to stop.
__ Mov(x6, jssp);
__ Claim(x5, 1);
__ sub(x4, x6, x5);
__ sub(x7, x6, x5);
// Push a slot for the receiver.
__ Str(xzr, MemOperand(x6, -kPointerSize, PreIndex));
Label loop_header, loop_check;
// TODO(mythria): Add a stack check before pushing arguments.
// Push the arguments.
__ B(&loop_check);
__ Bind(&loop_header);
// TODO(rmcilroy): Push two at a time once we ensure we keep stack aligned.
__ Ldr(x5, MemOperand(x2, -kPointerSize, PostIndex));
__ Ldr(x5, MemOperand(x4, -kPointerSize, PostIndex));
__ Str(x5, MemOperand(x6, -kPointerSize, PreIndex));
__ Bind(&loop_check);
__ Cmp(x6, x4);
__ Cmp(x6, x7);
__ B(gt, &loop_header);
// Call the constructor with x0, x1, and x3 unmodified.
__ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET);
__ AssertUndefinedOrAllocationSite(x2, x6);
if (construct_type == CallableType::kJSFunction) {
__ 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) {

View File

@ -50,5 +50,27 @@ void Builtins::Generate_InterpreterPushArgsAndTailCallFunction(
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 v8

View File

@ -126,9 +126,10 @@ namespace internal {
ASM(InterpreterMarkBaselineOnReturn) \
ASM(InterpreterPushArgsAndCall) \
ASM(InterpreterPushArgsAndCallFunction) \
ASM(InterpreterPushArgsAndConstruct) \
ASM(InterpreterPushArgsAndTailCall) \
ASM(InterpreterPushArgsAndTailCallFunction) \
ASM(InterpreterPushArgsAndConstruct) \
ASM(InterpreterPushArgsAndConstructFunction) \
ASM(InterpreterEnterBytecodeDispatch) \
ASM(InterpreterOnStackReplacement) \
\
@ -581,6 +582,7 @@ class Builtins {
Handle<Code> InterpreterPushArgsAndCall(
TailCallMode tail_call_mode,
CallableType function_type = CallableType::kAny);
Handle<Code> InterpreterPushArgsAndConstruct(CallableType function_type);
Code* builtin(Name name) {
// Code::cast cannot be used here since we access builtins
@ -625,6 +627,9 @@ class Builtins {
MacroAssembler* masm, TailCallMode tail_call_mode,
CallableType function_type);
static void Generate_InterpreterPushArgsAndConstructImpl(
MacroAssembler* masm, CallableType function_type);
static void Generate_DatePrototype_GetField(MacroAssembler* masm,
int field_index);

View File

@ -702,19 +702,20 @@ void Builtins::Generate_InterpreterMarkBaselineOnReturn(MacroAssembler* masm) {
}
static void Generate_InterpreterPushArgs(MacroAssembler* masm,
Register array_limit) {
Register array_limit,
Register start_address) {
// ----------- S t a t e -------------
// -- ebx : Pointer to the last argument in the args array.
// -- start_address : Pointer to the last argument in the args array.
// -- array_limit : Pointer to one before the first argument in the
// args array.
// -----------------------------------
Label loop_header, loop_check;
__ jmp(&loop_check);
__ bind(&loop_header);
__ Push(Operand(ebx, 0));
__ sub(ebx, Immediate(kPointerSize));
__ Push(Operand(start_address, 0));
__ sub(start_address, Immediate(kPointerSize));
__ bind(&loop_check);
__ cmp(ebx, array_limit);
__ cmp(start_address, array_limit);
__ j(greater, &loop_header, Label::kNear);
}
@ -740,7 +741,8 @@ void Builtins::Generate_InterpreterPushArgsAndCallImpl(
__ neg(ecx);
__ add(ecx, ebx);
Generate_InterpreterPushArgs(masm, ecx);
// TODO(mythria): Add a stack check before pushing the arguments.
Generate_InterpreterPushArgs(masm, ecx, ebx);
// Call the target.
__ Push(edx); // Re-push return address.
@ -758,40 +760,115 @@ void Builtins::Generate_InterpreterPushArgsAndCallImpl(
}
// static
void Builtins::Generate_InterpreterPushArgsAndConstruct(MacroAssembler* masm) {
void Builtins::Generate_InterpreterPushArgsAndConstructImpl(
MacroAssembler* masm, CallableType construct_type) {
// ----------- S t a t e -------------
// -- eax : the number of arguments (not including the receiver)
// -- edx : the new target
// -- edi : the constructor
// -- ebx : the address of the first argument to be pushed. Subsequent
// -- ebx : allocation site feedback (if available or undefined)
// -- ecx : the address of the first argument to be pushed. Subsequent
// arguments should be consecutive above this, in the same order as
// they are to be pushed onto the stack.
// -----------------------------------
// Pop return address to allow tail-call after pushing arguments.
__ Pop(ecx);
// Push edi in the slot meant for receiver. We need an extra register
// so store edi temporarily on stack.
// Store edi, edx onto the stack. We need two extra registers
// so store edi, edx temporarily on stack.
__ Push(edi);
__ Push(edx);
// Find the address of the last argument.
__ mov(edi, eax);
__ neg(edi);
__ shl(edi, kPointerSizeLog2);
__ add(edi, ebx);
// We have to pop return address and the two temporary registers before we
// can push arguments onto the stack. we do not have any free registers so
// update the stack and copy them into the correct places on the stack.
// current stack =====> required stack layout
// | | | edx | (2) <-- esp(1)
// | | | edi | (3)
// | | | return addr | (4)
// | | | arg N | (5)
// | edx | <-- esp | .... |
// | edi | | arg 0 |
// | return addr | | receiver slot |
Generate_InterpreterPushArgs(masm, edi);
// 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));
// Restore the constructor from slot on stack. It was pushed at the slot
// meant for receiver.
__ mov(edi, Operand(esp, eax, times_pointer_size, 0));
#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
// Re-push return address.
__ Push(ecx);
// TODO(mythria): Add a stack check before updating the stack pointer.
// Call the constructor with unmodified eax, edi, ebi values.
__ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET);
// 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;
__ 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.
__ Pop(edx);
__ Pop(edi);
__ 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.
__ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET);
}
}
void Builtins::Generate_InterpreterEnterBytecodeDispatch(MacroAssembler* masm) {

View File

@ -1198,17 +1198,19 @@ void Builtins::Generate_InterpreterPushArgsAndCallImpl(
}
// static
void Builtins::Generate_InterpreterPushArgsAndConstruct(MacroAssembler* masm) {
void Builtins::Generate_InterpreterPushArgsAndConstructImpl(
MacroAssembler* masm, CallableType construct_type) {
// ----------- S t a t e -------------
// -- a0 : argument count (not including receiver)
// -- a3 : new target
// -- a1 : constructor to call
// -- a2 : address of the first argument
// -- a2 : allocation site feedback if available, undefined otherwise.
// -- t4 : address of the first argument
// -----------------------------------
// Find the address of the last argument.
__ sll(t0, a0, kPointerSizeLog2);
__ Subu(t0, a2, Operand(t0));
__ Subu(t0, t4, Operand(t0));
// Push a slot for the receiver.
__ push(zero_reg);
@ -1217,14 +1219,27 @@ void Builtins::Generate_InterpreterPushArgsAndConstruct(MacroAssembler* masm) {
Label loop_header, loop_check;
__ Branch(&loop_check);
__ bind(&loop_header);
__ lw(t1, MemOperand(a2));
__ Addu(a2, a2, Operand(-kPointerSize));
__ lw(t1, MemOperand(t4));
__ Addu(t4, t4, Operand(-kPointerSize));
__ push(t1);
__ bind(&loop_check);
__ Branch(&loop_header, gt, a2, Operand(t0));
__ Branch(&loop_header, gt, t4, Operand(t0));
// Call the constructor with a0, a1, and a3 unmodified.
__ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET);
__ AssertUndefinedOrAllocationSite(a2, t0);
if (construct_type == CallableType::kJSFunction) {
__ 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) {

View File

@ -1190,17 +1190,19 @@ void Builtins::Generate_InterpreterPushArgsAndCallImpl(
}
// static
void Builtins::Generate_InterpreterPushArgsAndConstruct(MacroAssembler* masm) {
void Builtins::Generate_InterpreterPushArgsAndConstructImpl(
MacroAssembler* masm, CallableType construct_type) {
// ----------- S t a t e -------------
// -- a0 : argument count (not including receiver)
// -- a3 : new target
// -- a1 : constructor to call
// -- a2 : address of the first argument
// -- a2 : allocation site feedback if available, undefined otherwise.
// -- a4 : address of the first argument
// -----------------------------------
// Find the address of the last argument.
__ dsll(t0, a0, kPointerSizeLog2);
__ Dsubu(t0, a2, Operand(t0));
__ Dsubu(t0, a4, Operand(t0));
// Push a slot for the receiver.
__ push(zero_reg);
@ -1209,14 +1211,27 @@ void Builtins::Generate_InterpreterPushArgsAndConstruct(MacroAssembler* masm) {
Label loop_header, loop_check;
__ Branch(&loop_check);
__ bind(&loop_header);
__ ld(t1, MemOperand(a2));
__ Daddu(a2, a2, Operand(-kPointerSize));
__ ld(t1, MemOperand(a4));
__ Daddu(a4, a4, Operand(-kPointerSize));
__ push(t1);
__ bind(&loop_check);
__ Branch(&loop_header, gt, a2, Operand(t0));
__ Branch(&loop_header, gt, a4, Operand(t0));
// Call the constructor with a0, a1, and a3 unmodified.
__ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET);
__ AssertUndefinedOrAllocationSite(a2, t0);
if (construct_type == CallableType::kJSFunction) {
__ 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) {

View File

@ -778,7 +778,9 @@ void Builtins::Generate_InterpreterMarkBaselineOnReturn(MacroAssembler* masm) {
}
static void Generate_InterpreterPushArgs(MacroAssembler* masm,
bool push_receiver) {
Register num_args,
Register start_address,
Register scratch, bool push_receiver) {
// ----------- S t a t e -------------
// -- rax : the number of arguments (not including the receiver)
// -- rbx : the address of the first argument to be pushed. Subsequent
@ -787,23 +789,23 @@ static void Generate_InterpreterPushArgs(MacroAssembler* masm,
// -----------------------------------
// Find the address of the last argument.
__ movp(rcx, rax);
__ movp(scratch, num_args);
if (push_receiver) {
__ addp(rcx, Immediate(1)); // Add one for receiver.
__ addp(scratch, Immediate(1)); // Add one for receiver.
}
__ shlp(rcx, Immediate(kPointerSizeLog2));
__ negp(rcx);
__ addp(rcx, rbx);
__ shlp(scratch, Immediate(kPointerSizeLog2));
__ negp(scratch);
__ addp(scratch, start_address);
// Push the arguments.
Label loop_header, loop_check;
__ j(always, &loop_check);
__ bind(&loop_header);
__ Push(Operand(rbx, 0));
__ subp(rbx, Immediate(kPointerSize));
__ Push(Operand(start_address, 0));
__ subp(start_address, Immediate(kPointerSize));
__ bind(&loop_check);
__ cmpp(rbx, rcx);
__ cmpp(start_address, scratch);
__ j(greater, &loop_header, Label::kNear);
}
@ -822,7 +824,9 @@ void Builtins::Generate_InterpreterPushArgsAndCallImpl(
// Pop return address to allow tail-call after pushing arguments.
__ PopReturnAddressTo(kScratchRegister);
Generate_InterpreterPushArgs(masm, true);
// TODO(mythria): Add a stack check before pushing arguments.
// rax is readonly rcx and r8 will be modified.
Generate_InterpreterPushArgs(masm, rax, rbx, rcx, true);
// Call the target.
__ PushReturnAddressFrom(kScratchRegister); // Re-push return address.
@ -840,13 +844,15 @@ void Builtins::Generate_InterpreterPushArgsAndCallImpl(
}
// static
void Builtins::Generate_InterpreterPushArgsAndConstruct(MacroAssembler* masm) {
void Builtins::Generate_InterpreterPushArgsAndConstructImpl(
MacroAssembler* masm, CallableType construct_type) {
// ----------- S t a t e -------------
// -- rax : the number of arguments (not including the receiver)
// -- rdx : the new target (either the same as the constructor or
// the JSFunction on which new was invoked initially)
// -- rdi : the constructor to call (can be any Object)
// -- rbx : the address of the first argument to be pushed. Subsequent
// -- rbx : the allocation site feedback if available, undefined otherwise
// -- rcx : the address of the first argument to be pushed. Subsequent
// arguments should be consecutive above this, in the same order as
// they are to be pushed onto the stack.
// -----------------------------------
@ -857,13 +863,29 @@ void Builtins::Generate_InterpreterPushArgsAndConstruct(MacroAssembler* masm) {
// Push slot for the receiver to be constructed.
__ Push(Immediate(0));
Generate_InterpreterPushArgs(masm, false);
// TODO(mythria): Add a stack check before pushing arguments.
// 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.
__ PushReturnAddressFrom(kScratchRegister);
// Call the constructor (rax, rdx, rdi passed on).
__ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET);
__ AssertUndefinedOrAllocationSite(rbx);
if (construct_type == CallableType::kJSFunction) {
// 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) {

View File

@ -576,9 +576,11 @@ Callable CodeFactory::InterpreterPushArgsAndCall(Isolate* isolate,
}
// static
Callable CodeFactory::InterpreterPushArgsAndConstruct(Isolate* isolate) {
return Callable(isolate->builtins()->InterpreterPushArgsAndConstruct(),
InterpreterPushArgsAndConstructDescriptor(isolate));
Callable CodeFactory::InterpreterPushArgsAndConstruct(
Isolate* isolate, CallableType function_type) {
return Callable(
isolate->builtins()->InterpreterPushArgsAndConstruct(function_type),
InterpreterPushArgsAndConstructDescriptor(isolate));
}
// static

View File

@ -156,7 +156,8 @@ class CodeFactory final {
static Callable InterpreterPushArgsAndCall(
Isolate* isolate, TailCallMode tail_call_mode,
CallableType function_type = CallableType::kAny);
static Callable InterpreterPushArgsAndConstruct(Isolate* isolate);
static Callable InterpreterPushArgsAndConstruct(
Isolate* isolate, CallableType function_type = CallableType::kAny);
static Callable InterpreterCEntry(Isolate* isolate, int result_size = 1);
static Callable InterpreterOnStackReplacement(Isolate* isolate);
};

View File

@ -1094,12 +1094,17 @@ void BytecodeGraphBuilder::VisitNew() {
interpreter::Register callee_reg = bytecode_iterator().GetRegisterOperand(0);
interpreter::Register first_arg = bytecode_iterator().GetRegisterOperand(1);
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* callee = environment()->LookupRegister(callee_reg);
// TODO(turbofan): Pass the feedback here.
const Operator* call = javascript()->CallConstruct(
static_cast<int>(arg_count) + 2, VectorSlotPair());
const Operator* call =
javascript()->CallConstruct(static_cast<int>(arg_count) + 2, feedback);
Node* value = ProcessCallNewArguments(call, callee, new_target, first_arg,
arg_count + 2);
environment()->BindAccumulator(value, &states);

View File

@ -389,7 +389,8 @@ void InterpreterPushArgsAndConstructDescriptor::InitializePlatformSpecific(
eax, // argument count (not including receiver)
edx, // new target
edi, // constructor
ebx, // address of first argument
ebx, // allocation site feedback
ecx, // address of first argument
};
data->InitializePlatformSpecific(arraysize(registers), registers);
}

View File

@ -588,13 +588,15 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::Call(Register callable,
BytecodeArrayBuilder& BytecodeArrayBuilder::New(Register constructor,
Register first_arg,
size_t arg_count) {
size_t arg_count,
int feedback_slot_id) {
if (!first_arg.is_valid()) {
DCHECK_EQ(0u, arg_count);
first_arg = Register(0);
}
Output(Bytecode::kNew, RegisterOperand(constructor),
RegisterOperand(first_arg), UnsignedOperand(arg_count));
RegisterOperand(first_arg), UnsignedOperand(arg_count),
UnsignedOperand(feedback_slot_id));
return *this;
}

View File

@ -176,7 +176,7 @@ class BytecodeArrayBuilder final : public ZoneObject {
// consecutive arguments starting at |first_arg| for the constuctor
// invocation.
BytecodeArrayBuilder& New(Register constructor, Register first_arg,
size_t arg_count);
size_t arg_count, int feedback_slot);
// Call the runtime function with |function_id|. The first argument should be
// in |first_arg| and all subsequent arguments should be in registers

View File

@ -2619,7 +2619,7 @@ void BytecodeGenerator::VisitCall(Call* expr) {
if (expr->CallFeedbackICSlot().IsInvalid()) {
DCHECK(call_type == Call::POSSIBLY_EVAL_CALL);
// Valid type feedback slots can only be greater than kReservedIndexCount.
// We use 0 to indicate an invalid slot it. Statically assert that 0 cannot
// We use 0 to indicate an invalid slot id. Statically assert that 0 cannot
// be a valid slot id.
STATIC_ASSERT(TypeFeedbackVector::kReservedIndexCount > 0);
feedback_slot_index = 0;
@ -2654,7 +2654,13 @@ void BytecodeGenerator::VisitCallSuper(Call* expr) {
// Call construct.
builder()->SetExpressionPosition(expr);
builder()->New(constructor, first_arg, args->length());
// Valid type feedback slots can only be greater than kReservedIndexCount.
// 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();
}
@ -2671,7 +2677,8 @@ void BytecodeGenerator::VisitCallNew(CallNew* expr) {
// constructor for CallNew.
builder()
->LoadAccumulatorWithRegister(constructor)
.New(constructor, first_arg, args->length());
.New(constructor, first_arg, args->length(),
feedback_index(expr->CallNewFeedbackSlot()));
execution_result()->SetResultInAccumulator();
}

View File

@ -197,7 +197,7 @@ namespace interpreter {
\
/* New operator */ \
V(New, AccumulatorUse::kReadWrite, OperandType::kReg, \
OperandType::kMaybeReg, OperandType::kRegCount) \
OperandType::kMaybeReg, OperandType::kRegCount, OperandType::kIdx) \
\
/* Test Operators */ \
V(TestEqual, AccumulatorUse::kReadWrite, OperandType::kReg) \

View File

@ -489,7 +489,7 @@ Node* InterpreterAssembler::CallJSWithFeedback(Node* function, Node* context,
Node* is_feedback_unavailable = Word32Equal(slot_id, Int32Constant(0));
GotoIf(is_feedback_unavailable, &call);
// The checks. First, does rdi match the recorded monomorphic target?
// The checks. First, does function match the recorded monomorphic target?
Node* feedback_element = LoadFixedArrayElement(type_feedback_vector, slot_id);
Node* feedback_value = LoadWeakCellValue(feedback_element);
Node* is_monomorphic = WordEqual(function, feedback_value);
@ -623,11 +623,202 @@ Node* InterpreterAssembler::CallJS(Node* function, Node* context,
Node* InterpreterAssembler::CallConstruct(Node* constructor, Node* context,
Node* new_target, Node* first_arg,
Node* arg_count) {
Callable callable = CodeFactory::InterpreterPushArgsAndConstruct(isolate());
Node* code_target = HeapConstant(callable.code());
return CallStub(callable.descriptor(), code_target, context, arg_count,
new_target, constructor, first_arg);
Node* arg_count, Node* slot_id,
Node* type_feedback_vector) {
Label call_construct(this), js_function(this), end(this);
Variable return_value(this, MachineRepresentation::kTagged);
Variable allocation_feedback(this, MachineRepresentation::kTagged);
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,

View File

@ -120,7 +120,9 @@ class InterpreterAssembler : public CodeStubAssembler {
compiler::Node* context,
compiler::Node* new_target,
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
// located at |first_arg|.

View File

@ -1305,9 +1305,11 @@ void Interpreter::DoCallConstruct(InterpreterAssembler* assembler) {
Node* first_arg_reg = __ BytecodeOperandReg(1);
Node* first_arg = __ RegisterLocation(first_arg_reg);
Node* args_count = __ BytecodeOperandCount(2);
Node* slot_id = __ BytecodeOperandIdx(3);
Node* type_feedback_vector = __ LoadTypeFeedbackVector();
Node* context = __ GetContext();
Node* result =
__ CallConstruct(constructor, context, new_target, first_arg, args_count);
Node* result = __ CallConstruct(constructor, context, new_target, first_arg,
args_count, slot_id, type_feedback_vector);
__ SetAccumulator(result);
__ Dispatch();
}

View File

@ -381,7 +381,8 @@ void InterpreterPushArgsAndConstructDescriptor::InitializePlatformSpecific(
a0, // argument count (not including receiver)
a3, // new target
a1, // constructor to call
a2 // address of the first argument
a2, // allocation site feedback if available, undefined otherwise.
t4 // address of the first argument
};
data->InitializePlatformSpecific(arraysize(registers), registers);
}

View File

@ -380,7 +380,8 @@ void InterpreterPushArgsAndConstructDescriptor::InitializePlatformSpecific(
a0, // argument count (not including receiver)
a3, // new target
a1, // constructor to call
a2 // address of the first argument
a2, // allocation site feedback if available, undefined otherwise.
a4 // address of the first argument
};
data->InitializePlatformSpecific(arraysize(registers), registers);
}

View File

@ -380,7 +380,8 @@ void InterpreterPushArgsAndConstructDescriptor::InitializePlatformSpecific(
rax, // argument count (not including receiver)
rdx, // new target
rdi, // constructor
rbx, // address of first argument
rbx, // allocation site feedback if available, undefined otherwise
rcx, // address of first argument
};
data->InitializePlatformSpecific(arraysize(registers), registers);
}

View File

@ -130,12 +130,6 @@
# TODO(mythria,4780): Related to type feedback support for Array function.
'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.
'test-heap/Regress169209': [PASS, NO_IGNITION],
@ -150,8 +144,8 @@
# BUG(4680): Missing type feedback makes optimistic optimizations fail.
'test-cpu-profiler/DeoptUntrackedFunction': [PASS, NO_IGNITION],
# BUG(4680): Ignition doesn't support allocation sites currently.
'test-heap/EnsureAllocationSiteDependentCodesProcessed': [PASS, NO_IGNITION],
# TODO(mythria, 4780): In interpreter we disable mementos when creating array
# literals.
'test-heap/OptimizedPretenuringAllocationFolding': [PASS, NO_IGNITION],
'test-heap/OptimizedPretenuringdoubleArrayLiterals': [PASS, NO_IGNITION],
'test-heap/OptimizedPretenuringNestedDoubleLiterals': [PASS, NO_IGNITION],
@ -429,12 +423,6 @@
# TODO(mythria,4780): Related to type feedback support for Array function.
'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.
'test-heap/Regress169209': [FAIL],
@ -446,8 +434,8 @@
'test-cpu-profiler/CollectDeoptEvents': [FAIL],
'test-cpu-profiler/DeoptUntrackedFunction': [FAIL],
# BUG(4680): Ignition doesn't support allocation sites currently.
'test-heap/EnsureAllocationSiteDependentCodesProcessed': [FAIL],
# TODO(mythria, 4780): In interpreter we disable mementos when creating array
# literals.
'test-heap/OptimizedPretenuringAllocationFolding': [FAIL],
'test-heap/OptimizedPretenuringdoubleArrayLiterals': [FAIL],
'test-heap/OptimizedPretenuringNestedDoubleLiterals': [FAIL],

View File

@ -16,12 +16,12 @@ snippet: "
"
frame size: 1
parameter count: 1
bytecode array length: 11
bytecode array length: 12
bytecodes: [
/* 45 E> */ B(StackCheck),
/* 50 S> */ B(LdrGlobal), U8(3), R(0),
B(Ldar), R(0),
/* 57 E> */ B(New), R(0), R(0), U8(0),
/* 57 E> */ B(New), R(0), R(0), U8(0), U8(1),
/* 68 S> */ B(Return),
]
constant pool: [
@ -37,14 +37,14 @@ snippet: "
"
frame size: 2
parameter count: 1
bytecode array length: 15
bytecode array length: 16
bytecodes: [
/* 58 E> */ B(StackCheck),
/* 63 S> */ B(LdrGlobal), U8(3), R(0),
B(LdaSmi), U8(3),
B(Star), R(1),
B(Ldar), R(0),
/* 70 E> */ B(New), R(0), R(1), U8(1),
/* 70 E> */ B(New), R(0), R(1), U8(1), U8(1),
/* 82 S> */ B(Return),
]
constant pool: [
@ -65,7 +65,7 @@ snippet: "
"
frame size: 4
parameter count: 1
bytecode array length: 23
bytecode array length: 24
bytecodes: [
/* 100 E> */ B(StackCheck),
/* 105 S> */ B(LdrGlobal), U8(3), R(0),
@ -76,7 +76,7 @@ bytecodes: [
B(LdaSmi), U8(5),
B(Star), R(3),
B(Ldar), R(0),
/* 112 E> */ B(New), R(0), R(1), U8(3),
/* 112 E> */ B(New), R(0), R(1), U8(3), U8(1),
/* 130 S> */ B(Return),
]
constant pool: [

View File

@ -127,7 +127,7 @@ snippet: "
"
frame size: 5
parameter count: 1
bytecode array length: 105
bytecode array length: 106
bytecodes: [
B(Mov), R(closure), R(1),
B(Mov), R(new_target), R(0),
@ -147,7 +147,7 @@ bytecodes: [
B(LdaConstant), U8(1),
B(Star), R(4),
/* 118 E> */ B(CallRuntime), U16(Runtime::kThrowReferenceError), R(4), U8(1),
/* 118 E> */ B(New), R(2), R(3), U8(1),
/* 118 E> */ B(New), R(2), R(3), U8(1), U8(0),
B(Star), R(2),
B(Ldar), R(this),
B(JumpIfNotHole), U8(4),
@ -195,7 +195,7 @@ snippet: "
"
frame size: 4
parameter count: 1
bytecode array length: 101
bytecode array length: 102
bytecodes: [
B(Mov), R(closure), R(1),
B(Mov), R(new_target), R(0),
@ -213,7 +213,7 @@ bytecodes: [
B(LdaConstant), U8(1),
B(Star), R(3),
/* 117 E> */ B(CallRuntime), U16(Runtime::kThrowReferenceError), R(3), U8(1),
/* 117 E> */ B(New), R(2), R(0), U8(0),
/* 117 E> */ B(New), R(2), R(0), U8(0), U8(0),
B(Star), R(2),
B(Ldar), R(this),
B(JumpIfNotHole), U8(4),

View File

@ -196,7 +196,7 @@ snippet: "
"
frame size: 8
parameter count: 1
bytecode array length: 72
bytecode array length: 73
bytecodes: [
B(CreateFunctionContext), U8(1),
B(PushContext), R(3),
@ -227,7 +227,7 @@ bytecodes: [
B(Star), R(5),
B(CallRuntime), U16(Runtime::kThrowReferenceError), R(5), U8(1),
B(Star), R(4),
/* 94 E> */ B(New), R(4), R(0), U8(0),
/* 94 E> */ B(New), R(4), R(0), U8(0), U8(3),
/* 103 S> */ B(Return),
]
constant pool: [

View File

@ -223,10 +223,13 @@
############################################################################
# Ignition
# TODO(mythria, 4780): Related to type feedback for calls in interpreter.
'array-literal-feedback': [PASS, NO_IGNITION],
# TODO(mythria, 4780): Related to lack of allocation site feedback for calls.
'regress/regress-4121': [PASS, NO_IGNITION],
# TODO(mythria, 4780): In interpreter we disable mementos when creating array
# literals.
'array-literal-feedback': [PASS, NO_IGNITION],
# TODO(4680): Test doesn't know about three tier compiler pipeline.
'assert-opt-and-deopt': [PASS, NO_IGNITION],
@ -261,7 +264,6 @@
'smi-mul-const': [PASS, NO_IGNITION],
'smi-mul': [PASS, NO_IGNITION],
'unary-minus-deopt': [PASS, NO_IGNITION],
'array-constructor-feedback': [PASS, NO_IGNITION],
'array-feedback': [PASS, NO_IGNITION],
'allocation-site-info': [PASS, NO_IGNITION],
@ -702,11 +704,14 @@
##############################################################################
['variant == ignition_turbofan', {
# TODO(mythria, 4780): Related to type feedback for calls in interpreter.
'array-literal-feedback': [FAIL],
# TODO(mythria, 4780): Related to lack of allocation site feedback for calls
# in interpreter.
'regress/regress-4121': [FAIL],
'array-constructor-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],
'wasm/asm-wasm-f32': [PASS, ['arch in [arm64]', SKIP]],

View File

@ -165,8 +165,8 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
builder.Delete(reg, LanguageMode::SLOPPY).Delete(reg, LanguageMode::STRICT);
// Emit new.
builder.New(reg, reg, 0);
builder.New(wide, wide, 0);
builder.New(reg, reg, 0, 1);
builder.New(wide, wide, 0, 1);
// Emit test operator invocations.
builder.CompareOperation(Token::Value::EQ, reg)
@ -456,7 +456,7 @@ TEST_F(BytecodeArrayBuilderTest, FrameSizesLookGood) {
// Ensure temporaries are used so not optimized away by the
// register optimizer.
builder.New(Register(locals + contexts), Register(locals + contexts),
static_cast<size_t>(temps));
static_cast<size_t>(temps), 0);
}
builder.Return();