[es6] Super call in arrows and eval
authorarv <arv@chromium.org>
Tue, 2 Jun 2015 22:04:25 +0000 (15:04 -0700)
committerCommit bot <commit-bot@chromium.org>
Tue, 2 Jun 2015 22:04:33 +0000 (22:04 +0000)
This splits the SuperReference AST node into SuperPropertyReference and
SuperCallReference. The super call reference node consists of three
unresolved vars to this, new.target and this_function. These gets
declared when the right function is entered and if it is in use. The
variables gets assigned in FullCodeGenerator::Generate.

This is a revert of the revert 88b1c9170a0293cbcc8bdaf57fbe12744b48d7e8

BUG=v8:3768
LOG=N
R=wingo@igalia.com, adamk@chromium.org

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

Cr-Commit-Position: refs/heads/master@{#28769}

26 files changed:
src/arm/full-codegen-arm.cc
src/arm64/full-codegen-arm64.cc
src/ast-numbering.cc
src/ast-value-factory.h
src/ast.cc
src/ast.h
src/compiler/ast-graph-builder.cc
src/compiler/ast-loop-assignment-analyzer.cc
src/full-codegen.cc
src/full-codegen.h
src/hydrogen.cc
src/ia32/full-codegen-ia32.cc
src/mips/full-codegen-mips.cc
src/mips64/full-codegen-mips64.cc
src/parser.cc
src/parser.h
src/pattern-rewriter.cc
src/preparser.h
src/prettyprinter.cc
src/runtime/runtime.h
src/scopes.cc
src/scopes.h
src/typing.cc
src/variables.h
src/x64/full-codegen-x64.cc
test/mjsunit/harmony/super.js

index a792d9f3d2ed33728f80f293a7b0bf4fa9052965..19baa1e19fe6806774035218095c76a601c7d333 100644 (file)
@@ -247,6 +247,24 @@ void FullCodeGenerator::Generate() {
     __ Push(r1);
   }
 
+  // Possibly set up a local binding to the this function which is used in
+  // derived constructors with super calls.
+  Variable* this_function_var = scope()->this_function_var();
+  if (this_function_var != nullptr) {
+    Comment cmnt(masm_, "[ This function");
+    SetVar(this_function_var, r1, r0, r2);
+  }
+
+  Variable* new_target_var = scope()->new_target_var();
+  if (new_target_var != nullptr) {
+    Comment cmnt(masm_, "[ new.target");
+    // new.target is parameter -2.
+    int offset = 2 * kPointerSize +
+                 (info_->scope()->num_parameters() + 1) * kPointerSize;
+    __ ldr(r0, MemOperand(fp, offset));
+    SetVar(new_target_var, r0, r2, r3);
+  }
+
   ArgumentsAccessStub::HasNewTarget has_new_target =
       IsSubclassConstructor(info->function()->kind())
           ? ArgumentsAccessStub::HAS_NEW_TARGET
@@ -2002,9 +2020,10 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
       }
       break;
     case NAMED_SUPER_PROPERTY:
-      VisitForStackValue(property->obj()->AsSuperReference()->this_var());
+      VisitForStackValue(
+          property->obj()->AsSuperPropertyReference()->this_var());
       VisitForAccumulatorValue(
-          property->obj()->AsSuperReference()->home_object_var());
+          property->obj()->AsSuperPropertyReference()->home_object_var());
       __ Push(result_register());
       if (expr->is_compound()) {
         const Register scratch = r1;
@@ -2014,9 +2033,10 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
       }
       break;
     case KEYED_SUPER_PROPERTY:
-      VisitForStackValue(property->obj()->AsSuperReference()->this_var());
       VisitForStackValue(
-          property->obj()->AsSuperReference()->home_object_var());
+          property->obj()->AsSuperPropertyReference()->this_var());
+      VisitForStackValue(
+          property->obj()->AsSuperPropertyReference()->home_object_var());
       VisitForAccumulatorValue(property->key());
       __ Push(result_register());
       if (expr->is_compound()) {
@@ -2659,9 +2679,9 @@ void FullCodeGenerator::EmitAssignment(Expression* expr,
     }
     case NAMED_SUPER_PROPERTY: {
       __ Push(r0);
-      VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
+      VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
       VisitForAccumulatorValue(
-          prop->obj()->AsSuperReference()->home_object_var());
+          prop->obj()->AsSuperPropertyReference()->home_object_var());
       // stack: value, this; r0: home_object
       Register scratch = r2;
       Register scratch2 = r3;
@@ -2676,8 +2696,9 @@ void FullCodeGenerator::EmitAssignment(Expression* expr,
     }
     case KEYED_SUPER_PROPERTY: {
       __ Push(r0);
-      VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
-      VisitForStackValue(prop->obj()->AsSuperReference()->home_object_var());
+      VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
+      VisitForStackValue(
+          prop->obj()->AsSuperPropertyReference()->home_object_var());
       VisitForAccumulatorValue(prop->key());
       Register scratch = r2;
       Register scratch2 = r3;
@@ -2901,8 +2922,9 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
       __ Move(LoadDescriptor::ReceiverRegister(), r0);
       EmitNamedPropertyLoad(expr);
     } else {
-      VisitForStackValue(expr->obj()->AsSuperReference()->this_var());
-      VisitForStackValue(expr->obj()->AsSuperReference()->home_object_var());
+      VisitForStackValue(expr->obj()->AsSuperPropertyReference()->this_var());
+      VisitForStackValue(
+          expr->obj()->AsSuperPropertyReference()->home_object_var());
       EmitNamedSuperPropertyLoad(expr);
     }
   } else {
@@ -2913,8 +2935,9 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
       __ pop(LoadDescriptor::ReceiverRegister());
       EmitKeyedPropertyLoad(expr);
     } else {
-      VisitForStackValue(expr->obj()->AsSuperReference()->this_var());
-      VisitForStackValue(expr->obj()->AsSuperReference()->home_object_var());
+      VisitForStackValue(expr->obj()->AsSuperPropertyReference()->this_var());
+      VisitForStackValue(
+          expr->obj()->AsSuperPropertyReference()->home_object_var());
       VisitForStackValue(expr->key());
       EmitKeyedSuperPropertyLoad(expr);
     }
@@ -2979,7 +3002,7 @@ void FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) {
   DCHECK(!key->value()->IsSmi());
   // Load the function from the receiver.
   const Register scratch = r1;
-  SuperReference* super_ref = prop->obj()->AsSuperReference();
+  SuperPropertyReference* super_ref = prop->obj()->AsSuperPropertyReference();
   VisitForStackValue(super_ref->home_object_var());
   VisitForAccumulatorValue(super_ref->this_var());
   __ Push(r0);
@@ -3039,7 +3062,7 @@ void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) {
   SetSourcePosition(prop->position());
   // Load the function from the receiver.
   const Register scratch = r1;
-  SuperReference* super_ref = prop->obj()->AsSuperReference();
+  SuperPropertyReference* super_ref = prop->obj()->AsSuperPropertyReference();
   VisitForStackValue(super_ref->home_object_var());
   VisitForAccumulatorValue(super_ref->this_var());
   __ Push(r0);
@@ -3121,15 +3144,8 @@ void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
 }
 
 
-void FullCodeGenerator::EmitLoadSuperConstructor() {
-  __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
-  __ Push(r0);
-  __ CallRuntime(Runtime::kGetPrototype, 1);
-}
-
-
 void FullCodeGenerator::EmitInitializeThisAfterSuper(
-    SuperReference* super_ref, FeedbackVectorICSlot slot) {
+    SuperCallReference* super_ref, FeedbackVectorICSlot slot) {
   Variable* this_var = super_ref->this_var()->var();
   GetVar(r1, this_var);
   __ CompareRoot(r1, Heap::kTheHoleValueRootIndex);
@@ -3289,7 +3305,7 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) {
   // Push constructor on the stack.  If it's not a function it's used as
   // receiver for CALL_NON_FUNCTION, otherwise the value on the stack is
   // ignored.
-  DCHECK(!expr->expression()->IsSuperReference());
+  DCHECK(!expr->expression()->IsSuperPropertyReference());
   VisitForStackValue(expr->expression());
 
   // Push the arguments ("left-to-right") on the stack.
@@ -3325,11 +3341,14 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) {
 
 
 void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) {
-  Variable* new_target_var = scope()->DeclarationScope()->new_target_var();
-  GetVar(result_register(), new_target_var);
-  __ Push(result_register());
+  SuperCallReference* super_call_ref =
+      expr->expression()->AsSuperCallReference();
+  DCHECK_NOT_NULL(super_call_ref);
 
-  EmitLoadSuperConstructor();
+  VariableProxy* new_target_proxy = super_call_ref->new_target_var();
+  VisitForStackValue(new_target_proxy);
+
+  EmitLoadSuperConstructor(super_call_ref);
   __ push(result_register());
 
   // Push the arguments ("left-to-right") on the stack.
@@ -3367,8 +3386,7 @@ void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) {
 
   RecordJSReturnSite(expr);
 
-  EmitInitializeThisAfterSuper(expr->expression()->AsSuperReference(),
-                               expr->CallFeedbackICSlot());
+  EmitInitializeThisAfterSuper(super_call_ref, expr->CallFeedbackICSlot());
   context()->Plug(r0);
 }
 
@@ -4229,11 +4247,15 @@ void FullCodeGenerator::EmitCallFunction(CallRuntime* expr) {
 
 
 void FullCodeGenerator::EmitDefaultConstructorCallSuper(CallRuntime* expr) {
-  Variable* new_target_var = scope()->DeclarationScope()->new_target_var();
-  GetVar(result_register(), new_target_var);
-  __ Push(result_register());
+  ZoneList<Expression*>* args = expr->arguments();
+  DCHECK(args->length() == 2);
+
+  // new.target
+  VisitForStackValue(args->at(0));
 
-  EmitLoadSuperConstructor();
+  // .this_function
+  VisitForStackValue(args->at(1));
+  __ CallRuntime(Runtime::kGetPrototype, 1);
   __ Push(result_register());
 
   // Check if the calling frame is an arguments adaptor frame.
@@ -4626,11 +4648,14 @@ void FullCodeGenerator::EmitDebugIsActive(CallRuntime* expr) {
 
 void FullCodeGenerator::EmitCallSuperWithSpread(CallRuntime* expr) {
   // Assert: expr === CallRuntime("ReflectConstruct")
+  DCHECK_EQ(1, expr->arguments()->length());
   CallRuntime* call = expr->arguments()->at(0)->AsCallRuntime();
+
   ZoneList<Expression*>* args = call->arguments();
   DCHECK_EQ(3, args->length());
 
-  SuperReference* super_reference = args->at(0)->AsSuperReference();
+  SuperCallReference* super_call_ref = args->at(0)->AsSuperCallReference();
+  DCHECK_NOT_NULL(super_call_ref);
 
   // Load ReflectConstruct function
   EmitLoadJSRuntimeFunction(call);
@@ -4640,8 +4665,8 @@ void FullCodeGenerator::EmitCallSuperWithSpread(CallRuntime* expr) {
   __ push(ip);
   __ str(r0, MemOperand(sp, kPointerSize));
 
-  // Push super
-  EmitLoadSuperConstructor();
+  // Push super constructor
+  EmitLoadSuperConstructor(super_call_ref);
   __ Push(result_register());
 
   // Push arguments array
@@ -4658,7 +4683,7 @@ void FullCodeGenerator::EmitCallSuperWithSpread(CallRuntime* expr) {
   context()->DropAndPlug(1, r0);
 
   // TODO(mvstanton): with FLAG_vector_stores this needs a slot id.
-  EmitInitializeThisAfterSuper(super_reference);
+  EmitInitializeThisAfterSuper(super_call_ref);
 }
 
 
@@ -4883,9 +4908,9 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
       }
 
       case NAMED_SUPER_PROPERTY: {
-        VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
+        VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
         VisitForAccumulatorValue(
-            prop->obj()->AsSuperReference()->home_object_var());
+            prop->obj()->AsSuperPropertyReference()->home_object_var());
         __ Push(result_register());
         const Register scratch = r1;
         __ ldr(scratch, MemOperand(sp, kPointerSize));
@@ -4896,8 +4921,9 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
       }
 
       case KEYED_SUPER_PROPERTY: {
-        VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
-        VisitForStackValue(prop->obj()->AsSuperReference()->home_object_var());
+        VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
+        VisitForStackValue(
+            prop->obj()->AsSuperPropertyReference()->home_object_var());
         VisitForAccumulatorValue(prop->key());
         __ Push(result_register());
         const Register scratch = r1;
index dfbae7d59574814f5a9706f4fd686de00a62faba..2b5dc6a1b561a2e938dae80e67afa10fd439aaeb 100644 (file)
@@ -248,6 +248,24 @@ void FullCodeGenerator::Generate() {
     __ Push(x1);
   }
 
+  // Possibly set up a local binding to the this function which is used in
+  // derived constructors with super calls.
+  Variable* this_function_var = scope()->this_function_var();
+  if (this_function_var != nullptr) {
+    Comment cmnt(masm_, "[ This function");
+    SetVar(this_function_var, x1, x0, x2);
+  }
+
+  Variable* new_target_var = scope()->new_target_var();
+  if (new_target_var != nullptr) {
+    Comment cmnt(masm_, "[ new.target");
+    // new.target is parameter -2.
+    int offset =
+        2 * kXRegSize + (info_->scope()->num_parameters() + 1) * kPointerSize;
+    __ Ldr(x0, MemOperand(fp, offset));
+    SetVar(new_target_var, x0, x2, x3);
+  }
+
   ArgumentsAccessStub::HasNewTarget has_new_target =
       IsSubclassConstructor(info->function()->kind())
           ? ArgumentsAccessStub::HAS_NEW_TARGET
@@ -1970,9 +1988,10 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
       }
       break;
     case NAMED_SUPER_PROPERTY:
-      VisitForStackValue(property->obj()->AsSuperReference()->this_var());
+      VisitForStackValue(
+          property->obj()->AsSuperPropertyReference()->this_var());
       VisitForAccumulatorValue(
-          property->obj()->AsSuperReference()->home_object_var());
+          property->obj()->AsSuperPropertyReference()->home_object_var());
       __ Push(result_register());
       if (expr->is_compound()) {
         const Register scratch = x10;
@@ -1981,9 +2000,10 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
       }
       break;
     case KEYED_SUPER_PROPERTY:
-      VisitForStackValue(property->obj()->AsSuperReference()->this_var());
       VisitForStackValue(
-          property->obj()->AsSuperReference()->home_object_var());
+          property->obj()->AsSuperPropertyReference()->this_var());
+      VisitForStackValue(
+          property->obj()->AsSuperPropertyReference()->home_object_var());
       VisitForAccumulatorValue(property->key());
       __ Push(result_register());
       if (expr->is_compound()) {
@@ -2340,9 +2360,9 @@ void FullCodeGenerator::EmitAssignment(Expression* expr,
     }
     case NAMED_SUPER_PROPERTY: {
       __ Push(x0);
-      VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
+      VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
       VisitForAccumulatorValue(
-          prop->obj()->AsSuperReference()->home_object_var());
+          prop->obj()->AsSuperPropertyReference()->home_object_var());
       // stack: value, this; x0: home_object
       Register scratch = x10;
       Register scratch2 = x11;
@@ -2357,8 +2377,9 @@ void FullCodeGenerator::EmitAssignment(Expression* expr,
     }
     case KEYED_SUPER_PROPERTY: {
       __ Push(x0);
-      VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
-      VisitForStackValue(prop->obj()->AsSuperReference()->home_object_var());
+      VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
+      VisitForStackValue(
+          prop->obj()->AsSuperPropertyReference()->home_object_var());
       VisitForAccumulatorValue(prop->key());
       Register scratch = x10;
       Register scratch2 = x11;
@@ -2584,8 +2605,9 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
       __ Move(LoadDescriptor::ReceiverRegister(), x0);
       EmitNamedPropertyLoad(expr);
     } else {
-      VisitForStackValue(expr->obj()->AsSuperReference()->this_var());
-      VisitForStackValue(expr->obj()->AsSuperReference()->home_object_var());
+      VisitForStackValue(expr->obj()->AsSuperPropertyReference()->this_var());
+      VisitForStackValue(
+          expr->obj()->AsSuperPropertyReference()->home_object_var());
       EmitNamedSuperPropertyLoad(expr);
     }
   } else {
@@ -2596,8 +2618,9 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
       __ Pop(LoadDescriptor::ReceiverRegister());
       EmitKeyedPropertyLoad(expr);
     } else {
-      VisitForStackValue(expr->obj()->AsSuperReference()->this_var());
-      VisitForStackValue(expr->obj()->AsSuperReference()->home_object_var());
+      VisitForStackValue(expr->obj()->AsSuperPropertyReference()->this_var());
+      VisitForStackValue(
+          expr->obj()->AsSuperPropertyReference()->home_object_var());
       VisitForStackValue(expr->key());
       EmitKeyedSuperPropertyLoad(expr);
     }
@@ -2665,7 +2688,8 @@ void FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) {
 
   // Load the function from the receiver.
   const Register scratch = x10;
-  SuperReference* super_ref = callee->AsProperty()->obj()->AsSuperReference();
+  SuperPropertyReference* super_ref =
+      callee->AsProperty()->obj()->AsSuperPropertyReference();
   VisitForStackValue(super_ref->home_object_var());
   VisitForAccumulatorValue(super_ref->this_var());
   __ Push(x0);
@@ -2724,7 +2748,8 @@ void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) {
 
   // Load the function from the receiver.
   const Register scratch = x10;
-  SuperReference* super_ref = callee->AsProperty()->obj()->AsSuperReference();
+  SuperPropertyReference* super_ref =
+      callee->AsProperty()->obj()->AsSuperPropertyReference();
   VisitForStackValue(super_ref->home_object_var());
   VisitForAccumulatorValue(super_ref->this_var());
   __ Push(x0);
@@ -2805,15 +2830,8 @@ void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
 }
 
 
-void FullCodeGenerator::EmitLoadSuperConstructor() {
-  __ ldr(x0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
-  __ Push(x0);
-  __ CallRuntime(Runtime::kGetPrototype, 1);
-}
-
-
 void FullCodeGenerator::EmitInitializeThisAfterSuper(
-    SuperReference* super_ref, FeedbackVectorICSlot slot) {
+    SuperCallReference* super_ref, FeedbackVectorICSlot slot) {
   Variable* this_var = super_ref->this_var()->var();
   GetVar(x1, this_var);
   Label uninitialized_this;
@@ -2973,7 +2991,7 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) {
   // Push constructor on the stack.  If it's not a function it's used as
   // receiver for CALL_NON_FUNCTION, otherwise the value on the stack is
   // ignored.
-  DCHECK(!expr->expression()->IsSuperReference());
+  DCHECK(!expr->expression()->IsSuperPropertyReference());
   VisitForStackValue(expr->expression());
 
   // Push the arguments ("left-to-right") on the stack.
@@ -3009,11 +3027,14 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) {
 
 
 void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) {
-  Variable* new_target_var = scope()->DeclarationScope()->new_target_var();
-  GetVar(result_register(), new_target_var);
-  __ Push(result_register());
+  SuperCallReference* super_call_ref =
+      expr->expression()->AsSuperCallReference();
+  DCHECK_NOT_NULL(super_call_ref);
 
-  EmitLoadSuperConstructor();
+  VariableProxy* new_target_proxy = super_call_ref->new_target_var();
+  VisitForStackValue(new_target_proxy);
+
+  EmitLoadSuperConstructor(super_call_ref);
   __ push(result_register());
 
   // Push the arguments ("left-to-right") on the stack.
@@ -3051,8 +3072,7 @@ void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) {
 
   RecordJSReturnSite(expr);
 
-  EmitInitializeThisAfterSuper(expr->expression()->AsSuperReference(),
-                               expr->CallFeedbackICSlot());
+  EmitInitializeThisAfterSuper(super_call_ref, expr->CallFeedbackICSlot());
   context()->Plug(x0);
 }
 
@@ -3932,11 +3952,15 @@ void FullCodeGenerator::EmitCallFunction(CallRuntime* expr) {
 
 
 void FullCodeGenerator::EmitDefaultConstructorCallSuper(CallRuntime* expr) {
-  Variable* new_target_var = scope()->DeclarationScope()->new_target_var();
-  GetVar(result_register(), new_target_var);
-  __ Push(result_register());
+  ZoneList<Expression*>* args = expr->arguments();
+  DCHECK(args->length() == 2);
+
+  // new.target
+  VisitForStackValue(args->at(0));
 
-  EmitLoadSuperConstructor();
+  // .this_function
+  VisitForStackValue(args->at(1));
+  __ CallRuntime(Runtime::kGetPrototype, 1);
   __ Push(result_register());
 
   // Check if the calling frame is an arguments adaptor frame.
@@ -4309,11 +4333,14 @@ void FullCodeGenerator::EmitDebugIsActive(CallRuntime* expr) {
 
 void FullCodeGenerator::EmitCallSuperWithSpread(CallRuntime* expr) {
   // Assert: expr === CallRuntime("ReflectConstruct")
+  DCHECK_EQ(1, expr->arguments()->length());
   CallRuntime* call = expr->arguments()->at(0)->AsCallRuntime();
+
   ZoneList<Expression*>* args = call->arguments();
   DCHECK_EQ(3, args->length());
 
-  SuperReference* super_reference = args->at(0)->AsSuperReference();
+  SuperCallReference* super_call_ref = args->at(0)->AsSuperCallReference();
+  DCHECK_NOT_NULL(super_call_ref);
 
   // Load ReflectConstruct function
   EmitLoadJSRuntimeFunction(call);
@@ -4322,8 +4349,8 @@ void FullCodeGenerator::EmitCallSuperWithSpread(CallRuntime* expr) {
   __ Pop(x10);
   __ Push(x0, x10);
 
-  // Push super
-  EmitLoadSuperConstructor();
+  // Push super constructor
+  EmitLoadSuperConstructor(super_call_ref);
   __ Push(result_register());
 
   // Push arguments array
@@ -4340,7 +4367,7 @@ void FullCodeGenerator::EmitCallSuperWithSpread(CallRuntime* expr) {
   context()->DropAndPlug(1, x0);
 
   // TODO(mvstanton): with FLAG_vector_stores this needs a slot id.
-  EmitInitializeThisAfterSuper(super_reference);
+  EmitInitializeThisAfterSuper(super_call_ref);
 }
 
 
@@ -4562,9 +4589,9 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
       }
 
       case NAMED_SUPER_PROPERTY: {
-        VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
+        VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
         VisitForAccumulatorValue(
-            prop->obj()->AsSuperReference()->home_object_var());
+            prop->obj()->AsSuperPropertyReference()->home_object_var());
         __ Push(result_register());
         const Register scratch = x10;
         __ Peek(scratch, kPointerSize);
@@ -4574,8 +4601,9 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
       }
 
       case KEYED_SUPER_PROPERTY: {
-        VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
-        VisitForStackValue(prop->obj()->AsSuperReference()->home_object_var());
+        VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
+        VisitForStackValue(
+            prop->obj()->AsSuperPropertyReference()->home_object_var());
         VisitForAccumulatorValue(prop->key());
         __ Push(result_register());
         const Register scratch1 = x10;
index 8e00a782d57e91511c3f6b93cef9c085c4c6cd41..1beaded0e10fc18720800bf47614a03dfed41bd2 100644 (file)
@@ -168,15 +168,26 @@ void AstNumberingVisitor::VisitThisFunction(ThisFunction* node) {
 }
 
 
-void AstNumberingVisitor::VisitSuperReference(SuperReference* node) {
+void AstNumberingVisitor::VisitSuperPropertyReference(
+    SuperPropertyReference* node) {
   IncrementNodeCount();
   DisableOptimization(kSuperReference);
-  node->set_base_id(ReserveIdRange(SuperReference::num_ids()));
+  node->set_base_id(ReserveIdRange(SuperPropertyReference::num_ids()));
   Visit(node->this_var());
   Visit(node->home_object_var());
 }
 
 
+void AstNumberingVisitor::VisitSuperCallReference(SuperCallReference* node) {
+  IncrementNodeCount();
+  DisableOptimization(kSuperReference);
+  node->set_base_id(ReserveIdRange(SuperCallReference::num_ids()));
+  Visit(node->this_var());
+  Visit(node->new_target_var());
+  Visit(node->this_function_var());
+}
+
+
 void AstNumberingVisitor::VisitImportDeclaration(ImportDeclaration* node) {
   IncrementNodeCount();
   DisableOptimization(kImportDeclaration);
index e9830c33fbdd1eb900c16f9690c33d8e254bfd38..d3b4dc5bfb88805fec244e0a69758dfc54484f3a 100644 (file)
@@ -267,6 +267,7 @@ class AstValue : public ZoneObject {
   F(spread_arguments, "$spreadArguments")                                  \
   F(spread_iterable, "$spreadIterable")                                    \
   F(this, "this")                                                          \
+  F(this_function, ".this_function")                                       \
   F(throw_iterator_result_not_an_object, "ThrowIteratorResultNotAnObject") \
   F(to_string, "$toString")                                                \
   F(undefined, "undefined")                                                \
index 120598351038671794f7e62575bd45dd93a4171a..fbefbd46f960ce347d56b8129a0e83de5b8c3843 100644 (file)
@@ -734,7 +734,7 @@ Call::CallType Call::GetCallType(Isolate* isolate) const {
     }
   }
 
-  if (expression()->AsSuperReference() != NULL) return SUPER_CALL;
+  if (expression()->IsSuperCallReference()) return SUPER_CALL;
 
   Property* property = expression()->AsProperty();
   return property != NULL ? PROPERTY_CALL : OTHER_CALL;
index c2a3b0023040d358a25e090bdc93c78302f6f0f0..4ef0282c07c1e1aa98a41fb4eb8132dd21ac392b 100644 (file)
--- a/src/ast.h
+++ b/src/ast.h
@@ -87,7 +87,8 @@ namespace internal {
   V(CompareOperation)           \
   V(Spread)                     \
   V(ThisFunction)               \
-  V(SuperReference)             \
+  V(SuperPropertyReference)     \
+  V(SuperCallReference)         \
   V(CaseClause)
 
 #define AST_NODE_LIST(V)                        \
@@ -1760,9 +1761,7 @@ class Property final : public Expression {
   }
   bool is_for_call() const { return IsForCallField::decode(bit_field_); }
 
-  bool IsSuperAccess() {
-    return obj()->IsSuperReference();
-  }
+  bool IsSuperAccess() { return obj()->IsSuperPropertyReference(); }
 
   virtual FeedbackVectorRequirements ComputeFeedbackRequirements(
       Isolate* isolate, const ICSlotCache* cache) override {
@@ -2791,16 +2790,16 @@ class ThisFunction final : public Expression {
 };
 
 
-class SuperReference final : public Expression {
+class SuperPropertyReference final : public Expression {
  public:
-  DECLARE_NODE_TYPE(SuperReference)
+  DECLARE_NODE_TYPE(SuperPropertyReference)
 
   VariableProxy* this_var() const { return this_var_; }
   VariableProxy* home_object_var() const { return home_object_var_; }
 
  protected:
-  SuperReference(Zone* zone, VariableProxy* this_var,
-                 VariableProxy* home_object_var, int pos)
+  SuperPropertyReference(Zone* zone, VariableProxy* this_var,
+                         VariableProxy* home_object_var, int pos)
       : Expression(zone, pos),
         this_var_(this_var),
         home_object_var_(home_object_var) {
@@ -2814,6 +2813,34 @@ class SuperReference final : public Expression {
 };
 
 
+class SuperCallReference final : public Expression {
+ public:
+  DECLARE_NODE_TYPE(SuperCallReference)
+
+  VariableProxy* this_var() const { return this_var_; }
+  VariableProxy* new_target_var() const { return new_target_var_; }
+  VariableProxy* this_function_var() const { return this_function_var_; }
+
+ protected:
+  SuperCallReference(Zone* zone, VariableProxy* this_var,
+                     VariableProxy* new_target_var,
+                     VariableProxy* this_function_var, int pos)
+      : Expression(zone, pos),
+        this_var_(this_var),
+        new_target_var_(new_target_var),
+        this_function_var_(this_function_var) {
+    DCHECK(this_var->is_this());
+    DCHECK(new_target_var->raw_name()->IsOneByteEqualTo("new.target"));
+    DCHECK(this_function_var->raw_name()->IsOneByteEqualTo(".this_function"));
+  }
+
+ private:
+  VariableProxy* this_var_;
+  VariableProxy* new_target_var_;
+  VariableProxy* this_function_var_;
+};
+
+
 #undef DECLARE_NODE_TYPE
 
 
@@ -3581,9 +3608,18 @@ class AstNodeFactory final BASE_EMBEDDED {
     return new (zone_) ThisFunction(zone_, pos);
   }
 
-  SuperReference* NewSuperReference(VariableProxy* this_var,
-                                    VariableProxy* home_object_var, int pos) {
-    return new (zone_) SuperReference(zone_, this_var, home_object_var, pos);
+  SuperPropertyReference* NewSuperPropertyReference(
+      VariableProxy* this_var, VariableProxy* home_object_var, int pos) {
+    return new (zone_)
+        SuperPropertyReference(zone_, this_var, home_object_var, pos);
+  }
+
+  SuperCallReference* NewSuperCallReference(VariableProxy* this_var,
+                                            VariableProxy* new_target_var,
+                                            VariableProxy* this_function_var,
+                                            int pos) {
+    return new (zone_) SuperCallReference(zone_, this_var, new_target_var,
+                                          this_function_var, pos);
   }
 
  private:
index 247f674981c6892183424c8da7f22bdf43d854c3..11ac9edf6362c0c44a43d0291fa9f7308d1ca186 100644 (file)
@@ -2589,7 +2589,15 @@ void AstGraphBuilder::VisitThisFunction(ThisFunction* expr) {
 }
 
 
-void AstGraphBuilder::VisitSuperReference(SuperReference* expr) {
+void AstGraphBuilder::VisitSuperPropertyReference(
+    SuperPropertyReference* expr) {
+  // TODO(turbofan): Implement super here.
+  SetStackOverflow();
+  ast_context()->ProduceValue(jsgraph()->UndefinedConstant());
+}
+
+
+void AstGraphBuilder::VisitSuperCallReference(SuperCallReference* expr) {
   // TODO(turbofan): Implement super here.
   SetStackOverflow();
   ast_context()->ProduceValue(jsgraph()->UndefinedConstant());
index a45848a0305a14702ab644af4353bd5a17f4a2b1..61ed4f27cbba8e7d7b9287108a87ab9e8f3435e2 100644 (file)
@@ -67,7 +67,8 @@ void ALAA::VisitVariableProxy(VariableProxy* leaf) {}
 void ALAA::VisitLiteral(Literal* leaf) {}
 void ALAA::VisitRegExpLiteral(RegExpLiteral* leaf) {}
 void ALAA::VisitThisFunction(ThisFunction* leaf) {}
-void ALAA::VisitSuperReference(SuperReference* leaf) {}
+void ALAA::VisitSuperPropertyReference(SuperPropertyReference* leaf) {}
+void ALAA::VisitSuperCallReference(SuperCallReference* leaf) {}
 
 
 // ---------------------------------------------------------------------------
index c69f6252ba4e110f7fbd8d23590c0a0bd3705fd6..8c6347d7d1702195de9f4cb9d8f432d21c0d8fa2 100644 (file)
@@ -276,7 +276,12 @@ void BreakableStatementChecker::VisitThisFunction(ThisFunction* expr) {
 }
 
 
-void BreakableStatementChecker::VisitSuperReference(SuperReference* expr) {}
+void BreakableStatementChecker::VisitSuperPropertyReference(
+    SuperPropertyReference* expr) {}
+
+
+void BreakableStatementChecker::VisitSuperCallReference(
+    SuperCallReference* expr) {}
 
 
 #define __ ACCESS_MASM(masm())
@@ -669,7 +674,13 @@ void FullCodeGenerator::SetStatementPosition(Statement* stmt) {
 }
 
 
-void FullCodeGenerator::VisitSuperReference(SuperReference* super) {
+void FullCodeGenerator::VisitSuperPropertyReference(
+    SuperPropertyReference* super) {
+  __ CallRuntime(Runtime::kThrowUnsupportedSuperError, 0);
+}
+
+
+void FullCodeGenerator::VisitSuperCallReference(SuperCallReference* super) {
   __ CallRuntime(Runtime::kThrowUnsupportedSuperError, 0);
 }
 
@@ -979,6 +990,12 @@ void FullCodeGenerator::EmitPropertyKey(ObjectLiteralProperty* property,
 }
 
 
+void FullCodeGenerator::EmitLoadSuperConstructor(SuperCallReference* ref) {
+  VisitForStackValue(ref->this_function_var());
+  __ CallRuntime(Runtime::kGetPrototype, 1);
+}
+
+
 void FullCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) {
   Comment cmnt(masm_, "[ ReturnStatement");
   SetStatementPosition(stmt);
index e81b44e4a3fd6a01a4ec0323bc89ce4aaa7ee814..a7a91d0af9ad5b5a7005d05a6117c50990492f3b 100644 (file)
@@ -672,9 +672,9 @@ class FullCodeGenerator: public AstVisitor {
       Expression* initializer, int offset,
       FeedbackVectorICSlot slot = FeedbackVectorICSlot::Invalid());
 
-  void EmitLoadSuperConstructor();
+  void EmitLoadSuperConstructor(SuperCallReference* super_call_ref);
   void EmitInitializeThisAfterSuper(
-      SuperReference* super_ref,
+      SuperCallReference* super_call_ref,
       FeedbackVectorICSlot slot = FeedbackVectorICSlot::Invalid());
 
   void CallIC(Handle<Code> code,
index 4267145437b72618be37913d30b695887ee06930..5916860f766ba0f2adac6145d801db1a5d0848af 100644 (file)
@@ -11567,7 +11567,16 @@ void HOptimizedGraphBuilder::VisitThisFunction(ThisFunction* expr) {
 }
 
 
-void HOptimizedGraphBuilder::VisitSuperReference(SuperReference* expr) {
+void HOptimizedGraphBuilder::VisitSuperPropertyReference(
+    SuperPropertyReference* expr) {
+  DCHECK(!HasStackOverflow());
+  DCHECK(current_block() != NULL);
+  DCHECK(current_block()->HasPredecessor());
+  return Bailout(kSuperReference);
+}
+
+
+void HOptimizedGraphBuilder::VisitSuperCallReference(SuperCallReference* expr) {
   DCHECK(!HasStackOverflow());
   DCHECK(current_block() != NULL);
   DCHECK(current_block()->HasPredecessor());
index cd8b22fa55faaf16cada738bbafc26bc8b371712..6427013f4e77cf69296378c0b4821455e8d45aff 100644 (file)
@@ -243,6 +243,24 @@ void FullCodeGenerator::Generate() {
     __ push(edi);
   }
 
+  // Possibly set up a local binding to the this function which is used in
+  // derived constructors with super calls.
+  Variable* this_function_var = scope()->this_function_var();
+  if (this_function_var != nullptr) {
+    Comment cmnt(masm_, "[ This function");
+    SetVar(this_function_var, edi, ebx, edx);
+  }
+
+  Variable* new_target_var = scope()->new_target_var();
+  if (new_target_var != nullptr) {
+    Comment cmnt(masm_, "[ new.target");
+    // new.target is parameter -2.
+    int offset = 2 * kPointerSize + kFPOnStackSize + kPCOnStackSize +
+                 (info_->scope()->num_parameters() - 1) * kPointerSize;
+    __ mov(eax, Operand(ebp, offset));
+    SetVar(new_target_var, eax, ebx, edx);
+  }
+
   ArgumentsAccessStub::HasNewTarget has_new_target =
       IsSubclassConstructor(info->function()->kind())
           ? ArgumentsAccessStub::HAS_NEW_TARGET
@@ -1920,9 +1938,10 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
       // Nothing to do here.
       break;
     case NAMED_SUPER_PROPERTY:
-      VisitForStackValue(property->obj()->AsSuperReference()->this_var());
+      VisitForStackValue(
+          property->obj()->AsSuperPropertyReference()->this_var());
       VisitForAccumulatorValue(
-          property->obj()->AsSuperReference()->home_object_var());
+          property->obj()->AsSuperPropertyReference()->home_object_var());
       __ push(result_register());
       if (expr->is_compound()) {
         __ push(MemOperand(esp, kPointerSize));
@@ -1939,9 +1958,10 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
       }
       break;
     case KEYED_SUPER_PROPERTY:
-      VisitForStackValue(property->obj()->AsSuperReference()->this_var());
       VisitForStackValue(
-          property->obj()->AsSuperReference()->home_object_var());
+          property->obj()->AsSuperPropertyReference()->this_var());
+      VisitForStackValue(
+          property->obj()->AsSuperPropertyReference()->home_object_var());
       VisitForAccumulatorValue(property->key());
       __ Push(result_register());
       if (expr->is_compound()) {
@@ -2565,9 +2585,9 @@ void FullCodeGenerator::EmitAssignment(Expression* expr,
     }
     case NAMED_SUPER_PROPERTY: {
       __ push(eax);
-      VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
+      VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
       VisitForAccumulatorValue(
-          prop->obj()->AsSuperReference()->home_object_var());
+          prop->obj()->AsSuperPropertyReference()->home_object_var());
       // stack: value, this; eax: home_object
       Register scratch = ecx;
       Register scratch2 = edx;
@@ -2582,8 +2602,9 @@ void FullCodeGenerator::EmitAssignment(Expression* expr,
     }
     case KEYED_SUPER_PROPERTY: {
       __ push(eax);
-      VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
-      VisitForStackValue(prop->obj()->AsSuperReference()->home_object_var());
+      VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
+      VisitForStackValue(
+          prop->obj()->AsSuperPropertyReference()->home_object_var());
       VisitForAccumulatorValue(prop->key());
       Register scratch = ecx;
       Register scratch2 = edx;
@@ -2805,8 +2826,9 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
       __ Move(LoadDescriptor::ReceiverRegister(), result_register());
       EmitNamedPropertyLoad(expr);
     } else {
-      VisitForStackValue(expr->obj()->AsSuperReference()->this_var());
-      VisitForStackValue(expr->obj()->AsSuperReference()->home_object_var());
+      VisitForStackValue(expr->obj()->AsSuperPropertyReference()->this_var());
+      VisitForStackValue(
+          expr->obj()->AsSuperPropertyReference()->home_object_var());
       EmitNamedSuperPropertyLoad(expr);
     }
   } else {
@@ -2817,8 +2839,9 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
       __ Move(LoadDescriptor::NameRegister(), result_register());  // Key.
       EmitKeyedPropertyLoad(expr);
     } else {
-      VisitForStackValue(expr->obj()->AsSuperReference()->this_var());
-      VisitForStackValue(expr->obj()->AsSuperReference()->home_object_var());
+      VisitForStackValue(expr->obj()->AsSuperPropertyReference()->this_var());
+      VisitForStackValue(
+          expr->obj()->AsSuperPropertyReference()->home_object_var());
       VisitForStackValue(expr->key());
       EmitKeyedSuperPropertyLoad(expr);
     }
@@ -2876,7 +2899,7 @@ void FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) {
   Literal* key = prop->key()->AsLiteral();
   DCHECK(!key->value()->IsSmi());
   // Load the function from the receiver.
-  SuperReference* super_ref = callee->AsProperty()->obj()->AsSuperReference();
+  SuperPropertyReference* super_ref = prop->obj()->AsSuperPropertyReference();
   VisitForStackValue(super_ref->home_object_var());
   VisitForAccumulatorValue(super_ref->this_var());
   __ push(eax);
@@ -2932,7 +2955,7 @@ void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) {
 
   SetSourcePosition(prop->position());
   // Load the function from the receiver.
-  SuperReference* super_ref = callee->AsProperty()->obj()->AsSuperReference();
+  SuperPropertyReference* super_ref = prop->obj()->AsSuperPropertyReference();
   VisitForStackValue(super_ref->home_object_var());
   VisitForAccumulatorValue(super_ref->this_var());
   __ push(eax);
@@ -3010,15 +3033,9 @@ void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
 }
 
 
-void FullCodeGenerator::EmitLoadSuperConstructor() {
-  __ push(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
-  __ CallRuntime(Runtime::kGetPrototype, 1);
-}
-
-
 void FullCodeGenerator::EmitInitializeThisAfterSuper(
-    SuperReference* super_ref, FeedbackVectorICSlot slot) {
-  Variable* this_var = super_ref->this_var()->var();
+    SuperCallReference* super_call_ref, FeedbackVectorICSlot slot) {
+  Variable* this_var = super_call_ref->this_var()->var();
   GetVar(ecx, this_var);
   __ cmp(ecx, isolate()->factory()->the_hole_value());
   Label uninitialized_this;
@@ -3167,7 +3184,7 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) {
   // Push constructor on the stack.  If it's not a function it's used as
   // receiver for CALL_NON_FUNCTION, otherwise the value on the stack is
   // ignored.
-  DCHECK(!expr->expression()->IsSuperReference());
+  DCHECK(!expr->expression()->IsSuperPropertyReference());
   VisitForStackValue(expr->expression());
 
   // Push the arguments ("left-to-right") on the stack.
@@ -3203,11 +3220,14 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) {
 
 
 void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) {
-  Variable* new_target_var = scope()->DeclarationScope()->new_target_var();
-  GetVar(eax, new_target_var);
-  __ push(eax);
+  SuperCallReference* super_call_ref =
+      expr->expression()->AsSuperCallReference();
+  DCHECK_NOT_NULL(super_call_ref);
 
-  EmitLoadSuperConstructor();
+  VariableProxy* new_target_proxy = super_call_ref->new_target_var();
+  VisitForStackValue(new_target_proxy);
+
+  EmitLoadSuperConstructor(super_call_ref);
   __ push(result_register());
 
   // Push the arguments ("left-to-right") on the stack.
@@ -3245,8 +3265,7 @@ void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) {
 
   RecordJSReturnSite(expr);
 
-  EmitInitializeThisAfterSuper(expr->expression()->AsSuperReference(),
-                               expr->CallFeedbackICSlot());
+  EmitInitializeThisAfterSuper(super_call_ref, expr->CallFeedbackICSlot());
   context()->Plug(eax);
 }
 
@@ -4123,11 +4142,15 @@ void FullCodeGenerator::EmitCallFunction(CallRuntime* expr) {
 
 
 void FullCodeGenerator::EmitDefaultConstructorCallSuper(CallRuntime* expr) {
-  Variable* new_target_var = scope()->DeclarationScope()->new_target_var();
-  GetVar(eax, new_target_var);
-  __ push(eax);
+  ZoneList<Expression*>* args = expr->arguments();
+  DCHECK(args->length() == 2);
+
+  // new.target
+  VisitForStackValue(args->at(0));
 
-  EmitLoadSuperConstructor();
+  // .this_function
+  VisitForStackValue(args->at(1));
+  __ CallRuntime(Runtime::kGetPrototype, 1);
   __ push(result_register());
 
   // Check if the calling frame is an arguments adaptor frame.
@@ -4550,11 +4573,14 @@ void FullCodeGenerator::EmitDebugIsActive(CallRuntime* expr) {
 
 void FullCodeGenerator::EmitCallSuperWithSpread(CallRuntime* expr) {
   // Assert: expr == CallRuntime("ReflectConstruct")
+  DCHECK_EQ(1, expr->arguments()->length());
   CallRuntime* call = expr->arguments()->at(0)->AsCallRuntime();
+
   ZoneList<Expression*>* args = call->arguments();
   DCHECK_EQ(3, args->length());
 
-  SuperReference* super_reference = args->at(0)->AsSuperReference();
+  SuperCallReference* super_call_ref = args->at(0)->AsSuperCallReference();
+  DCHECK_NOT_NULL(super_call_ref);
 
   // Load ReflectConstruct function
   EmitLoadJSRuntimeFunction(call);
@@ -4563,8 +4589,8 @@ void FullCodeGenerator::EmitCallSuperWithSpread(CallRuntime* expr) {
   __ push(Operand(esp, 0));
   __ mov(Operand(esp, kPointerSize), eax);
 
-  // Push super
-  EmitLoadSuperConstructor();
+  // Push super constructor
+  EmitLoadSuperConstructor(super_call_ref);
   __ Push(result_register());
 
   // Push arguments array
@@ -4581,7 +4607,7 @@ void FullCodeGenerator::EmitCallSuperWithSpread(CallRuntime* expr) {
   context()->DropAndPlug(1, eax);
 
   // TODO(mvstanton): with FLAG_vector_stores this needs a slot id.
-  EmitInitializeThisAfterSuper(super_reference);
+  EmitInitializeThisAfterSuper(super_call_ref);
 }
 
 
@@ -4806,9 +4832,9 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
       }
 
       case NAMED_SUPER_PROPERTY: {
-        VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
+        VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
         VisitForAccumulatorValue(
-            prop->obj()->AsSuperReference()->home_object_var());
+            prop->obj()->AsSuperPropertyReference()->home_object_var());
         __ push(result_register());
         __ push(MemOperand(esp, kPointerSize));
         __ push(result_register());
@@ -4817,8 +4843,9 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
       }
 
       case KEYED_SUPER_PROPERTY: {
-        VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
-        VisitForStackValue(prop->obj()->AsSuperReference()->home_object_var());
+        VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
+        VisitForStackValue(
+            prop->obj()->AsSuperPropertyReference()->home_object_var());
         VisitForAccumulatorValue(prop->key());
         __ push(result_register());
         __ push(MemOperand(esp, 2 * kPointerSize));
index fa295a4767174a45e89c8491566dd207db7b2a5e..ef8f981008fd5d9575009f4997f7eab1f5d2c5e8 100644 (file)
@@ -256,6 +256,24 @@ void FullCodeGenerator::Generate() {
     __ Push(a1);
   }
 
+  // Possibly set up a local binding to the this function which is used in
+  // derived constructors with super calls.
+  Variable* this_function_var = scope()->this_function_var();
+  if (this_function_var != nullptr) {
+    Comment cmnt(masm_, "[ This function");
+    SetVar(this_function_var, a1, a2, a3);
+  }
+
+  Variable* new_target_var = scope()->new_target_var();
+  if (new_target_var != nullptr) {
+    Comment cmnt(masm_, "[ new.target");
+    // new.target is parameter -2.
+    int offset = 2 * kPointerSize +
+                 (info_->scope()->num_parameters() + 1) * kPointerSize;
+    __ lw(v0, MemOperand(fp, offset));
+    SetVar(new_target_var, v0, a2, a3);
+  }
+
   ArgumentsAccessStub::HasNewTarget has_new_target =
       IsSubclassConstructor(info->function()->kind())
           ? ArgumentsAccessStub::HAS_NEW_TARGET
@@ -1988,9 +2006,10 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
       }
       break;
     case NAMED_SUPER_PROPERTY:
-      VisitForStackValue(property->obj()->AsSuperReference()->this_var());
+      VisitForStackValue(
+          property->obj()->AsSuperPropertyReference()->this_var());
       VisitForAccumulatorValue(
-          property->obj()->AsSuperReference()->home_object_var());
+          property->obj()->AsSuperPropertyReference()->home_object_var());
       __ Push(result_register());
       if (expr->is_compound()) {
         const Register scratch = a1;
@@ -2000,9 +2019,10 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
       break;
     case KEYED_SUPER_PROPERTY: {
       const Register scratch = a1;
-      VisitForStackValue(property->obj()->AsSuperReference()->this_var());
+      VisitForStackValue(
+          property->obj()->AsSuperPropertyReference()->this_var());
       VisitForAccumulatorValue(
-          property->obj()->AsSuperReference()->home_object_var());
+          property->obj()->AsSuperPropertyReference()->home_object_var());
       __ Move(scratch, result_register());
       VisitForAccumulatorValue(property->key());
       __ Push(scratch, result_register());
@@ -2636,9 +2656,9 @@ void FullCodeGenerator::EmitAssignment(Expression* expr,
     }
     case NAMED_SUPER_PROPERTY: {
       __ Push(v0);
-      VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
+      VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
       VisitForAccumulatorValue(
-          prop->obj()->AsSuperReference()->home_object_var());
+          prop->obj()->AsSuperPropertyReference()->home_object_var());
       // stack: value, this; v0: home_object
       Register scratch = a2;
       Register scratch2 = a3;
@@ -2653,8 +2673,9 @@ void FullCodeGenerator::EmitAssignment(Expression* expr,
     }
     case KEYED_SUPER_PROPERTY: {
       __ Push(v0);
-      VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
-      VisitForStackValue(prop->obj()->AsSuperReference()->home_object_var());
+      VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
+      VisitForStackValue(
+          prop->obj()->AsSuperPropertyReference()->home_object_var());
       VisitForAccumulatorValue(prop->key());
       Register scratch = a2;
       Register scratch2 = a3;
@@ -2883,8 +2904,9 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
       __ Move(LoadDescriptor::ReceiverRegister(), v0);
       EmitNamedPropertyLoad(expr);
     } else {
-      VisitForStackValue(expr->obj()->AsSuperReference()->this_var());
-      VisitForStackValue(expr->obj()->AsSuperReference()->home_object_var());
+      VisitForStackValue(expr->obj()->AsSuperPropertyReference()->this_var());
+      VisitForStackValue(
+          expr->obj()->AsSuperPropertyReference()->home_object_var());
       EmitNamedSuperPropertyLoad(expr);
     }
   } else {
@@ -2895,8 +2917,9 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
       __ pop(LoadDescriptor::ReceiverRegister());
       EmitKeyedPropertyLoad(expr);
     } else {
-      VisitForStackValue(expr->obj()->AsSuperReference()->this_var());
-      VisitForStackValue(expr->obj()->AsSuperReference()->home_object_var());
+      VisitForStackValue(expr->obj()->AsSuperPropertyReference()->this_var());
+      VisitForStackValue(
+          expr->obj()->AsSuperPropertyReference()->home_object_var());
       VisitForStackValue(expr->key());
       EmitKeyedSuperPropertyLoad(expr);
     }
@@ -2958,7 +2981,7 @@ void FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) {
   DCHECK(!key->value()->IsSmi());
   // Load the function from the receiver.
   const Register scratch = a1;
-  SuperReference* super_ref = prop->obj()->AsSuperReference();
+  SuperPropertyReference* super_ref = prop->obj()->AsSuperPropertyReference();
   VisitForAccumulatorValue(super_ref->home_object_var());
   __ mov(scratch, v0);
   VisitForAccumulatorValue(super_ref->this_var());
@@ -3016,7 +3039,7 @@ void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) {
   SetSourcePosition(prop->position());
   // Load the function from the receiver.
   const Register scratch = a1;
-  SuperReference* super_ref = prop->obj()->AsSuperReference();
+  SuperPropertyReference* super_ref = prop->obj()->AsSuperPropertyReference();
   VisitForAccumulatorValue(super_ref->home_object_var());
   __ Move(scratch, v0);
   VisitForAccumulatorValue(super_ref->this_var());
@@ -3096,15 +3119,8 @@ void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
 }
 
 
-void FullCodeGenerator::EmitLoadSuperConstructor() {
-  __ lw(a0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
-  __ Push(a0);
-  __ CallRuntime(Runtime::kGetPrototype, 1);
-}
-
-
 void FullCodeGenerator::EmitInitializeThisAfterSuper(
-    SuperReference* super_ref, FeedbackVectorICSlot slot) {
+    SuperCallReference* super_ref, FeedbackVectorICSlot slot) {
   Variable* this_var = super_ref->this_var()->var();
   GetVar(a1, this_var);
   __ LoadRoot(at, Heap::kTheHoleValueRootIndex);
@@ -3262,7 +3278,7 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) {
   // Push constructor on the stack.  If it's not a function it's used as
   // receiver for CALL_NON_FUNCTION, otherwise the value on the stack is
   // ignored.
-  DCHECK(!expr->expression()->IsSuperReference());
+  DCHECK(!expr->expression()->IsSuperPropertyReference());
   VisitForStackValue(expr->expression());
 
   // Push the arguments ("left-to-right") on the stack.
@@ -3298,11 +3314,14 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) {
 
 
 void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) {
-  Variable* new_target_var = scope()->DeclarationScope()->new_target_var();
-  GetVar(result_register(), new_target_var);
-  __ Push(result_register());
+  SuperCallReference* super_call_ref =
+      expr->expression()->AsSuperCallReference();
+  DCHECK_NOT_NULL(super_call_ref);
+
+  VariableProxy* new_target_proxy = super_call_ref->new_target_var();
+  VisitForStackValue(new_target_proxy);
 
-  EmitLoadSuperConstructor();
+  EmitLoadSuperConstructor(super_call_ref);
   __ push(result_register());
 
   // Push the arguments ("left-to-right") on the stack.
@@ -3340,8 +3359,7 @@ void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) {
 
   RecordJSReturnSite(expr);
 
-  EmitInitializeThisAfterSuper(expr->expression()->AsSuperReference(),
-                               expr->CallFeedbackICSlot());
+  EmitInitializeThisAfterSuper(super_call_ref, expr->CallFeedbackICSlot());
   context()->Plug(v0);
 }
 
@@ -4227,11 +4245,15 @@ void FullCodeGenerator::EmitCallFunction(CallRuntime* expr) {
 
 
 void FullCodeGenerator::EmitDefaultConstructorCallSuper(CallRuntime* expr) {
-  Variable* new_target_var = scope()->DeclarationScope()->new_target_var();
-  GetVar(result_register(), new_target_var);
-  __ Push(result_register());
+  ZoneList<Expression*>* args = expr->arguments();
+  DCHECK(args->length() == 2);
 
-  EmitLoadSuperConstructor();
+  // new.target
+  VisitForStackValue(args->at(0));
+
+  // .this_function
+  VisitForStackValue(args->at(1));
+  __ CallRuntime(Runtime::kGetPrototype, 1);
   __ Push(result_register());
 
   // Check if the calling frame is an arguments adaptor frame.
@@ -4633,11 +4655,14 @@ void FullCodeGenerator::EmitDebugIsActive(CallRuntime* expr) {
 
 void FullCodeGenerator::EmitCallSuperWithSpread(CallRuntime* expr) {
   // Assert: expr == CallRuntime("ReflectConstruct")
+  DCHECK_EQ(1, expr->arguments()->length());
   CallRuntime* call = expr->arguments()->at(0)->AsCallRuntime();
+
   ZoneList<Expression*>* args = call->arguments();
   DCHECK_EQ(3, args->length());
 
-  SuperReference* super_reference = args->at(0)->AsSuperReference();
+  SuperCallReference* super_call_ref = args->at(0)->AsSuperCallReference();
+  DCHECK_NOT_NULL(super_call_ref);
 
   // Load ReflectConstruct function
   EmitLoadJSRuntimeFunction(call);
@@ -4647,8 +4672,8 @@ void FullCodeGenerator::EmitCallSuperWithSpread(CallRuntime* expr) {
   __ push(at);
   __ sw(v0, MemOperand(sp, kPointerSize));
 
-  // Push super
-  EmitLoadSuperConstructor();
+  // Push super constructor
+  EmitLoadSuperConstructor(super_call_ref);
   __ Push(result_register());
 
   // Push arguments array
@@ -4665,7 +4690,7 @@ void FullCodeGenerator::EmitCallSuperWithSpread(CallRuntime* expr) {
   context()->DropAndPlug(1, v0);
 
   // TODO(mvstanton): with FLAG_vector_stores this needs a slot id.
-  EmitInitializeThisAfterSuper(super_reference);
+  EmitInitializeThisAfterSuper(super_call_ref);
 }
 
 
@@ -4890,9 +4915,9 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
       }
 
       case NAMED_SUPER_PROPERTY: {
-        VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
+        VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
         VisitForAccumulatorValue(
-            prop->obj()->AsSuperReference()->home_object_var());
+            prop->obj()->AsSuperPropertyReference()->home_object_var());
         __ Push(result_register());
         const Register scratch = a1;
         __ lw(scratch, MemOperand(sp, kPointerSize));
@@ -4902,9 +4927,9 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
       }
 
       case KEYED_SUPER_PROPERTY: {
-        VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
+        VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
         VisitForAccumulatorValue(
-            prop->obj()->AsSuperReference()->home_object_var());
+            prop->obj()->AsSuperPropertyReference()->home_object_var());
         const Register scratch = a1;
         const Register scratch1 = t0;
         __ Move(scratch, result_register());
index 9cd93eeaa1bc1e202c7d86b7532e047f37d3aa96..ef0590036e4299416a0e35bd2f3fa18b427c0df5 100644 (file)
@@ -253,6 +253,24 @@ void FullCodeGenerator::Generate() {
     __ Push(a1);
   }
 
+  // Possibly set up a local binding to the this function which is used in
+  // derived constructors with super calls.
+  Variable* this_function_var = scope()->this_function_var();
+  if (this_function_var != nullptr) {
+    Comment cmnt(masm_, "[ This function");
+    SetVar(this_function_var, a1, a2, a3);
+  }
+
+  Variable* new_target_var = scope()->new_target_var();
+  if (new_target_var != nullptr) {
+    Comment cmnt(masm_, "[ new.target");
+    // new.target is parameter -2.
+    int offset = 2 * kPointerSize +
+                 (info_->scope()->num_parameters() + 1) * kPointerSize;
+    __ lw(v0, MemOperand(fp, offset));
+    SetVar(new_target_var, v0, a2, a3);
+  }
+
   ArgumentsAccessStub::HasNewTarget has_new_target =
       IsSubclassConstructor(info->function()->kind())
           ? ArgumentsAccessStub::HAS_NEW_TARGET
@@ -1987,9 +2005,10 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
       }
       break;
     case NAMED_SUPER_PROPERTY:
-      VisitForStackValue(property->obj()->AsSuperReference()->this_var());
+      VisitForStackValue(
+          property->obj()->AsSuperPropertyReference()->this_var());
       VisitForAccumulatorValue(
-          property->obj()->AsSuperReference()->home_object_var());
+          property->obj()->AsSuperPropertyReference()->home_object_var());
       __ Push(result_register());
       if (expr->is_compound()) {
         const Register scratch = a1;
@@ -1999,9 +2018,10 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
       break;
     case KEYED_SUPER_PROPERTY: {
       const Register scratch = a1;
-      VisitForStackValue(property->obj()->AsSuperReference()->this_var());
+      VisitForStackValue(
+          property->obj()->AsSuperPropertyReference()->this_var());
       VisitForAccumulatorValue(
-          property->obj()->AsSuperReference()->home_object_var());
+          property->obj()->AsSuperPropertyReference()->home_object_var());
       __ Move(scratch, result_register());
       VisitForAccumulatorValue(property->key());
       __ Push(scratch, result_register());
@@ -2635,9 +2655,9 @@ void FullCodeGenerator::EmitAssignment(Expression* expr,
     }
     case NAMED_SUPER_PROPERTY: {
       __ Push(v0);
-      VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
+      VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
       VisitForAccumulatorValue(
-          prop->obj()->AsSuperReference()->home_object_var());
+          prop->obj()->AsSuperPropertyReference()->home_object_var());
       // stack: value, this; v0: home_object
       Register scratch = a2;
       Register scratch2 = a3;
@@ -2652,8 +2672,9 @@ void FullCodeGenerator::EmitAssignment(Expression* expr,
     }
     case KEYED_SUPER_PROPERTY: {
       __ Push(v0);
-      VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
-      VisitForStackValue(prop->obj()->AsSuperReference()->home_object_var());
+      VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
+      VisitForStackValue(
+          prop->obj()->AsSuperPropertyReference()->home_object_var());
       VisitForAccumulatorValue(prop->key());
       Register scratch = a2;
       Register scratch2 = a3;
@@ -2886,8 +2907,9 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
       __ Move(LoadDescriptor::ReceiverRegister(), v0);
       EmitNamedPropertyLoad(expr);
     } else {
-      VisitForStackValue(expr->obj()->AsSuperReference()->this_var());
-      VisitForStackValue(expr->obj()->AsSuperReference()->home_object_var());
+      VisitForStackValue(expr->obj()->AsSuperPropertyReference()->this_var());
+      VisitForStackValue(
+          expr->obj()->AsSuperPropertyReference()->home_object_var());
       EmitNamedSuperPropertyLoad(expr);
     }
   } else {
@@ -2898,8 +2920,9 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
       __ pop(LoadDescriptor::ReceiverRegister());
       EmitKeyedPropertyLoad(expr);
     } else {
-      VisitForStackValue(expr->obj()->AsSuperReference()->this_var());
-      VisitForStackValue(expr->obj()->AsSuperReference()->home_object_var());
+      VisitForStackValue(expr->obj()->AsSuperPropertyReference()->this_var());
+      VisitForStackValue(
+          expr->obj()->AsSuperPropertyReference()->home_object_var());
       VisitForStackValue(expr->key());
       EmitKeyedSuperPropertyLoad(expr);
     }
@@ -2961,7 +2984,7 @@ void FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) {
   DCHECK(!key->value()->IsSmi());
   // Load the function from the receiver.
   const Register scratch = a1;
-  SuperReference* super_ref = prop->obj()->AsSuperReference();
+  SuperPropertyReference* super_ref = prop->obj()->AsSuperPropertyReference();
   VisitForAccumulatorValue(super_ref->home_object_var());
   __ mov(scratch, v0);
   VisitForAccumulatorValue(super_ref->this_var());
@@ -3019,7 +3042,7 @@ void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) {
   SetSourcePosition(prop->position());
   // Load the function from the receiver.
   const Register scratch = a1;
-  SuperReference* super_ref = prop->obj()->AsSuperReference();
+  SuperPropertyReference* super_ref = prop->obj()->AsSuperPropertyReference();
   VisitForAccumulatorValue(super_ref->home_object_var());
   __ Move(scratch, v0);
   VisitForAccumulatorValue(super_ref->this_var());
@@ -3098,15 +3121,8 @@ void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
 }
 
 
-void FullCodeGenerator::EmitLoadSuperConstructor() {
-  __ ld(a0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
-  __ Push(a0);
-  __ CallRuntime(Runtime::kGetPrototype, 1);
-}
-
-
 void FullCodeGenerator::EmitInitializeThisAfterSuper(
-    SuperReference* super_ref, FeedbackVectorICSlot slot) {
+    SuperCallReference* super_ref, FeedbackVectorICSlot slot) {
   Variable* this_var = super_ref->this_var()->var();
   GetVar(a1, this_var);
   __ LoadRoot(at, Heap::kTheHoleValueRootIndex);
@@ -3264,7 +3280,7 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) {
   // Push constructor on the stack.  If it's not a function it's used as
   // receiver for CALL_NON_FUNCTION, otherwise the value on the stack is
   // ignored.
-  DCHECK(!expr->expression()->IsSuperReference());
+  DCHECK(!expr->expression()->IsSuperPropertyReference());
   VisitForStackValue(expr->expression());
 
   // Push the arguments ("left-to-right") on the stack.
@@ -3300,11 +3316,14 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) {
 
 
 void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) {
-  Variable* new_target_var = scope()->DeclarationScope()->new_target_var();
-  GetVar(result_register(), new_target_var);
-  __ Push(result_register());
+  SuperCallReference* super_call_ref =
+      expr->expression()->AsSuperCallReference();
+  DCHECK_NOT_NULL(super_call_ref);
+
+  VariableProxy* new_target_proxy = super_call_ref->new_target_var();
+  VisitForStackValue(new_target_proxy);
 
-  EmitLoadSuperConstructor();
+  EmitLoadSuperConstructor(super_call_ref);
   __ push(result_register());
 
   // Push the arguments ("left-to-right") on the stack.
@@ -3342,8 +3361,7 @@ void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) {
 
   RecordJSReturnSite(expr);
 
-  EmitInitializeThisAfterSuper(expr->expression()->AsSuperReference(),
-                               expr->CallFeedbackICSlot());
+  EmitInitializeThisAfterSuper(super_call_ref, expr->CallFeedbackICSlot());
   context()->Plug(v0);
 }
 
@@ -4231,11 +4249,15 @@ void FullCodeGenerator::EmitCallFunction(CallRuntime* expr) {
 
 
 void FullCodeGenerator::EmitDefaultConstructorCallSuper(CallRuntime* expr) {
-  Variable* new_target_var = scope()->DeclarationScope()->new_target_var();
-  GetVar(result_register(), new_target_var);
-  __ Push(result_register());
+  ZoneList<Expression*>* args = expr->arguments();
+  DCHECK(args->length() == 2);
 
-  EmitLoadSuperConstructor();
+  // new.target
+  VisitForStackValue(args->at(0));
+
+  // .this_function
+  VisitForStackValue(args->at(1));
+  __ CallRuntime(Runtime::kGetPrototype, 1);
   __ Push(result_register());
 
   // Check if the calling frame is an arguments adaptor frame.
@@ -4637,11 +4659,14 @@ void FullCodeGenerator::EmitDebugIsActive(CallRuntime* expr) {
 
 void FullCodeGenerator::EmitCallSuperWithSpread(CallRuntime* expr) {
   // Assert: expr === CallRuntime("ReflectConstruct")
+  DCHECK_EQ(1, expr->arguments()->length());
   CallRuntime* call = expr->arguments()->at(0)->AsCallRuntime();
+
   ZoneList<Expression*>* args = call->arguments();
   DCHECK_EQ(3, args->length());
 
-  SuperReference* super_reference = args->at(0)->AsSuperReference();
+  SuperCallReference* super_call_ref = args->at(0)->AsSuperCallReference();
+  DCHECK_NOT_NULL(super_call_ref);
 
   // Load ReflectConstruct function
   EmitLoadJSRuntimeFunction(call);
@@ -4651,8 +4676,8 @@ void FullCodeGenerator::EmitCallSuperWithSpread(CallRuntime* expr) {
   __ push(at);
   __ sd(v0, MemOperand(sp, kPointerSize));
 
-  // Push super
-  EmitLoadSuperConstructor();
+  // Push super constructor
+  EmitLoadSuperConstructor(super_call_ref);
   __ Push(result_register());
 
   // Push arguments array
@@ -4669,7 +4694,7 @@ void FullCodeGenerator::EmitCallSuperWithSpread(CallRuntime* expr) {
   context()->DropAndPlug(1, v0);
 
   // TODO(mvstanton): with FLAG_vector_stores this needs a slot id.
-  EmitInitializeThisAfterSuper(super_reference);
+  EmitInitializeThisAfterSuper(super_call_ref);
 }
 
 
@@ -4893,9 +4918,9 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
       }
 
       case NAMED_SUPER_PROPERTY: {
-        VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
+        VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
         VisitForAccumulatorValue(
-            prop->obj()->AsSuperReference()->home_object_var());
+            prop->obj()->AsSuperPropertyReference()->home_object_var());
         __ Push(result_register());
         const Register scratch = a1;
         __ ld(scratch, MemOperand(sp, kPointerSize));
@@ -4905,9 +4930,9 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
       }
 
       case KEYED_SUPER_PROPERTY: {
-        VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
+        VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
         VisitForAccumulatorValue(
-            prop->obj()->AsSuperReference()->home_object_var());
+            prop->obj()->AsSuperPropertyReference()->home_object_var());
         const Register scratch = a1;
         const Register scratch1 = a4;
         __ Move(scratch, result_register());
index ff2c446772c8b27c8fade277f217552c21349108..383f96c8faf98609a165086a58954ddc04e454b8 100644 (file)
@@ -359,8 +359,17 @@ FunctionLiteral* Parser::DefaultConstructor(bool call_super, Scope* scope,
     body = new (zone()) ZoneList<Statement*>(call_super ? 2 : 1, zone());
     AddAssertIsConstruct(body, pos);
     if (call_super) {
+      // %_DefaultConstructorCallSuper(new.target, .this_function)
       ZoneList<Expression*>* args =
-          new (zone()) ZoneList<Expression*>(0, zone());
+          new (zone()) ZoneList<Expression*>(2, zone());
+      VariableProxy* new_target_proxy = scope_->NewUnresolved(
+          factory(), ast_value_factory()->new_target_string(), Variable::NORMAL,
+          pos);
+      args->Add(new_target_proxy, zone());
+      VariableProxy* this_function_proxy = scope_->NewUnresolved(
+          factory(), ast_value_factory()->this_function_string(),
+          Variable::NORMAL, pos);
+      args->Add(this_function_proxy, zone());
       CallRuntime* call = factory()->NewCallRuntime(
           ast_value_factory()->empty_string(),
           Runtime::FunctionForId(Runtime::kInlineDefaultConstructorCallSuper),
@@ -747,19 +756,32 @@ Expression* ParserTraits::ThisExpression(Scope* scope, AstNodeFactory* factory,
                               Variable::THIS, pos, pos + 4);
 }
 
-Expression* ParserTraits::SuperReference(Scope* scope, AstNodeFactory* factory,
-                                         int pos) {
-  // TODO(arv): Split into SuperProperty and SuperCall?
+Expression* ParserTraits::SuperPropertyReference(Scope* scope,
+                                                 AstNodeFactory* factory,
+                                                 int pos) {
   VariableProxy* home_object_proxy = scope->NewUnresolved(
       factory, parser_->ast_value_factory()->home_object_string(),
       Variable::NORMAL, pos);
-
-  return factory->NewSuperReference(
+  return factory->NewSuperPropertyReference(
       ThisExpression(scope, factory, pos)->AsVariableProxy(), home_object_proxy,
       pos);
 }
 
 
+Expression* ParserTraits::SuperCallReference(Scope* scope,
+                                             AstNodeFactory* factory, int pos) {
+  VariableProxy* new_target_proxy = scope->NewUnresolved(
+      factory, parser_->ast_value_factory()->new_target_string(),
+      Variable::NORMAL, pos);
+  VariableProxy* this_function_proxy = scope->NewUnresolved(
+      factory, parser_->ast_value_factory()->this_function_string(),
+      Variable::NORMAL, pos);
+  return factory->NewSuperCallReference(
+      ThisExpression(scope, factory, pos)->AsVariableProxy(), new_target_proxy,
+      this_function_proxy, pos);
+}
+
+
 Expression* ParserTraits::DefaultConstructor(bool call_super, Scope* scope,
                                              int pos, int end_pos) {
   return parser_->DefaultConstructor(call_super, scope, pos, end_pos);
@@ -5744,13 +5766,14 @@ ZoneList<v8::internal::Expression*>* Parser::PrepareSpreadArguments(
 Expression* Parser::SpreadCall(Expression* function,
                                ZoneList<v8::internal::Expression*>* args,
                                int pos) {
-  if (function->IsSuperReference()) {
+  if (function->IsSuperCallReference()) {
     // Super calls
+    // %_CallSuperWithSpread(%ReflectConstruct(<super>, args, new.target))
     args->InsertAt(0, function, zone());
-    args->Add(factory()->NewVariableProxy(scope_->new_target_var()), zone());
+    args->Add(function->AsSuperCallReference()->new_target_var(), zone());
     Expression* result = factory()->NewCallRuntime(
         ast_value_factory()->reflect_construct_string(), NULL, args, pos);
-    args = new (zone()) ZoneList<Expression*>(0, zone());
+    args = new (zone()) ZoneList<Expression*>(1, zone());
     args->Add(result, zone());
     return factory()->NewCallRuntime(
         ast_value_factory()->empty_string(),
index eba677c94bb945da45e6f2b4f3fbc3fbbc3e2845..9080160c7590f21cce5a7ac3e619e86b60d383f0 100644 (file)
@@ -724,7 +724,10 @@ class ParserTraits {
 
   Expression* ThisExpression(Scope* scope, AstNodeFactory* factory,
                              int pos = RelocInfo::kNoPosition);
-  Expression* SuperReference(Scope* scope, AstNodeFactory* factory, int pos);
+  Expression* SuperPropertyReference(Scope* scope, AstNodeFactory* factory,
+                                     int pos);
+  Expression* SuperCallReference(Scope* scope, AstNodeFactory* factory,
+                                 int pos);
   Expression* DefaultConstructor(bool call_super, Scope* scope, int pos,
                                  int end_pos);
   Literal* ExpressionFromLiteral(Token::Value token, int pos, Scanner* scanner,
index 7be3ff8446c9db7a02c1b9a01eefb75c915ca779..a487a10c3597fc51155827b2bacc2a37c050b4a7 100644 (file)
@@ -404,7 +404,8 @@ NOT_A_PATTERN(NativeFunctionLiteral)
 NOT_A_PATTERN(Property)
 NOT_A_PATTERN(RegExpLiteral)
 NOT_A_PATTERN(ReturnStatement)
-NOT_A_PATTERN(SuperReference)
+NOT_A_PATTERN(SuperPropertyReference)
+NOT_A_PATTERN(SuperCallReference)
 NOT_A_PATTERN(SwitchStatement)
 NOT_A_PATTERN(ThisFunction)
 NOT_A_PATTERN(Throw)
index 2fe5db1d08e9e0f1b63d68c69950ca29ae31371a..34295c71f297bce5cdca1fc81aa80252298304e5 100644 (file)
@@ -1715,9 +1715,15 @@ class PreParserTraits {
     return PreParserExpression::This();
   }
 
-  static PreParserExpression SuperReference(Scope* scope,
-                                            PreParserFactory* factory,
-                                            int pos) {
+  static PreParserExpression SuperPropertyReference(Scope* scope,
+                                                    PreParserFactory* factory,
+                                                    int pos) {
+    return PreParserExpression::Default();
+  }
+
+  static PreParserExpression SuperCallReference(Scope* scope,
+                                                PreParserFactory* factory,
+                                                int pos) {
     return PreParserExpression::Default();
   }
 
@@ -3515,7 +3521,7 @@ ParserBase<Traits>::ParseStrongSuperCallExpression(
   Consume(Token::SUPER);
   int pos = position();
   Scanner::Location super_loc = scanner()->location();
-  ExpressionT expr = this->SuperReference(scope_, factory(), pos);
+  ExpressionT expr = this->SuperCallReference(scope_, factory(), pos);
 
   if (peek() != Token::LPAREN) {
     ReportMessage(MessageTemplate::kStrongConstructorSuper);
@@ -3580,7 +3586,7 @@ ParserBase<Traits>::ParseSuperExpression(bool is_new,
       i::IsConstructor(kind)) {
     if (peek() == Token::PERIOD || peek() == Token::LBRACK) {
       scope->RecordSuperPropertyUsage();
-      return this->SuperReference(scope_, factory(), pos);
+      return this->SuperPropertyReference(scope_, factory(), pos);
     }
     // new super() is never allowed.
     // super() is only allowed in derived constructor
@@ -3595,7 +3601,7 @@ ParserBase<Traits>::ParseSuperExpression(bool is_new,
       // TODO(rossberg): This might not be the correct FunctionState for the
       // method here.
       function_state_->set_super_location(scanner()->location());
-      return this->SuperReference(scope_, factory(), pos);
+      return this->SuperCallReference(scope_, factory(), pos);
     }
   }
 
index aa331dadb2c28c96d16b2ea5a957b1bab01288fd..284beadfeedb5a7dc64472a6372a4091e6a42eff 100644 (file)
@@ -364,7 +364,10 @@ void CallPrinter::VisitSpread(Spread* node) {
 void CallPrinter::VisitThisFunction(ThisFunction* node) {}
 
 
-void CallPrinter::VisitSuperReference(SuperReference* node) {}
+void CallPrinter::VisitSuperPropertyReference(SuperPropertyReference* node) {}
+
+
+void CallPrinter::VisitSuperCallReference(SuperCallReference* node) {}
 
 
 void CallPrinter::FindStatements(ZoneList<Statement*>* statements) {
@@ -835,8 +838,13 @@ void PrettyPrinter::VisitThisFunction(ThisFunction* node) {
 }
 
 
-void PrettyPrinter::VisitSuperReference(SuperReference* node) {
-  Print("<super-reference>");
+void PrettyPrinter::VisitSuperPropertyReference(SuperPropertyReference* node) {
+  Print("<super-property-reference>");
+}
+
+
+void PrettyPrinter::VisitSuperCallReference(SuperCallReference* node) {
+  Print("<super-call-reference>");
 }
 
 
@@ -1527,10 +1535,16 @@ void AstPrinter::VisitThisFunction(ThisFunction* node) {
 }
 
 
-void AstPrinter::VisitSuperReference(SuperReference* node) {
-  IndentedScope indent(this, "SUPER-REFERENCE");
+void AstPrinter::VisitSuperPropertyReference(SuperPropertyReference* node) {
+  IndentedScope indent(this, "SUPER-PROPERTY-REFERENCE");
 }
 
+
+void AstPrinter::VisitSuperCallReference(SuperCallReference* node) {
+  IndentedScope indent(this, "SUPER-CALL-REFERENCE");
+}
+
+
 #endif  // DEBUG
 
 }  // namespace internal
index d8d63ceb7b2258065c3db4ccc5fcb33317ab350a..bf72469827938844941b8adf52412022474b662a 100644 (file)
@@ -72,8 +72,8 @@ namespace internal {
   F(StoreKeyedToSuper_Strict, 4, 1)           \
   F(StoreKeyedToSuper_Sloppy, 4, 1)           \
   F(HandleStepInForDerivedConstructors, 1, 1) \
-  F(DefaultConstructorCallSuper, 0, 1)        \
-  F(CallSuperWithSpread, 0, 1)
+  F(DefaultConstructorCallSuper, 2, 1)        \
+  F(CallSuperWithSpread, 1, 1)
 
 
 #define FOR_EACH_INTRINSIC_COLLECTIONS(F) \
index 3d5220438cdfd8c7b086066e0de666651bde7cd2..9db5745160c1cff2f859936780744b83c8bac44a 100644 (file)
@@ -160,6 +160,7 @@ void Scope::SetDefaults(ScopeType scope_type, Scope* outer_scope,
   function_ = nullptr;
   arguments_ = nullptr;
   home_object_ = nullptr;
+  this_function_ = nullptr;
   illegal_redecl_ = nullptr;
   scope_inside_with_ = false;
   scope_contains_with_ = false;
@@ -308,45 +309,44 @@ void Scope::Initialize() {
   }
 
   // Declare convenience variables and the receiver.
-  if (is_declaration_scope()) {
-    DCHECK(!subclass_constructor || is_function_scope());
-    if (has_this_declaration()) {
-      Variable* var = variables_.Declare(
-          this, ast_value_factory_->this_string(),
-          subclass_constructor ? CONST : VAR, Variable::THIS,
-          subclass_constructor ? kNeedsInitialization : kCreatedInitialized);
-      receiver_ = var;
+  if (is_declaration_scope() && has_this_declaration()) {
+    Variable* var = variables_.Declare(
+        this, ast_value_factory_->this_string(),
+        subclass_constructor ? CONST : VAR, Variable::THIS,
+        subclass_constructor ? kNeedsInitialization : kCreatedInitialized);
+    receiver_ = var;
+  }
+
+  if (is_function_scope()) {
+    if (!is_arrow_scope()) {
+      // Declare 'arguments' variable which exists in all non arrow functions.
+      // Note that it might never be accessed, in which case it won't be
+      // allocated during variable allocation.
+      variables_.Declare(this, ast_value_factory_->arguments_string(), VAR,
+                         Variable::ARGUMENTS, kCreatedInitialized);
     }
 
     if (subclass_constructor) {
-      new_target_ =
-          variables_.Declare(this, ast_value_factory_->new_target_string(),
-                             CONST, Variable::NEW_TARGET, kCreatedInitialized);
-      new_target_->AllocateTo(Variable::PARAMETER, -2);
-      new_target_->set_is_used();
+      DCHECK(!is_arrow_scope());
+      variables_.Declare(this, ast_value_factory_->new_target_string(), CONST,
+                         Variable::NORMAL, kCreatedInitialized);
     }
-  }
 
-  if (is_function_scope() && !is_arrow_scope()) {
-    // Declare 'arguments' variable which exists in all non arrow functions.
-    // Note that it might never be accessed, in which case it won't be
-    // allocated during variable allocation.
-    variables_.Declare(this,
-                       ast_value_factory_->arguments_string(),
-                       VAR,
-                       Variable::ARGUMENTS,
-                       kCreatedInitialized);
-  }
+    if (IsConciseMethod(function_kind_) || IsConstructor(function_kind_) ||
+        IsAccessorFunction(function_kind_)) {
+      DCHECK(!is_arrow_scope());
+      // Declare '.home_object' variable which exists in all methods.
+      // Note that it might never be accessed, in which case it won't be
+      // allocated during variable allocation.
+      variables_.Declare(this, ast_value_factory_->home_object_string(), CONST,
+                         Variable::NORMAL, kCreatedInitialized);
+    }
 
-  if (is_function_scope() &&
-      (IsConciseMethod(function_kind_) || IsConstructor(function_kind_) ||
-       IsAccessorFunction(function_kind_))) {
-    DCHECK(!is_arrow_scope());
-    // Declare '.home_object' variable which exists in all methods.
-    // Note that it might never be accessed, in which case it won't be
-    // allocated during variable allocation.
-    variables_.Declare(this, ast_value_factory_->home_object_string(), VAR,
-                       Variable::NORMAL, kCreatedInitialized);
+    if (IsSubclassConstructor(function_kind_)) {
+      DCHECK(!is_arrow_scope());
+      variables_.Declare(this, ast_value_factory_->this_function_string(),
+                         CONST, Variable::NORMAL, kCreatedInitialized);
+    }
   }
 }
 
@@ -1311,7 +1311,7 @@ bool Scope::MustAllocate(Variable* var) {
   // Give var a read/write use if there is a chance it might be accessed
   // via an eval() call.  This is only possible if the variable has a
   // visible name.
-  if ((var->is_this() || var->is_new_target() || !var->raw_name()->IsEmpty()) &&
+  if ((var->is_this() || !var->raw_name()->IsEmpty()) &&
       (var->has_forced_context_allocation() || scope_calls_eval_ ||
        inner_scope_calls_eval_ || scope_contains_with_ || is_catch_scope() ||
        is_block_scope() || is_module_scope() || is_script_scope())) {
@@ -1403,18 +1403,6 @@ void Scope::AllocateParameterLocals(Isolate* isolate) {
     rest_parameter_ = NULL;
   }
 
-  Variable* home_object_var =
-      LookupLocal(ast_value_factory_->home_object_string());
-  if (home_object_var != nullptr && uses_super_property() &&
-      MustAllocate(home_object_var)) {
-    // TODO(arv): super() uses a SuperReference so it generates a VariableProxy
-    // for the .home_object which makes it look like we need to allocate the
-    // home_object_var.
-    // Consider splitting the AST node into 2 different nodes since the
-    // semantics is just so different.
-    home_object_ = home_object_var;
-  }
-
   // The same parameter may occur multiple times in the parameters_ list.
   // If it does, and if it is not copied into the context object, it must
   // receive the highest parameter index for that parameter; thus iteration
@@ -1503,13 +1491,31 @@ void Scope::AllocateNonParameterLocals(Isolate* isolate) {
   // allocated in the context, it must be the last slot in the context,
   // because of the current ScopeInfo implementation (see
   // ScopeInfo::ScopeInfo(FunctionScope* scope) constructor).
-  if (function_ != NULL) {
+  if (function_ != nullptr) {
     AllocateNonParameterLocal(isolate, function_->proxy()->var());
   }
 
-  if (rest_parameter_) {
+  if (rest_parameter_ != nullptr) {
     AllocateNonParameterLocal(isolate, rest_parameter_);
   }
+
+  Variable* home_object_var =
+      LookupLocal(ast_value_factory_->home_object_string());
+  if (home_object_var != nullptr && MustAllocate(home_object_var)) {
+    home_object_ = home_object_var;
+  }
+
+  Variable* new_target_var =
+      LookupLocal(ast_value_factory_->new_target_string());
+  if (new_target_var != nullptr && MustAllocate(new_target_var)) {
+    new_target_ = new_target_var;
+  }
+
+  Variable* this_function_var =
+      LookupLocal(ast_value_factory_->this_function_string());
+  if (this_function_var != nullptr && MustAllocate(this_function_var)) {
+    this_function_ = this_function_var;
+  }
 }
 
 
index d56018532152909538635d95cdb50286ddfc0d34..63cd13d47c175ce5b934825df1d2ccb4163ea0ea 100644 (file)
@@ -419,6 +419,13 @@ class Scope: public ZoneObject {
     return home_object_;
   }
 
+  Variable* this_function_var() const {
+    // This is only used in derived constructors atm.
+    DCHECK(this_function_ == nullptr ||
+           (is_function_scope() && IsSubclassConstructor(function_kind())));
+    return this_function_;
+  }
+
   // Declarations list.
   ZoneList<Declaration*>* declarations() { return &decls_; }
 
@@ -579,6 +586,8 @@ class Scope: public ZoneObject {
   Variable* arguments_;
   // Convenience variable; method scopes only.
   Variable* home_object_;
+  // Convenience variable; Subclass constructor only
+  Variable* this_function_;
   // Module descriptor; module scopes only.
   ModuleDescriptor* module_descriptor_;
 
index 85790097f1da4be99e25c0b48a09bd7cb2ae03db..0d8ed525a18a3c6ceff0639a9a0bffcd596e7e9d 100644 (file)
@@ -761,7 +761,10 @@ void AstTyper::VisitThisFunction(ThisFunction* expr) {
 }
 
 
-void AstTyper::VisitSuperReference(SuperReference* expr) {}
+void AstTyper::VisitSuperPropertyReference(SuperPropertyReference* expr) {}
+
+
+void AstTyper::VisitSuperCallReference(SuperCallReference* expr) {}
 
 
 void AstTyper::VisitDeclarations(ZoneList<Declaration*>* decls) {
index 384a8859545045ac502c5f80cc7a8229ddd81d75..0cb50c87e985580c1fd1c7fc5ea9b3fde63f4206 100644 (file)
@@ -20,7 +20,7 @@ class ClassVariable;
 
 class Variable: public ZoneObject {
  public:
-  enum Kind { NORMAL, FUNCTION, CLASS, THIS, NEW_TARGET, ARGUMENTS };
+  enum Kind { NORMAL, FUNCTION, CLASS, THIS, ARGUMENTS };
 
   enum Location {
     // Before and during variable allocation, a variable whose location is
@@ -103,7 +103,6 @@ class Variable: public ZoneObject {
   bool is_function() const { return kind_ == FUNCTION; }
   bool is_class() const { return kind_ == CLASS; }
   bool is_this() const { return kind_ == THIS; }
-  bool is_new_target() const { return kind_ == NEW_TARGET; }
   bool is_arguments() const { return kind_ == ARGUMENTS; }
 
   ClassVariable* AsClassVariable() {
index 1306b2353f3d541912efa78c670dd8e1993f80dc..e1f747a730334015b7f07b45f0431b1e8039eab8 100644 (file)
@@ -239,6 +239,24 @@ void FullCodeGenerator::Generate() {
     __ Push(rdi);
   }
 
+  // Possibly set up a local binding to the this function which is used in
+  // derived constructors with super calls.
+  Variable* this_function_var = scope()->this_function_var();
+  if (this_function_var != nullptr) {
+    Comment cmnt(masm_, "[ This function");
+    SetVar(this_function_var, rdi, rbx, rdx);
+  }
+
+  Variable* new_target_var = scope()->new_target_var();
+  if (new_target_var != nullptr) {
+    Comment cmnt(masm_, "[ new.target");
+    // new.target is parameter -2.
+    int offset = 2 * kPointerSize + kFPOnStackSize + kPCOnStackSize +
+                 (info_->scope()->num_parameters() - 1) * kPointerSize;
+    __ movp(rax, Operand(rbp, offset));
+    SetVar(new_target_var, rax, rbx, rdx);
+  }
+
   ArgumentsAccessStub::HasNewTarget has_new_target =
       IsSubclassConstructor(info->function()->kind())
           ? ArgumentsAccessStub::HAS_NEW_TARGET
@@ -1959,9 +1977,10 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
       }
       break;
     case NAMED_SUPER_PROPERTY:
-      VisitForStackValue(property->obj()->AsSuperReference()->this_var());
+      VisitForStackValue(
+          property->obj()->AsSuperPropertyReference()->this_var());
       VisitForAccumulatorValue(
-          property->obj()->AsSuperReference()->home_object_var());
+          property->obj()->AsSuperPropertyReference()->home_object_var());
       __ Push(result_register());
       if (expr->is_compound()) {
         __ Push(MemOperand(rsp, kPointerSize));
@@ -1969,9 +1988,10 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
       }
       break;
     case KEYED_SUPER_PROPERTY:
-      VisitForStackValue(property->obj()->AsSuperReference()->this_var());
       VisitForStackValue(
-          property->obj()->AsSuperReference()->home_object_var());
+          property->obj()->AsSuperPropertyReference()->this_var());
+      VisitForStackValue(
+          property->obj()->AsSuperPropertyReference()->home_object_var());
       VisitForAccumulatorValue(property->key());
       __ Push(result_register());
       if (expr->is_compound()) {
@@ -2563,9 +2583,9 @@ void FullCodeGenerator::EmitAssignment(Expression* expr,
     }
     case NAMED_SUPER_PROPERTY: {
       __ Push(rax);
-      VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
+      VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
       VisitForAccumulatorValue(
-          prop->obj()->AsSuperReference()->home_object_var());
+          prop->obj()->AsSuperPropertyReference()->home_object_var());
       // stack: value, this; rax: home_object
       Register scratch = rcx;
       Register scratch2 = rdx;
@@ -2580,8 +2600,9 @@ void FullCodeGenerator::EmitAssignment(Expression* expr,
     }
     case KEYED_SUPER_PROPERTY: {
       __ Push(rax);
-      VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
-      VisitForStackValue(prop->obj()->AsSuperReference()->home_object_var());
+      VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
+      VisitForStackValue(
+          prop->obj()->AsSuperPropertyReference()->home_object_var());
       VisitForAccumulatorValue(prop->key());
       Register scratch = rcx;
       Register scratch2 = rdx;
@@ -2800,8 +2821,9 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
       __ movp(LoadDescriptor::ReceiverRegister(), rax);
       EmitNamedPropertyLoad(expr);
     } else {
-      VisitForStackValue(expr->obj()->AsSuperReference()->this_var());
-      VisitForStackValue(expr->obj()->AsSuperReference()->home_object_var());
+      VisitForStackValue(expr->obj()->AsSuperPropertyReference()->this_var());
+      VisitForStackValue(
+          expr->obj()->AsSuperPropertyReference()->home_object_var());
       EmitNamedSuperPropertyLoad(expr);
     }
   } else {
@@ -2812,8 +2834,9 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
       __ Pop(LoadDescriptor::ReceiverRegister());
       EmitKeyedPropertyLoad(expr);
     } else {
-      VisitForStackValue(expr->obj()->AsSuperReference()->this_var());
-      VisitForStackValue(expr->obj()->AsSuperReference()->home_object_var());
+      VisitForStackValue(expr->obj()->AsSuperPropertyReference()->this_var());
+      VisitForStackValue(
+          expr->obj()->AsSuperPropertyReference()->home_object_var());
       VisitForStackValue(expr->key());
       EmitKeyedSuperPropertyLoad(expr);
     }
@@ -2871,7 +2894,7 @@ void FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) {
   Literal* key = prop->key()->AsLiteral();
   DCHECK(!key->value()->IsSmi());
   // Load the function from the receiver.
-  SuperReference* super_ref = prop->obj()->AsSuperReference();
+  SuperPropertyReference* super_ref = prop->obj()->AsSuperPropertyReference();
   VisitForStackValue(super_ref->home_object_var());
   VisitForAccumulatorValue(super_ref->this_var());
   __ Push(rax);
@@ -2928,7 +2951,7 @@ void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) {
 
   SetSourcePosition(prop->position());
   // Load the function from the receiver.
-  SuperReference* super_ref = prop->obj()->AsSuperReference();
+  SuperPropertyReference* super_ref = prop->obj()->AsSuperPropertyReference();
   VisitForStackValue(super_ref->home_object_var());
   VisitForAccumulatorValue(super_ref->this_var());
   __ Push(rax);
@@ -3009,14 +3032,8 @@ void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
 }
 
 
-void FullCodeGenerator::EmitLoadSuperConstructor() {
-  __ Push(Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
-  __ CallRuntime(Runtime::kGetPrototype, 1);
-}
-
-
 void FullCodeGenerator::EmitInitializeThisAfterSuper(
-    SuperReference* super_ref, FeedbackVectorICSlot slot) {
+    SuperCallReference* super_ref, FeedbackVectorICSlot slot) {
   Variable* this_var = super_ref->this_var()->var();
   GetVar(rcx, this_var);
   __ CompareRoot(rcx, Heap::kTheHoleValueRootIndex);
@@ -3166,7 +3183,7 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) {
   // Push constructor on the stack.  If it's not a function it's used as
   // receiver for CALL_NON_FUNCTION, otherwise the value on the stack is
   // ignored.
-  DCHECK(!expr->expression()->IsSuperReference());
+  DCHECK(!expr->expression()->IsSuperPropertyReference());
   VisitForStackValue(expr->expression());
 
   // Push the arguments ("left-to-right") on the stack.
@@ -3202,11 +3219,14 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) {
 
 
 void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) {
-  Variable* new_target_var = scope()->DeclarationScope()->new_target_var();
-  GetVar(result_register(), new_target_var);
-  __ Push(result_register());
+  SuperCallReference* super_call_ref =
+      expr->expression()->AsSuperCallReference();
+  DCHECK_NOT_NULL(super_call_ref);
 
-  EmitLoadSuperConstructor();
+  VariableProxy* new_target_proxy = super_call_ref->new_target_var();
+  VisitForStackValue(new_target_proxy);
+
+  EmitLoadSuperConstructor(super_call_ref);
   __ Push(result_register());
 
   // Push the arguments ("left-to-right") on the stack.
@@ -3244,8 +3264,7 @@ void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) {
 
   RecordJSReturnSite(expr);
 
-  EmitInitializeThisAfterSuper(expr->expression()->AsSuperReference(),
-                               expr->CallFeedbackICSlot());
+  EmitInitializeThisAfterSuper(super_call_ref, expr->CallFeedbackICSlot());
   context()->Plug(rax);
 }
 
@@ -4112,11 +4131,15 @@ void FullCodeGenerator::EmitCallFunction(CallRuntime* expr) {
 
 
 void FullCodeGenerator::EmitDefaultConstructorCallSuper(CallRuntime* expr) {
-  Variable* new_target_var = scope()->DeclarationScope()->new_target_var();
-  GetVar(result_register(), new_target_var);
-  __ Push(result_register());
+  ZoneList<Expression*>* args = expr->arguments();
+  DCHECK(args->length() == 2);
+
+  // new.target
+  VisitForStackValue(args->at(0));
 
-  EmitLoadSuperConstructor();
+  // .this_function
+  VisitForStackValue(args->at(1));
+  __ CallRuntime(Runtime::kGetPrototype, 1);
   __ Push(result_register());
 
   // Check if the calling frame is an arguments adaptor frame.
@@ -4568,11 +4591,14 @@ void FullCodeGenerator::EmitDebugIsActive(CallRuntime* expr) {
 
 void FullCodeGenerator::EmitCallSuperWithSpread(CallRuntime* expr) {
   // Assert: expr === CallRuntime("ReflectConstruct")
+  DCHECK_EQ(1, expr->arguments()->length());
   CallRuntime* call = expr->arguments()->at(0)->AsCallRuntime();
+
   ZoneList<Expression*>* args = call->arguments();
   DCHECK_EQ(3, args->length());
 
-  SuperReference* super_reference = args->at(0)->AsSuperReference();
+  SuperCallReference* super_call_ref = args->at(0)->AsSuperCallReference();
+  DCHECK_NOT_NULL(super_call_ref);
 
   // Load ReflectConstruct function
   EmitLoadJSRuntimeFunction(call);
@@ -4581,8 +4607,8 @@ void FullCodeGenerator::EmitCallSuperWithSpread(CallRuntime* expr) {
   __ Push(Operand(rsp, 0));
   __ movp(Operand(rsp, kPointerSize), rax);
 
-  // Push super
-  EmitLoadSuperConstructor();
+  // Push super constructor
+  EmitLoadSuperConstructor(super_call_ref);
   __ Push(result_register());
 
   // Push arguments array
@@ -4599,7 +4625,7 @@ void FullCodeGenerator::EmitCallSuperWithSpread(CallRuntime* expr) {
   context()->DropAndPlug(1, rax);
 
   // TODO(mvstanton): with FLAG_vector_stores this needs a slot id.
-  EmitInitializeThisAfterSuper(super_reference);
+  EmitInitializeThisAfterSuper(super_call_ref);
 }
 
 
@@ -4824,9 +4850,9 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
       }
 
       case NAMED_SUPER_PROPERTY: {
-        VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
+        VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
         VisitForAccumulatorValue(
-            prop->obj()->AsSuperReference()->home_object_var());
+            prop->obj()->AsSuperPropertyReference()->home_object_var());
         __ Push(result_register());
         __ Push(MemOperand(rsp, kPointerSize));
         __ Push(result_register());
@@ -4835,8 +4861,9 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
       }
 
       case KEYED_SUPER_PROPERTY: {
-        VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
-        VisitForStackValue(prop->obj()->AsSuperReference()->home_object_var());
+        VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
+        VisitForStackValue(
+            prop->obj()->AsSuperPropertyReference()->home_object_var());
         VisitForAccumulatorValue(prop->key());
         __ Push(result_register());
         __ Push(MemOperand(rsp, 2 * kPointerSize));
index 1af7ab2e234f97b3d48ef94935ab908a5cef034a..87fceafb299bceffd8fead995e1e4a45f03705c7 100644 (file)
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 // Flags: --harmony-classes --harmony-arrow-functions --allow-natives-syntax
-
+// Flags: --harmony-spreadcalls
 
 (function TestSuperNamedLoads() {
   function Base() { }
@@ -2107,3 +2107,99 @@ TestKeyedSetterCreatingOwnPropertiesNonConfigurable(42, 43, 44);
   let d = new Derived();
   assertSame(1, d.arrow());
 })();
+
+
+(function TestSuperCallInEval() {
+  'use strict';
+  class Base {
+    constructor(x) {
+      this.x = x;
+    }
+  }
+  class Derived extends Base {
+    constructor(x) {
+      eval('super(x)');
+    }
+  }
+  let d = new Derived(42);
+  assertSame(42, d.x);
+})();
+
+
+(function TestSuperCallInArrow() {
+  'use strict';
+  class Base {
+    constructor(x) {
+      this.x = x;
+    }
+  }
+  class Derived extends Base {
+    constructor(x) {
+      (() => super(x))();
+    }
+  }
+  let d = new Derived(42);
+  assertSame(42, d.x);
+})();
+
+
+(function TestSuperCallEscapes() {
+  'use strict';
+  class Base {
+    constructor(x) {
+      this.x = x;
+    }
+  }
+
+  let f;
+  class Derived extends Base {
+    constructor() {
+      f = () => super(2);
+    }
+  }
+  assertThrows(function() {
+    new Derived();
+  }, ReferenceError);
+
+  let o = f();
+  assertEquals(2, o.x);
+  assertInstanceof(o, Derived);
+
+  assertThrows(function() {
+    f();
+  }, ReferenceError);
+})();
+
+
+(function TestSuperCallSpreadInEval() {
+  'use strict';
+  class Base {
+    constructor(x) {
+      this.x = x;
+    }
+  }
+  class Derived extends Base {
+    constructor(x) {
+      eval('super(...[x])');
+    }
+  }
+  let d = new Derived(42);
+  assertSame(42, d.x);
+})();
+
+
+(function TestSuperCallSpreadInArrow() {
+  'use strict';
+  class Base {
+    constructor(x) {
+      this.x = x;
+    }
+  }
+  class Derived extends Base {
+    constructor(x) {
+      (() => super(...[x]))();
+    }
+  }
+  let d = new Derived(42);
+  assertSame(42, d.x);
+})();