Reviewers: mvstanton,

Message:
Note that this only contains the ARM port, but I wanted to get your general
opinion on this early, before doing the ports.

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

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 exists, hence cannot be peeked into.

[email protected]

Please review this at https://codereview.chromium.org/1237813002/

Base URL: https://chromium.googlesource.com/v8/v8.git@master

Affected files (+41, -38 lines):
  M src/arm/builtins-arm.cc
  M src/arm/code-stubs-arm.cc
  M src/arm/full-codegen-arm.cc
  M src/arm/interface-descriptors-arm.cc
  M src/arm64/interface-descriptors-arm64.cc
  M src/compiler/js-generic-lowering.cc
  M src/ia32/interface-descriptors-ia32.cc
  M src/mips/interface-descriptors-mips.cc
  M src/mips64/interface-descriptors-mips64.cc
  M src/x64/interface-descriptors-x64.cc


Index: src/arm/builtins-arm.cc
diff --git a/src/arm/builtins-arm.cc b/src/arm/builtins-arm.cc
index d08216c74adb878f70dbfe0dc9f87eaac1ef7c0a..3f0177457af12ea2816f7fb318255ae6d7a4d3c3 100644
--- a/src/arm/builtins-arm.cc
+++ b/src/arm/builtins-arm.cc
@@ -1503,9 +1503,7 @@ static void Generate_ConstructHelper(MacroAssembler* masm) {
     __ push(r0);  // limit
     __ mov(r1, Operand::Zero());  // initial index
     __ push(r1);
-    // Push newTarget and callee functions
-    __ ldr(r0, MemOperand(fp, kNewTargetOffset));
-    __ push(r0);
+    // Push the constructor function as callee.
     __ ldr(r0, MemOperand(fp, kFunctionOffset));
     __ push(r0);

@@ -1516,13 +1514,12 @@ static void Generate_ConstructHelper(MacroAssembler* masm) {
     // Use undefined feedback vector
     __ LoadRoot(r2, Heap::kUndefinedValueRootIndex);
     __ ldr(r1, MemOperand(fp, kFunctionOffset));
+    __ ldr(r4, MemOperand(fp, kNewTargetOffset));

     // Call the function.
     CallConstructStub stub(masm->isolate(), SUPER_CONSTRUCTOR_CALL);
     __ Call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL);

-    __ Drop(1);
-
     // Leave internal frame.
   }
   __ add(sp, sp, Operand(kStackSize * kPointerSize));
Index: src/arm/code-stubs-arm.cc
diff --git a/src/arm/code-stubs-arm.cc b/src/arm/code-stubs-arm.cc
index 005fb97513d0277325c9ff516612aeb922f1949c..c71a6e3efebfb95188eae188fd514f396a458e0d 100644
--- a/src/arm/code-stubs-arm.cc
+++ b/src/arm/code-stubs-arm.cc
@@ -2607,18 +2607,24 @@ void CallConstructStub::Generate(MacroAssembler* masm) {
   // r0 : number of arguments
   // r1 : the function to call
   // r2 : feedback vector
-  // r3 : (only if r2 is not the megamorphic symbol) slot in feedback
-  //      vector (Smi)
+  // r3 : slot in feedback vector (Smi, for RecordCallTarget)
+  // r4 : original constructor (for IsSuperConstructorCall)
   Label slow, non_function_call;

   // Check that the function is not a smi.
   __ JumpIfSmi(r1, &non_function_call);
   // Check that the function is a JSFunction.
-  __ CompareObjectType(r1, r4, r4, JS_FUNCTION_TYPE);
+  __ CompareObjectType(r1, r5, r5, JS_FUNCTION_TYPE);
   __ b(ne, &slow);

   if (RecordCallTarget()) {
+    if (IsSuperConstructorCall()) {
+      __ push(r4);
+    }
     GenerateRecordCallTarget(masm);
+    if (IsSuperConstructorCall()) {
+      __ pop(r4);
+    }

     __ add(r5, r2, Operand::PointerOffsetFromSmiKey(r3));
     if (FLAG_pretenuring_call_new) {
@@ -2642,9 +2648,7 @@ void CallConstructStub::Generate(MacroAssembler* masm) {

   // Pass function as original constructor.
   if (IsSuperConstructorCall()) {
-    __ mov(r4, Operand(1 * kPointerSize));
-    __ add(r4, r4, Operand(r0, LSL, kPointerSizeLog2));
-    __ ldr(r3, MemOperand(sp, r4));
+    __ mov(r3, r4);
   } else {
     __ mov(r3, r1);
   }
@@ -2658,10 +2662,10 @@ void CallConstructStub::Generate(MacroAssembler* masm) {

   // r0: number of arguments
   // r1: called object
-  // r4: object type
+  // r5: object type
   Label do_call;
   __ bind(&slow);
-  __ cmp(r4, Operand(JS_FUNCTION_PROXY_TYPE));
+  __ cmp(r5, Operand(JS_FUNCTION_PROXY_TYPE));
   __ b(ne, &non_function_call);
   __ GetBuiltinFunction(r1, Builtins::CALL_FUNCTION_PROXY_AS_CONSTRUCTOR);
   __ jmp(&do_call);
Index: src/arm/full-codegen-arm.cc
diff --git a/src/arm/full-codegen-arm.cc b/src/arm/full-codegen-arm.cc
index 2ed37e4196c86b64e7492ffa87770f858e55cfd6..7eb88a43f762a8986e74588c4bbf46e617349f85 100644
--- a/src/arm/full-codegen-arm.cc
+++ b/src/arm/full-codegen-arm.cc
@@ -3386,9 +3386,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());

@@ -3403,6 +3400,10 @@ void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) {
   // constructor invocation.
   SetConstructCallPosition(expr);

+  // Load original constructor into r4.
+  VisitForAccumulatorValue(super_call_ref->new_target_var());
+  __ mov(r4, result_register());
+
   // Load function and argument count into r1 and r0.
   __ mov(r0, Operand(arg_count));
   __ ldr(r1, MemOperand(sp, arg_count * kPointerSize));
@@ -3423,8 +3424,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());
@@ -4335,6 +4334,9 @@ void FullCodeGenerator::EmitDefaultConstructorCallSuper(CallRuntime* expr) {
   __ CallRuntime(Runtime::kGetPrototype, 1);
   __ Push(result_register());

+  // Load original constructor into r4.
+  __ ldr(r4, MemOperand(sp, 1 * kPointerSize));
+
   // Check if the calling frame is an arguments adaptor frame.
   Label adaptor_frame, args_set_up, runtime;
   __ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
Index: src/arm/interface-descriptors-arm.cc
diff --git a/src/arm/interface-descriptors-arm.cc b/src/arm/interface-descriptors-arm.cc index f65b6d272d7679e2b4114b0a835262dfa10e98a8..76ad3ba39c2aa56854589f36a3eb2bf032b52cc0 100644
--- a/src/arm/interface-descriptors-arm.cc
+++ b/src/arm/interface-descriptors-arm.cc
@@ -169,11 +169,11 @@ void CallConstructDescriptor::InitializePlatformSpecific(
   // r0 : number of arguments
   // r1 : the function to call
   // r2 : feedback vector
-  // r3 : (only if r2 is not the megamorphic symbol) slot in feedback
-  //      vector (Smi)
+  // r3 : slot in feedback vector (Smi, for RecordCallTarget)
+  // r4 : original constructor (for IsSuperConstructorCall)
// 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[] = {r0, r1, r2};
+  Register registers[] = {r0, r1, r4, r2};
   data->InitializePlatformSpecific(arraysize(registers), registers);
 }

Index: src/arm64/interface-descriptors-arm64.cc
diff --git a/src/arm64/interface-descriptors-arm64.cc b/src/arm64/interface-descriptors-arm64.cc index d6aa2573d05c12482f3f16a6aea6aaf4af3d60c0..d175de307cfb1fad118bf386b7c5a68d5515c426 100644
--- a/src/arm64/interface-descriptors-arm64.cc
+++ b/src/arm64/interface-descriptors-arm64.cc
@@ -192,10 +192,11 @@ void CallConstructDescriptor::InitializePlatformSpecific(
   // x0 : number of arguments
   // x1 : the function to call
   // x2 : feedback vector
- // x3 : slot in feedback vector (smi) (if r2 is not the megamorphic symbol)
+  // x3 : slot in feedback vector (Smi, for RecordCallTarget)
+  // x4 : original constructor (for IsSuperConstructorCall)
// 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[] = {x0, x1, x2};
+  Register registers[] = {x0, x1, x4, x2};
   data->InitializePlatformSpecific(arraysize(registers), registers);
 }

Index: src/compiler/js-generic-lowering.cc
diff --git a/src/compiler/js-generic-lowering.cc b/src/compiler/js-generic-lowering.cc index 4915b75d06f4d93e009472dcf84c66974e6d9541..84ee3933e22a28ba715417ed7222fdca7aa117bd 100644
--- a/src/compiler/js-generic-lowering.cc
+++ b/src/compiler/js-generic-lowering.cc
@@ -549,9 +549,8 @@ void JSGenericLowering::LowerJSCallConstruct(Node* node) {
   node->InsertInput(zone(), 0, stub_code);
   node->InsertInput(zone(), 1, jsgraph()->Int32Constant(arity - 2));
   node->InsertInput(zone(), 2, actual_construct);
-  // TODO(mstarzinger): Pass original constructor in register.
-  CHECK_EQ(actual_construct, original_construct);
-  node->InsertInput(zone(), 3, jsgraph()->UndefinedConstant());
+  node->InsertInput(zone(), 3, original_construct);
+  node->InsertInput(zone(), 4, jsgraph()->UndefinedConstant());
   node->set_op(common()->Call(desc));
 }

Index: src/ia32/interface-descriptors-ia32.cc
diff --git a/src/ia32/interface-descriptors-ia32.cc b/src/ia32/interface-descriptors-ia32.cc index 9c87d324f192bdf2777a6d118035b9d734800bde..fda6de1de6fd7b25fd8ad7a16798343f5dbcb7f4 100644
--- a/src/ia32/interface-descriptors-ia32.cc
+++ b/src/ia32/interface-descriptors-ia32.cc
@@ -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);
 }

Index: src/mips/interface-descriptors-mips.cc
diff --git a/src/mips/interface-descriptors-mips.cc b/src/mips/interface-descriptors-mips.cc index 55b86c03b1da3d94aa0f0ed19bfafc07a8e97158..71be512d7bc0fa3142d7c9014265eb6095f2a690 100644
--- a/src/mips/interface-descriptors-mips.cc
+++ b/src/mips/interface-descriptors-mips.cc
@@ -169,11 +169,11 @@ void CallConstructDescriptor::InitializePlatformSpecific(
   // a0 : number of arguments
   // a1 : the function to call
   // a2 : feedback vector
-  // a3 : (only if a2 is not the megamorphic symbol) slot in feedback
-  //      vector (Smi)
+  // a3 : slot in feedback vector (Smi, for RecordCallTarget)
+  // t0 : original constructor (for IsSuperConstructorCall)
// 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[] = {a0, a1, a2};
+  Register registers[] = {a0, a1, t0, a2};
   data->InitializePlatformSpecific(arraysize(registers), registers, NULL);
 }

Index: src/mips64/interface-descriptors-mips64.cc
diff --git a/src/mips64/interface-descriptors-mips64.cc b/src/mips64/interface-descriptors-mips64.cc index cb596af41478143721020bc6c4da338ab817b751..495d93768dde12f4d8d86f574be61183641e9ceb 100644
--- a/src/mips64/interface-descriptors-mips64.cc
+++ b/src/mips64/interface-descriptors-mips64.cc
@@ -169,11 +169,11 @@ void CallConstructDescriptor::InitializePlatformSpecific(
   // a0 : number of arguments
   // a1 : the function to call
   // a2 : feedback vector
-  // a3 : (only if a2 is not the megamorphic symbol) slot in feedback
-  //      vector (Smi)
+  // a3 : slot in feedback vector (Smi, for RecordCallTarget)
+  // t0 : original constructor (for IsSuperConstructorCall)
// 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[] = {a0, a1, a2};
+  Register registers[] = {a0, a1, t0, a2};
   data->InitializePlatformSpecific(arraysize(registers), registers, NULL);
 }

Index: src/x64/interface-descriptors-x64.cc
diff --git a/src/x64/interface-descriptors-x64.cc b/src/x64/interface-descriptors-x64.cc index 36f7ea66ff87a8937898b411980f41be99a13a30..40bff24f5128e246e361eac4c4fee96948b37c00 100644
--- a/src/x64/interface-descriptors-x64.cc
+++ b/src/x64/interface-descriptors-x64.cc
@@ -171,12 +171,12 @@ void CallConstructDescriptor::InitializePlatformSpecific(
     CallInterfaceDescriptorData* data) {
   // rax : number of arguments
   // rbx : feedback vector
-  // rdx : (only if rbx is not the megamorphic symbol) slot in feedback
-  //       vector (Smi)
+  // rcx : original constructor (for IsSuperConstructorCall)
+  // rdx : slot in feedback vector (Smi, for RecordCallTarget)
   // rdi : 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[] = {rax, rdi, rbx};
+  Register registers[] = {rax, rdi, rcx, rbx};
   data->InitializePlatformSpecific(arraysize(registers), registers);
 }



--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to