X87: Switch CallConstructStub to take new.target in register.
authorchunyang.dai <chunyang.dai@intel.com>
Thu, 16 Jul 2015 08:52:51 +0000 (01:52 -0700)
committerCommit bot <commit-bot@chromium.org>
Thu, 16 Jul 2015 08:53:06 +0000 (08:53 +0000)
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}

src/x87/builtins-x87.cc
src/x87/code-stubs-x87.cc
src/x87/full-codegen-x87.cc
src/x87/interface-descriptors-x87.cc

index 2e2bcd3..1036eff 100644 (file)
@@ -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
index 959160a..9eae32a 100644 (file)
@@ -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 =
index 2eca38a..1bf9ff8 100644 (file)
@@ -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);
   }
 
index 09ea37c..279b426 100644 (file)
@@ -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);
 }