Reviewers: rossberg, adamk,

Message:
Andreas: PTAL.
Adam: FYI.

Description:
Represent implicit 'this' binding by 'super' in AST.

This makes the implicit initializing assignment to 'this' performed
after a super constructor call explicit in the AST. It removes the
need to handle the special case where a CallExpression behaves like a
AssignmentExpression from various AstVisitor implementations.

[email protected]

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

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

Affected files (+53, -44 lines):
  M src/ast.h
  M src/ast.cc
  M src/compiler/ast-graph-builder.cc
  M src/compiler/ast-loop-assignment-analyzer.cc
  M src/full-codegen.h
  M src/ia32/full-codegen-ia32.cc
  M src/preparser.h


Index: src/ast.cc
diff --git a/src/ast.cc b/src/ast.cc
index 93cb6c09b99358f6a118f58e83442ef01f58e832..de229cb014ea36ad65f0f8d927646659a183d30e 100644
--- a/src/ast.cc
+++ b/src/ast.cc
@@ -59,6 +59,11 @@ bool Expression::IsUndefinedLiteral(Isolate* isolate) const {
 }


+bool Expression::IsVariableProxyOrProperty() const {
+  return IsVariableProxy() || IsProperty();
+}
+
+
 VariableProxy::VariableProxy(Zone* zone, Variable* var, int start_position,
                              int end_position)
     : Expression(zone, start_position),
Index: src/ast.h
diff --git a/src/ast.h b/src/ast.h
index b1a634edb4c7f02f4dc96658e3e9dba6c5cb9908..1cb9cedfdff4d1d2f23ea81a167aff557924b301 100644
--- a/src/ast.h
+++ b/src/ast.h
@@ -362,6 +362,9 @@ class Expression : public AstNode {
   // True if we can prove that the expression is the undefined literal.
   bool IsUndefinedLiteral(Isolate* isolate) const;

+  // True iff the expression represents a variable or a property.
+  bool IsVariableProxyOrProperty() const;
+
   // Expression type bounds
   Bounds bounds() const { return bounds_; }
   void set_bounds(Bounds bounds) { bounds_ = bounds; }
Index: src/compiler/ast-graph-builder.cc
diff --git a/src/compiler/ast-graph-builder.cc b/src/compiler/ast-graph-builder.cc index 0c0bb02ea5bd24d1a5b83c207ff00652ca4608ce..1dd7e5fee99bb27ce3e952bfb718b677e06bbc48 100644
--- a/src/compiler/ast-graph-builder.cc
+++ b/src/compiler/ast-graph-builder.cc
@@ -2016,7 +2016,7 @@ void AstGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
 void AstGraphBuilder::VisitForInAssignment(Expression* expr, Node* value,
                                            const VectorSlotPair& feedback,
                                            BailoutId bailout_id) {
-  DCHECK(expr->IsValidReferenceExpression());
+  DCHECK(expr->IsVariableProxyOrProperty());

   // Left-hand side can only be a property, a global or a variable slot.
   Property* property = expr->AsProperty();
@@ -2090,7 +2090,7 @@ void AstGraphBuilder::VisitForInAssignment(Expression* expr, Node* value,


 void AstGraphBuilder::VisitAssignment(Assignment* expr) {
-  DCHECK(expr->target()->IsValidReferenceExpression());
+  DCHECK(expr->target()->IsVariableProxyOrProperty());

   // Left-hand side can only be a property, a global or a variable slot.
   Property* property = expr->target()->AsProperty();
@@ -2520,12 +2520,6 @@ void AstGraphBuilder::VisitCallSuper(Call* expr) {
   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.
-  FrameStateBeforeAndAfter states(this, BailoutId::None());
- BuildVariableAssignment(super->this_var()->var(), value, Token::INIT_CONST,
-                          VectorSlotPair(), expr->id(), states);
-
   ast_context()->ProduceValue(value);
 }

@@ -2627,7 +2621,7 @@ void AstGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) {


 void AstGraphBuilder::VisitCountOperation(CountOperation* expr) {
-  DCHECK(expr->expression()->IsValidReferenceExpression());
+  DCHECK(expr->expression()->IsVariableProxyOrProperty());

   // Left-hand side can only be a property, a global or a variable slot.
   Property* property = expr->expression()->AsProperty();
Index: src/compiler/ast-loop-assignment-analyzer.cc
diff --git a/src/compiler/ast-loop-assignment-analyzer.cc b/src/compiler/ast-loop-assignment-analyzer.cc index e0a92a464c487e7e1b74b88321d28298c2502f33..61ed4f27cbba8e7d7b9287108a87ab9e8f3435e2 100644
--- a/src/compiler/ast-loop-assignment-analyzer.cc
+++ b/src/compiler/ast-loop-assignment-analyzer.cc
@@ -161,11 +161,6 @@ void ALAA::VisitProperty(Property* e) {
 void ALAA::VisitCall(Call* e) {
   Visit(e->expression());
   VisitExpressions(e->arguments());
-  // TODO(mstarzinger): It sure would be nice if this were desugared.
-  if (e->GetCallType(isolate()) == Call::SUPER_CALL) {
-    SuperCallReference* super = e->expression()->AsSuperCallReference();
-    AnalyzeAssignment(super->this_var()->var());
-  }
 }


Index: src/full-codegen.h
diff --git a/src/full-codegen.h b/src/full-codegen.h
index ccc10e061bcdfd8704cbae57caee662ff19ca7e2..88a88f45b2d56c5924e0219bfc7d8ca29d7f5b52 100644
--- a/src/full-codegen.h
+++ b/src/full-codegen.h
@@ -644,9 +644,6 @@ class FullCodeGenerator: public AstVisitor {
       FeedbackVectorICSlot slot = FeedbackVectorICSlot::Invalid());

   void EmitLoadSuperConstructor(SuperCallReference* super_call_ref);
-  void EmitInitializeThisAfterSuper(
-      SuperCallReference* super_call_ref,
-      FeedbackVectorICSlot slot = FeedbackVectorICSlot::Invalid());

   void CallIC(Handle<Code> code,
               TypeFeedbackId id = TypeFeedbackId::None());
Index: src/ia32/full-codegen-ia32.cc
diff --git a/src/ia32/full-codegen-ia32.cc b/src/ia32/full-codegen-ia32.cc
index 820d28ea6886e458894ea414943532ddf4578e00..d212eccd50b2d595ac81a1926e5444b72f301f06 100644
--- a/src/ia32/full-codegen-ia32.cc
+++ b/src/ia32/full-codegen-ia32.cc
@@ -1927,7 +1927,7 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {


 void FullCodeGenerator::VisitAssignment(Assignment* expr) {
-  DCHECK(expr->target()->IsValidReferenceExpression());
+  DCHECK(expr->target()->IsVariableProxyOrProperty());

   Comment cmnt(masm_, "[ Assignment");
   SetExpressionPosition(expr, INSERT_BREAK);
@@ -2584,7 +2584,7 @@ void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, Token::Value op) {

 void FullCodeGenerator::EmitAssignment(Expression* expr,
                                        FeedbackVectorICSlot slot) {
-  DCHECK(expr->IsValidReferenceExpression());
+  DCHECK(expr->IsVariableProxyOrProperty());

   Property* prop = expr->AsProperty();
   LhsKind assign_type = Property::GetAssignType(prop);
@@ -2726,6 +2726,19 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op,
     __ bind(&const_error);
     __ CallRuntime(Runtime::kThrowConstAssignError, 0);

+  } else if (var->is_this() && op == Token::INIT_CONST) {
+    // Initializing assignment to const {this} needs a write barrier.
+    DCHECK(var->IsStackAllocated() || var->IsContextSlot());
+    Label uninitialized_this;
+    MemOperand location = VarOperand(var, ecx);
+    __ mov(edx, location);
+    __ cmp(edx, isolate()->factory()->the_hole_value());
+    __ j(equal, &uninitialized_this);
+    __ push(Immediate(var->name()));
+    __ CallRuntime(Runtime::kThrowReferenceError, 1);
+    __ bind(&uninitialized_this);
+    EmitStoreToStackLocalOrContextSlot(var, location);
+
   } else if (!var->is_const_mode() || op == Token::INIT_CONST) {
     if (var->IsLookupSlot()) {
       // Assignment to var.
@@ -3068,22 +3081,6 @@ void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
 }


-void FullCodeGenerator::EmitInitializeThisAfterSuper(
-    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;
-  __ j(equal, &uninitialized_this);
-  __ push(Immediate(this_var->name()));
-  __ CallRuntime(Runtime::kThrowReferenceError, 1);
-  __ bind(&uninitialized_this);
-
-  EmitVariableAssignment(this_var, Token::INIT_CONST, slot);
-}
-
-
 // See http://www.ecma-international.org/ecma-262/6.0/#sec-function-calls.
 void FullCodeGenerator::PushCalleeAndWithBaseObject(Call* expr) {
   VariableProxy* callee = expr->expression()->AsVariableProxy();
@@ -3299,7 +3296,6 @@ void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) {

   RecordJSReturnSite(expr);

-  EmitInitializeThisAfterSuper(super_call_ref, expr->CallFeedbackICSlot());
   context()->Plug(eax);
 }

@@ -4675,9 +4671,6 @@ void FullCodeGenerator::EmitCallSuperWithSpread(CallRuntime* expr) {
   // Restore context register.
   __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
   context()->DropAndPlug(1, eax);
-
-  // TODO(mvstanton): with FLAG_vector_stores this needs a slot id.
-  EmitInitializeThisAfterSuper(super_call_ref);
 }


@@ -4876,7 +4869,7 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {


 void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
-  DCHECK(expr->expression()->IsValidReferenceExpression());
+  DCHECK(expr->expression()->IsVariableProxyOrProperty());

   Comment cmnt(masm_, "[ CountOperation");

Index: src/preparser.h
diff --git a/src/preparser.h b/src/preparser.h
index 921cd875a1816abaee53eed6db15e6222465bc5a..a4edc37a2aba5959106e1acac0c54a6947040a50 100644
--- a/src/preparser.h
+++ b/src/preparser.h
@@ -947,10 +947,16 @@ class PreParserExpression {
ExpressionTypeField::encode(kCallExpression));
   }

+  static PreParserExpression SuperCallReference() {
+    return PreParserExpression(
+        TypeField::encode(kExpression) |
+        ExpressionTypeField::encode(kSuperCallReference));
+  }
+
   static PreParserExpression NoTemplateTag() {
-    return PreParserExpression(TypeField::encode(kExpression) |
-                               ExpressionTypeField::encode(
-                                  kNoTemplateTagExpression));
+    return PreParserExpression(
+        TypeField::encode(kExpression) |
+        ExpressionTypeField::encode(kNoTemplateTagExpression));
   }

   bool IsIdentifier() const {
@@ -997,6 +1003,11 @@ class PreParserExpression {
            ExpressionTypeField::decode(code_) == kCallExpression;
   }

+  bool IsSuperCallReference() const {
+    return TypeField::decode(code_) == kExpression &&
+           ExpressionTypeField::decode(code_) == kSuperCallReference;
+  }
+
   bool IsValidReferenceExpression() const {
     return IsIdentifier() || IsProperty();
   }
@@ -1045,6 +1056,7 @@ class PreParserExpression {
     kThisPropertyExpression,
     kPropertyExpression,
     kCallExpression,
+    kSuperCallReference,
     kNoTemplateTagExpression
   };

@@ -1528,7 +1540,7 @@ class PreParserTraits {
   static PreParserExpression SuperCallReference(Scope* scope,
                                                 PreParserFactory* factory,
                                                 int pos) {
-    return PreParserExpression::Default();
+    return PreParserExpression::SuperCallReference();
   }

   static PreParserExpression NewTargetExpression(Scope* scope,
@@ -3184,12 +3196,22 @@ ParserBase<Traits>::ParseLeftHandSideExpression(
// they are actually direct calls to eval is determined at run time.
         this->CheckPossibleEvalCall(result, scope_);

+        bool is_super_call = result->IsSuperCallReference();
         if (spread_pos.IsValid()) {
           args = Traits::PrepareSpreadArguments(args);
           result = Traits::SpreadCall(result, args, pos);
         } else {
           result = factory()->NewCall(result, args, pos);
         }
+
+ // Explicit calls to the super constructor using super() perform and
+        // implicit binding assignment to the 'this' variable.
+        if (is_super_call) {
+ ExpressionT this_expr = this->ThisExpression(scope_, factory(), pos);
+          result = factory()->NewAssignment(Token::INIT_CONST, this_expr,
+                                            result, pos);
+        }
+
         if (fni_ != NULL) fni_->RemoveLastFunction();
         break;
       }


--
--
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