Commit 1d2574af authored by zhengxing.li's avatar zhengxing.li Committed by Commit bot

X87: [Interpreter] Collect allocation site feedback in call bytecode handler.

  port 9a31162d(r39283)

  original commit message:
  Adds support to collect allocation site feedback for Array function calls
  to the call bytecode handler.

BUG=

Review-Url: https://codereview.chromium.org/2319123004
Cr-Commit-Position: refs/heads/master@{#39299}
parent 05652917
......@@ -762,42 +762,38 @@ void Builtins::Generate_InterpreterPushArgsAndCallImpl(
}
}
// static
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 : 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.
// -----------------------------------
namespace {
// Store edi, edx onto the stack. We need two extra registers
// so store edi, edx temporarily on stack.
__ Push(edi);
__ Push(edx);
// This function modified start_addr, and only reads the contents of num_args
// register. scratch1 and scratch2 are used as temporary registers. Their
// original values are restored after the use.
void Generate_InterpreterPushArgsAndReturnAddress(
MacroAssembler* masm, Register num_args, Register start_addr,
Register scratch1, Register scratch2, bool receiver_in_args) {
// Store scratch2, scratch1 onto the stack. We need to restore the original
// values
// so store scratch2, scratch1 temporarily on stack.
__ Push(scratch2);
__ Push(scratch1);
// 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)
// | | | scratch1 | (2) <-- esp(1)
// | | | scratch2 | (3)
// | | | return addr | (4)
// | | | arg N | (5)
// | edx | <-- esp | .... |
// | edi | | arg 0 |
// | scratch1 | <-- esp | .... |
// | scratch2 | | 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));
__ mov(scratch1, num_args);
__ shl(scratch1, kPointerSizeLog2);
__ add(scratch1, Immediate(kPointerSize));
#ifdef _MSC_VER
// TODO(mythria): Move it to macro assembler.
......@@ -808,12 +804,12 @@ void Builtins::Generate_InterpreterPushArgsAndConstructImpl(
const int page_size = 4 * 1024;
Label check_offset, update_stack_pointer;
__ bind(&check_offset);
__ cmp(edx, page_size);
__ cmp(scratch1, 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));
__ sub(scratch1, Immediate(page_size));
__ jmp(&check_offset);
__ bind(&update_stack_pointer);
#endif
......@@ -821,44 +817,74 @@ void Builtins::Generate_InterpreterPushArgsAndConstructImpl(
// TODO(mythria): Add a stack check before updating the stack pointer.
// Step 1 - Update the stack pointer.
__ sub(esp, edx);
__ sub(esp, scratch1);
// 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
// Step 2 move scratch1 to the correct location. Move scratch1 first otherwise
// we may overwrite when num_args = 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);
__ mov(scratch1,
Operand(esp, num_args, times_pointer_size, 1 * kPointerSize));
__ mov(Operand(esp, 0), scratch1);
// 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 3 move scratch2 to the correct location
__ mov(scratch1,
Operand(esp, num_args, times_pointer_size, 2 * kPointerSize));
__ mov(Operand(esp, 1 * kPointerSize), scratch1);
// 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);
// Slot meant for receiver contains return address. Reset it so that
// we will not incorrectly interpret return address as an object.
__ mov(Operand(esp, eax, times_pointer_size, 3 * kPointerSize), Immediate(0));
__ mov(scratch1,
Operand(esp, num_args, times_pointer_size, 3 * kPointerSize));
__ mov(Operand(esp, 2 * kPointerSize), scratch1);
// Step 5 copy arguments to correct locations.
__ mov(edx, eax);
if (receiver_in_args) {
__ mov(scratch1, num_args);
__ add(scratch1, Immediate(1));
} else {
// Slot meant for receiver contains return address. Reset it so that
// we will not incorrectly interpret return address as an object.
__ mov(Operand(esp, num_args, times_pointer_size, 3 * kPointerSize),
Immediate(0));
__ mov(scratch1, num_args);
}
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));
__ mov(scratch2, Operand(start_addr, 0));
__ mov(Operand(esp, scratch1, times_pointer_size, 2 * kPointerSize),
scratch2);
__ sub(start_addr, Immediate(kPointerSize));
__ sub(scratch1, Immediate(1));
__ bind(&loop_check);
__ cmp(edx, Immediate(0));
__ cmp(scratch1, Immediate(0));
__ j(greater, &loop_header, Label::kNear);
// Restore edi and edx.
__ Pop(edx);
__ Pop(edi);
// Restore scratch1 and scratch2.
__ Pop(scratch1);
__ Pop(scratch2);
}
} // end anonymous namespace
// static
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 : 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.
// -----------------------------------
// Push arguments and move return address to the top of stack.
// The eax register is readonly. The ecx register will be modified. The edx
// and edi registers will be modified but restored to their original values.
Generate_InterpreterPushArgsAndReturnAddress(masm, eax, ecx, edx, edi, false);
__ AssertUndefinedOrAllocationSite(ebx);
if (construct_type == CallableType::kJSFunction) {
......@@ -878,6 +904,30 @@ void Builtins::Generate_InterpreterPushArgsAndConstructImpl(
}
}
// static
void Builtins::Generate_InterpreterPushArgsAndConstructArray(
MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- eax : the number of arguments (not including the receiver)
// -- edx : the target to call checked to be Array function.
// -- ebx : the allocation site feedback
// -- 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.
// -----------------------------------
// Push arguments and move return address to the top of stack.
// The eax register is readonly. The ecx register will be modified. The edx
// and edi registers will be modified but restored to their original values.
Generate_InterpreterPushArgsAndReturnAddress(masm, eax, ecx, edx, ebx, true);
// Array constructor expects constructor in edi. It is same as edx here.
__ Move(edi, edx);
ArrayConstructorStub stub(masm->isolate());
__ TailCallStub(&stub);
}
void Builtins::Generate_InterpreterEnterBytecodeDispatch(MacroAssembler* masm) {
// Set the return address to the correct point in the interpreter entry
// trampoline.
......
......@@ -404,6 +404,17 @@ void InterpreterPushArgsAndConstructDescriptor::InitializePlatformSpecific(
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void InterpreterPushArgsAndConstructArrayDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {
eax, // argument count (not including receiver)
edx, // target to the call. It is checked to be Array function.
ebx, // allocation site feedback
ecx, // address of first argument
};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void InterpreterCEntryDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {
......
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