Commit b913e2a9 authored by chunyang.dai's avatar chunyang.dai Committed by Commit bot

X87: [es6] Make new.target work in functions.

port 7a63bf77 (r29358).

original commit message:

    This makes new.target work in [[Call]] and [[Construct]] of ordinary
    functions.

    We achieve this by introducing a new construct stub for functions that
    uses the new.target variable. The construct stub pushes the original
    constructor just above the receiver in the construct frame.

BUG=

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

Cr-Commit-Position: refs/heads/master@{#29413}
parent fb1329aa
......@@ -138,6 +138,7 @@ static void Generate_Runtime_NewObject(MacroAssembler* masm,
static void Generate_JSConstructStubHelper(MacroAssembler* masm,
bool is_api_function,
bool use_new_target,
bool create_memento) {
// ----------- S t a t e -------------
// -- eax: number of arguments
......@@ -158,12 +159,13 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
__ push(ebx);
}
// Store a smi-tagged arguments count on the stack.
// Preserve the incoming parameters on the stack.
__ SmiTag(eax);
__ push(eax);
// Push the function to invoke on the stack.
__ push(edi);
if (use_new_target) {
__ push(edx);
}
__ cmp(edx, edi);
Label normal_new;
......@@ -391,7 +393,8 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
__ bind(&allocated);
if (create_memento) {
__ mov(ecx, Operand(esp, kPointerSize * 2));
int offset = (use_new_target ? 3 : 2) * kPointerSize;
__ mov(ecx, Operand(esp, offset));
__ cmp(ecx, masm->isolate()->factory()->undefined_value());
__ j(equal, &count_incremented);
// ecx is an AllocationSite. We are creating a memento from it, so we
......@@ -401,13 +404,22 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
__ bind(&count_incremented);
}
// Retrieve the function from the stack.
__ pop(edi);
// Restore the parameters.
if (use_new_target) {
__ pop(edx); // new.target
}
__ pop(edi); // Constructor function.
// Retrieve smi-tagged arguments count from the stack.
__ mov(eax, Operand(esp, 0));
__ SmiUntag(eax);
// Push new.target onto the construct frame. This is stored just below the
// receiver on the stack.
if (use_new_target) {
__ push(edx);
}
// Push the allocated receiver to the stack. We need two copies
// because we may have to return the original one and the calling
// conventions dictate that the called function pops the receiver.
......@@ -440,7 +452,9 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
}
// Store offset of return address for deoptimizer.
if (!is_api_function) {
// TODO(arv): Remove the "!use_new_target" before supporting optimization
// of functions that reference new.target
if (!is_api_function && !use_new_target) {
masm->isolate()->heap()->SetConstructStubDeoptPCOffset(masm->pc_offset());
}
......@@ -465,9 +479,11 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
__ bind(&use_receiver);
__ mov(eax, Operand(esp, 0));
// Restore the arguments count and leave the construct frame.
// Restore the arguments count and leave the construct frame. The arguments
// count is stored below the reciever and the new.target.
__ bind(&exit);
__ mov(ebx, Operand(esp, kPointerSize)); // Get arguments count.
int offset = (use_new_target ? 2 : 1) * kPointerSize;
__ mov(ebx, Operand(esp, offset));
// Leave construct frame.
}
......@@ -483,12 +499,17 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
Generate_JSConstructStubHelper(masm, false, FLAG_pretenuring_call_new);
Generate_JSConstructStubHelper(masm, false, false, FLAG_pretenuring_call_new);
}
void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) {
Generate_JSConstructStubHelper(masm, true, false);
Generate_JSConstructStubHelper(masm, true, false, false);
}
void Builtins::Generate_JSConstructStubNewTarget(MacroAssembler* masm) {
Generate_JSConstructStubHelper(masm, false, true, FLAG_pretenuring_call_new);
}
......
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