Reviewers: Benedikt Meurer,

Description:
[turbofan] Build graphs for super constructor calls.

This adapts JSCallConstruct nodes to represent both, ordinary 'new'
constructor calls as well as 'super' constructor calls. Note that we
still bailout for super calls for now.

[email protected]

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

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

Affected files (+56, -11 lines):
  M src/compiler/ast-graph-builder.h
  M src/compiler/ast-graph-builder.cc
  M src/compiler/js-generic-lowering.cc


Index: src/compiler/ast-graph-builder.cc
diff --git a/src/compiler/ast-graph-builder.cc b/src/compiler/ast-graph-builder.cc index fd1b6960d094b5b7ec47a20f1996d828737bf949..2d3d8279b12aabe9a67967a6e8d95714e8ddd207 100644
--- a/src/compiler/ast-graph-builder.cc
+++ b/src/compiler/ast-graph-builder.cc
@@ -2415,11 +2415,7 @@ void AstGraphBuilder::VisitCall(Call* expr) {
       break;
     }
     case Call::SUPER_CALL:
-      // TODO(dslomov): Implement super calls.
-      callee_value = jsgraph()->UndefinedConstant();
-      receiver_value = jsgraph()->UndefinedConstant();
-      SetStackOverflow();
-      break;
+      return VisitCallSuper(expr);
     case Call::POSSIBLY_EVAL_CALL:
       possibly_eval = true;
       if (callee->AsVariableProxy()->var()->IsLookupSlot()) {
@@ -2486,6 +2482,45 @@ void AstGraphBuilder::VisitCall(Call* expr) {
 }


+void AstGraphBuilder::VisitCallSuper(Call* expr) {
+  SuperCallReference* super = expr->expression()->AsSuperCallReference();
+  DCHECK_NOT_NULL(super);
+
+ // Prepare the callee to the super call. The super constructor is stored as
+  // the prototype of the constructor we are currently executing.
+  VisitForValue(super->this_function_var());
+  Node* this_function = environment()->Pop();
+ const Operator* op = javascript()->CallRuntime(Runtime::kGetPrototype, 1);
+  Node* super_function = NewNode(op, this_function);
+  // TODO(mstarzinger): This probably needs a proper bailout id.
+  PrepareFrameState(super_function, BailoutId::None());
+  environment()->Push(super_function);
+
+  // Evaluate all arguments to the super call.
+  ZoneList<Expression*>* args = expr->arguments();
+  VisitForValues(args);
+
+  // Original receiver is loaded from the {new.target} variable.
+  VisitForValue(super->new_target_var());
+
+  // Create node to perform the super call.
+  const Operator* call = javascript()->CallConstruct(args->length() + 2);
+  Node* value = ProcessArguments(call, args->length() + 2);
+  PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
+
+ // TODO(mstarzinger): It sure would be nice if this were desugared. Also we
+  // are still missing the hole-check in the assignment below, fix that.
+  FrameStateBeforeAndAfter states(this, BailoutId::None());
+ BuildVariableAssignment(super->this_var()->var(), value, Token::INIT_CONST,
+                          VectorSlotPair(), BailoutId::None(), states);
+
+  // TODO(mstarzinger): Remove bailout once lowering is correct.
+  SetStackOverflow();
+
+  ast_context()->ProduceValue(value);
+}
+
+
 void AstGraphBuilder::VisitCallNew(CallNew* expr) {
   VisitForValue(expr->expression());

@@ -2493,9 +2528,12 @@ void AstGraphBuilder::VisitCallNew(CallNew* expr) {
   ZoneList<Expression*>* args = expr->arguments();
   VisitForValues(args);

+  // Original receiver is the same as the callee.
+  environment()->Push(environment()->Peek(args->length()));
+
   // Create node to perform the construct call.
-  const Operator* call = javascript()->CallConstruct(args->length() + 1);
-  Node* value = ProcessArguments(call, args->length() + 1);
+  const Operator* call = javascript()->CallConstruct(args->length() + 2);
+  Node* value = ProcessArguments(call, args->length() + 2);
   PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
   ast_context()->ProduceValue(value);
 }
Index: src/compiler/ast-graph-builder.h
diff --git a/src/compiler/ast-graph-builder.h b/src/compiler/ast-graph-builder.h index 47a6197e5d22409a8b83f21e3f10c1962f2a0330..bbe380f8c802f6aa4593e638e2de45e6c99802f8 100644
--- a/src/compiler/ast-graph-builder.h
+++ b/src/compiler/ast-graph-builder.h
@@ -387,6 +387,9 @@ class AstGraphBuilder : public AstVisitor {
   // Common for all IterationStatement bodies.
   void VisitIterationBody(IterationStatement* stmt, LoopBuilder* loop);

+  // Dispatched from VisitCall.
+  void VisitCallSuper(Call* expr);
+
   // Dispatched from VisitCallRuntime.
   void VisitCallJSRuntime(CallRuntime* expr);

Index: src/compiler/js-generic-lowering.cc
diff --git a/src/compiler/js-generic-lowering.cc b/src/compiler/js-generic-lowering.cc index 1dbe382cfd29b26f4550d9ee3e6fd864a774f18f..91643a36ee6a231e4c151675d46743c7baee70fa 100644
--- a/src/compiler/js-generic-lowering.cc
+++ b/src/compiler/js-generic-lowering.cc
@@ -540,12 +540,16 @@ void JSGenericLowering::LowerJSCallConstruct(Node* node) {
   CallInterfaceDescriptor d = stub.GetCallInterfaceDescriptor();
   CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
   CallDescriptor* desc =
-      Linkage::GetStubCallDescriptor(isolate(), zone(), d, arity, flags);
+ Linkage::GetStubCallDescriptor(isolate(), zone(), d, arity - 1, flags);
   Node* stub_code = jsgraph()->HeapConstant(stub.GetCode());
-  Node* construct = NodeProperties::GetValueInput(node, 0);
+  Node* actual_construct = NodeProperties::GetValueInput(node, 0);
+ Node* original_construct = NodeProperties::GetValueInput(node, arity - 1);
+  node->RemoveInput(arity - 1);  // Drop original constructor.
   node->InsertInput(zone(), 0, stub_code);
-  node->InsertInput(zone(), 1, jsgraph()->Int32Constant(arity - 1));
-  node->InsertInput(zone(), 2, construct);
+  node->InsertInput(zone(), 1, jsgraph()->Int32Constant(arity - 2));
+  node->InsertInput(zone(), 2, actual_construct);
+  // TODO(mstarzinger): Pass original constructor in register.
+  DCHECK_EQ(actual_construct, original_construct);
   node->InsertInput(zone(), 3, jsgraph()->UndefinedConstant());
   node->set_op(common()->Call(desc));
 }


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

Reply via email to