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

X87: Switch CallConstructStub to take new.target in register.

original commit message:

    This changes the calling convention of the CallConstructStub to take
    the original constructor (i.e. new.target in JS-speak) in a register
    instead of magically via the operand stack. For optimizing compilers
    the operand stack doesn't exist, hence cannot be peeked into.

BUG=

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

Cr-Commit-Position: refs/heads/master@{#29695}
parent 1d921650
......@@ -1172,8 +1172,7 @@ static void Generate_ConstructHelper(MacroAssembler* masm) {
const int kIndexOffset = kLimitOffset - 1 * kPointerSize;
__ Push(eax); // limit
__ push(Immediate(0)); // index
// Push newTarget and callee functions
__ push(Operand(ebp, kNewTargetOffset));
// Push the constructor function as callee.
__ push(Operand(ebp, kFunctionOffset));
// Loop over the arguments array, pushing each value to the stack
......@@ -1183,13 +1182,12 @@ static void Generate_ConstructHelper(MacroAssembler* masm) {
// Use undefined feedback vector
__ LoadRoot(ebx, Heap::kUndefinedValueRootIndex);
__ mov(edi, Operand(ebp, kFunctionOffset));
__ mov(ecx, Operand(ebp, kNewTargetOffset));
// Call the function.
CallConstructStub stub(masm->isolate(), SUPER_CONSTRUCTOR_CALL);
__ call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL);
__ Drop(1);
// Leave internal frame.
}
// remove this, target, arguments, and newTarget
......
......@@ -1834,11 +1834,15 @@ void CallFunctionStub::Generate(MacroAssembler* masm) {
void CallConstructStub::Generate(MacroAssembler* masm) {
// eax : number of arguments
// ebx : feedback vector
// edx : (only if ebx is not the megamorphic symbol) slot in feedback
// vector (Smi)
// ecx : original constructor (for IsSuperConstructorCall)
// edx : slot in feedback vector (Smi, for RecordCallTarget)
// edi : constructor function
Label slow, non_function_call;
if (IsSuperConstructorCall()) {
__ push(ecx);
}
// Check that function is not a smi.
__ JumpIfSmi(edi, &non_function_call);
// Check that function is a JSFunction.
......@@ -1871,7 +1875,7 @@ void CallConstructStub::Generate(MacroAssembler* masm) {
}
if (IsSuperConstructorCall()) {
__ mov(edx, Operand(esp, eax, times_pointer_size, 2 * kPointerSize));
__ pop(edx);
} else {
// Pass original constructor to construct stub.
__ mov(edx, edi);
......@@ -1888,6 +1892,7 @@ void CallConstructStub::Generate(MacroAssembler* masm) {
// edi: called object
// eax: number of arguments
// ecx: object map
// esp[0]: original receiver
Label do_call;
__ bind(&slow);
__ CmpInstanceType(ecx, JS_FUNCTION_PROXY_TYPE);
......@@ -1898,6 +1903,9 @@ void CallConstructStub::Generate(MacroAssembler* masm) {
__ bind(&non_function_call);
__ GetBuiltinEntry(edx, Builtins::CALL_NON_FUNCTION_AS_CONSTRUCTOR);
__ bind(&do_call);
if (IsSuperConstructorCall()) {
__ Drop(1);
}
// Set expected number of arguments to zero (not changing eax).
__ Move(ebx, Immediate(0));
Handle<Code> arguments_adaptor =
......
......@@ -3250,9 +3250,6 @@ void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) {
expr->expression()->AsSuperCallReference();
DCHECK_NOT_NULL(super_call_ref);
VariableProxy* new_target_proxy = super_call_ref->new_target_var();
VisitForStackValue(new_target_proxy);
EmitLoadSuperConstructor(super_call_ref);
__ push(result_register());
......@@ -3267,6 +3264,10 @@ void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) {
// constructor invocation.
SetConstructCallPosition(expr);
// Load original constructor into ecx.
VisitForAccumulatorValue(super_call_ref->new_target_var());
__ mov(ecx, result_register());
// Load function and argument count into edi and eax.
__ Move(eax, Immediate(arg_count));
__ mov(edi, Operand(esp, arg_count * kPointerSize));
......@@ -3287,8 +3288,6 @@ void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) {
CallConstructStub stub(isolate(), SUPER_CALL_RECORD_TARGET);
__ call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL);
__ Drop(1);
RecordJSReturnSite(expr);
EmitInitializeThisAfterSuper(super_call_ref, expr->CallFeedbackICSlot());
......@@ -4213,11 +4212,14 @@ void FullCodeGenerator::EmitDefaultConstructorCallSuper(CallRuntime* expr) {
__ CallRuntime(Runtime::kGetPrototype, 1);
__ push(result_register());
// Load original constructor into ecx.
__ mov(ecx, Operand(esp, 1 * kPointerSize));
// Check if the calling frame is an arguments adaptor frame.
Label adaptor_frame, args_set_up, runtime;
__ mov(edx, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
__ mov(ecx, Operand(edx, StandardFrameConstants::kContextOffset));
__ cmp(ecx, Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
__ mov(ebx, Operand(edx, StandardFrameConstants::kContextOffset));
__ cmp(ebx, Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
__ j(equal, &adaptor_frame);
// default constructor has no arguments, so no adaptor frame means no args.
__ mov(eax, Immediate(0));
......@@ -4226,17 +4228,17 @@ void FullCodeGenerator::EmitDefaultConstructorCallSuper(CallRuntime* expr) {
// Copy arguments from adaptor frame.
{
__ bind(&adaptor_frame);
__ mov(ecx, Operand(edx, ArgumentsAdaptorFrameConstants::kLengthOffset));
__ SmiUntag(ecx);
__ mov(ebx, Operand(edx, ArgumentsAdaptorFrameConstants::kLengthOffset));
__ SmiUntag(ebx);
__ mov(eax, ecx);
__ lea(edx, Operand(edx, ecx, times_pointer_size,
__ mov(eax, ebx);
__ lea(edx, Operand(edx, ebx, times_pointer_size,
StandardFrameConstants::kCallerSPOffset));
Label loop;
__ bind(&loop);
__ push(Operand(edx, -1 * kPointerSize));
__ sub(edx, Immediate(kPointerSize));
__ dec(ecx);
__ dec(ebx);
__ j(not_zero, &loop);
}
......
......@@ -170,12 +170,12 @@ void CallConstructDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// eax : number of arguments
// ebx : feedback vector
// edx : (only if ebx is not the megamorphic symbol) slot in feedback
// vector (Smi)
// ecx : original constructor (for IsSuperConstructorCall)
// edx : slot in feedback vector (Smi, for RecordCallTarget)
// edi : constructor function
// TODO(turbofan): So far we don't gather type feedback and hence skip the
// slot parameter, but ArrayConstructStub needs the vector to be undefined.
Register registers[] = {eax, edi, ebx};
Register registers[] = {eax, edi, ecx, ebx};
data->InitializePlatformSpecific(arraysize(registers), registers, NULL);
}
......
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