[es6] Support super.property in eval and arrow functions
authorarv <arv@chromium.org>
Tue, 26 May 2015 20:29:47 +0000 (13:29 -0700)
committerCommit bot <commit-bot@chromium.org>
Tue, 26 May 2015 20:29:54 +0000 (20:29 +0000)
When we enter a method that needs access to the [[HomeObject]]
we allocate a local variable `.home_object` and assign it the
value from the [[HomeObject]] private symbol. Something along
the lines of:

  method() {
    var .home_object = %ThisFunction()[home_object_symbol];
    ...
  }

BUG=v8:3867, v8:4031
LOG=N

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

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

24 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/full-codegen.h
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/preparser.cc
src/preparser.h
src/scopes.cc
src/scopes.h
src/x64/full-codegen-x64.cc
test/cctest/test-compiler.cc
test/cctest/test-feedback-vector.cc
test/cctest/test-heap.cc
test/cctest/test-parsing.cc
test/mjsunit/harmony/object-literals-super.js
test/mjsunit/harmony/super.js

index 8539ad4c4ac3e3e4d5beaf5c9819eee9394fc76e..5f612ee92c8b197df64af1a8504088b28a6363f9 100644 (file)
@@ -242,6 +242,11 @@ void FullCodeGenerator::Generate() {
     }
   }
 
+  Variable* home_object_var = scope()->home_object_var();
+  if (home_object_var != nullptr) {
+    __ Push(r1);
+  }
+
   ArgumentsAccessStub::HasNewTarget has_new_target =
       IsSubclassConstructor(info->function()->kind())
           ? ArgumentsAccessStub::HAS_NEW_TARGET
@@ -307,6 +312,19 @@ void FullCodeGenerator::Generate() {
     SetVar(arguments, r0, r1, r2);
   }
 
+  // Possibly set up a local binding to the [[HomeObject]].
+  if (home_object_var != nullptr) {
+    Comment cmnt(masm_, "[ Home object");
+    __ Pop(LoadDescriptor::ReceiverRegister());
+    Handle<Symbol> home_object_symbol(isolate()->heap()->home_object_symbol());
+    __ Move(LoadDescriptor::NameRegister(), home_object_symbol);
+    __ Move(LoadDescriptor::SlotRegister(),
+            Operand(SmiFromSlot(function()->HomeObjectFeedbackSlot())));
+    CallLoadIC(NOT_CONTEXTUAL);
+
+    SetVar(home_object_var, r0, r1, r2);
+  }
+
   if (FLAG_trace) {
     __ CallRuntime(Runtime::kTraceEnter, 0);
   }
@@ -1325,27 +1343,6 @@ void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
 }
 
 
-void FullCodeGenerator::EmitLoadHomeObject(SuperReference* expr) {
-  Comment cnmt(masm_, "[ SuperReference ");
-
-  __ ldr(LoadDescriptor::ReceiverRegister(),
-         MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
-
-  Handle<Symbol> home_object_symbol(isolate()->heap()->home_object_symbol());
-  __ Move(LoadDescriptor::NameRegister(), home_object_symbol);
-
-  __ mov(LoadDescriptor::SlotRegister(),
-         Operand(SmiFromSlot(expr->HomeObjectFeedbackSlot())));
-  CallLoadIC(NOT_CONTEXTUAL);
-
-  __ cmp(r0, Operand(isolate()->factory()->undefined_value()));
-  Label done;
-  __ b(ne, &done);
-  __ CallRuntime(Runtime::kThrowNonMethodError, 0);
-  __ bind(&done);
-}
-
-
 void FullCodeGenerator::EmitSetHomeObjectIfNeeded(Expression* initializer,
                                                   int offset) {
   if (NeedsHomeObject(initializer)) {
@@ -1980,7 +1977,8 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
       break;
     case NAMED_SUPER_PROPERTY:
       VisitForStackValue(property->obj()->AsSuperReference()->this_var());
-      EmitLoadHomeObject(property->obj()->AsSuperReference());
+      VisitForAccumulatorValue(
+          property->obj()->AsSuperReference()->home_object_var());
       __ Push(result_register());
       if (expr->is_compound()) {
         const Register scratch = r1;
@@ -1991,8 +1989,8 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
       break;
     case KEYED_SUPER_PROPERTY:
       VisitForStackValue(property->obj()->AsSuperReference()->this_var());
-      EmitLoadHomeObject(property->obj()->AsSuperReference());
-      __ Push(result_register());
+      VisitForStackValue(
+          property->obj()->AsSuperReference()->home_object_var());
       VisitForAccumulatorValue(property->key());
       __ Push(result_register());
       if (expr->is_compound()) {
@@ -2634,7 +2632,8 @@ void FullCodeGenerator::EmitAssignment(Expression* expr) {
     case NAMED_SUPER_PROPERTY: {
       __ Push(r0);
       VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
-      EmitLoadHomeObject(prop->obj()->AsSuperReference());
+      VisitForAccumulatorValue(
+          prop->obj()->AsSuperReference()->home_object_var());
       // stack: value, this; r0: home_object
       Register scratch = r2;
       Register scratch2 = r3;
@@ -2650,8 +2649,7 @@ void FullCodeGenerator::EmitAssignment(Expression* expr) {
     case KEYED_SUPER_PROPERTY: {
       __ Push(r0);
       VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
-      EmitLoadHomeObject(prop->obj()->AsSuperReference());
-      __ Push(result_register());
+      VisitForStackValue(prop->obj()->AsSuperReference()->home_object_var());
       VisitForAccumulatorValue(prop->key());
       Register scratch = r2;
       Register scratch2 = r3;
@@ -2863,8 +2861,7 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
       EmitNamedPropertyLoad(expr);
     } else {
       VisitForStackValue(expr->obj()->AsSuperReference()->this_var());
-      EmitLoadHomeObject(expr->obj()->AsSuperReference());
-      __ Push(result_register());
+      VisitForStackValue(expr->obj()->AsSuperReference()->home_object_var());
       EmitNamedSuperPropertyLoad(expr);
     }
   } else {
@@ -2876,8 +2873,7 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
       EmitKeyedPropertyLoad(expr);
     } else {
       VisitForStackValue(expr->obj()->AsSuperReference()->this_var());
-      EmitLoadHomeObject(expr->obj()->AsSuperReference());
-      __ Push(result_register());
+      VisitForStackValue(expr->obj()->AsSuperReference()->home_object_var());
       VisitForStackValue(expr->key());
       EmitKeyedSuperPropertyLoad(expr);
     }
@@ -2943,8 +2939,7 @@ void FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) {
   // Load the function from the receiver.
   const Register scratch = r1;
   SuperReference* super_ref = prop->obj()->AsSuperReference();
-  EmitLoadHomeObject(super_ref);
-  __ Push(r0);
+  VisitForStackValue(super_ref->home_object_var());
   VisitForAccumulatorValue(super_ref->this_var());
   __ Push(r0);
   __ Push(r0);
@@ -3004,8 +2999,7 @@ void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) {
   // Load the function from the receiver.
   const Register scratch = r1;
   SuperReference* super_ref = prop->obj()->AsSuperReference();
-  EmitLoadHomeObject(super_ref);
-  __ Push(r0);
+  VisitForStackValue(super_ref->home_object_var());
   VisitForAccumulatorValue(super_ref->this_var());
   __ Push(r0);
   __ Push(r0);
@@ -4847,7 +4841,8 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
 
       case NAMED_SUPER_PROPERTY: {
         VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
-        EmitLoadHomeObject(prop->obj()->AsSuperReference());
+        VisitForAccumulatorValue(
+            prop->obj()->AsSuperReference()->home_object_var());
         __ Push(result_register());
         const Register scratch = r1;
         __ ldr(scratch, MemOperand(sp, kPointerSize));
@@ -4859,8 +4854,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
 
       case KEYED_SUPER_PROPERTY: {
         VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
-        EmitLoadHomeObject(prop->obj()->AsSuperReference());
-        __ Push(result_register());
+        VisitForStackValue(prop->obj()->AsSuperReference()->home_object_var());
         VisitForAccumulatorValue(prop->key());
         __ Push(result_register());
         const Register scratch = r1;
index 36aad7cd9a6fcb06923801905a8c466d3f08324f..bb95859cec0294ab8a09e04bd6074faa6e84fcda 100644 (file)
@@ -243,6 +243,11 @@ void FullCodeGenerator::Generate() {
     }
   }
 
+  Variable* home_object_var = scope()->home_object_var();
+  if (home_object_var != nullptr) {
+    __ Push(x1);
+  }
+
   ArgumentsAccessStub::HasNewTarget has_new_target =
       IsSubclassConstructor(info->function()->kind())
           ? ArgumentsAccessStub::HAS_NEW_TARGET
@@ -307,11 +312,23 @@ void FullCodeGenerator::Generate() {
     SetVar(arguments, x0, x1, x2);
   }
 
+  // Possibly set up a local binding to the [[HomeObject]].
+  if (home_object_var != nullptr) {
+    Comment cmnt(masm_, "[ Home object");
+    __ Pop(LoadDescriptor::ReceiverRegister());
+    Handle<Symbol> home_object_symbol(isolate()->heap()->home_object_symbol());
+    __ Mov(LoadDescriptor::NameRegister(), home_object_symbol);
+    __ Mov(LoadDescriptor::SlotRegister(),
+           SmiFromSlot(function()->HomeObjectFeedbackSlot()));
+    CallLoadIC(NOT_CONTEXTUAL);
+
+    SetVar(home_object_var, x0, x1, x2);
+  }
+
   if (FLAG_trace) {
     __ CallRuntime(Runtime::kTraceEnter, 0);
   }
 
-
   // Visit the declarations and body unless there is an illegal
   // redeclaration.
   if (scope()->HasIllegalRedeclaration()) {
@@ -1310,28 +1327,6 @@ void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
 }
 
 
-void FullCodeGenerator::EmitLoadHomeObject(SuperReference* expr) {
-  Comment cnmt(masm_, "[ SuperReference ");
-
-  __ ldr(LoadDescriptor::ReceiverRegister(),
-         MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
-
-  Handle<Symbol> home_object_symbol(isolate()->heap()->home_object_symbol());
-  __ Mov(LoadDescriptor::NameRegister(), Operand(home_object_symbol));
-
-  __ Mov(LoadDescriptor::SlotRegister(),
-         SmiFromSlot(expr->HomeObjectFeedbackSlot()));
-  CallLoadIC(NOT_CONTEXTUAL);
-
-  __ Mov(x10, Operand(isolate()->factory()->undefined_value()));
-  __ cmp(x0, x10);
-  Label done;
-  __ b(&done, ne);
-  __ CallRuntime(Runtime::kThrowNonMethodError, 0);
-  __ bind(&done);
-}
-
-
 void FullCodeGenerator::EmitSetHomeObjectIfNeeded(Expression* initializer,
                                                   int offset) {
   if (NeedsHomeObject(initializer)) {
@@ -1951,7 +1946,8 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
       break;
     case NAMED_SUPER_PROPERTY:
       VisitForStackValue(property->obj()->AsSuperReference()->this_var());
-      EmitLoadHomeObject(property->obj()->AsSuperReference());
+      VisitForAccumulatorValue(
+          property->obj()->AsSuperReference()->home_object_var());
       __ Push(result_register());
       if (expr->is_compound()) {
         const Register scratch = x10;
@@ -1961,8 +1957,8 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
       break;
     case KEYED_SUPER_PROPERTY:
       VisitForStackValue(property->obj()->AsSuperReference()->this_var());
-      EmitLoadHomeObject(property->obj()->AsSuperReference());
-      __ Push(result_register());
+      VisitForStackValue(
+          property->obj()->AsSuperReference()->home_object_var());
       VisitForAccumulatorValue(property->key());
       __ Push(result_register());
       if (expr->is_compound()) {
@@ -2318,7 +2314,8 @@ void FullCodeGenerator::EmitAssignment(Expression* expr) {
     case NAMED_SUPER_PROPERTY: {
       __ Push(x0);
       VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
-      EmitLoadHomeObject(prop->obj()->AsSuperReference());
+      VisitForAccumulatorValue(
+          prop->obj()->AsSuperReference()->home_object_var());
       // stack: value, this; x0: home_object
       Register scratch = x10;
       Register scratch2 = x11;
@@ -2334,8 +2331,7 @@ void FullCodeGenerator::EmitAssignment(Expression* expr) {
     case KEYED_SUPER_PROPERTY: {
       __ Push(x0);
       VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
-      EmitLoadHomeObject(prop->obj()->AsSuperReference());
-      __ Push(result_register());
+      VisitForStackValue(prop->obj()->AsSuperReference()->home_object_var());
       VisitForAccumulatorValue(prop->key());
       Register scratch = x10;
       Register scratch2 = x11;
@@ -2550,8 +2546,7 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
       EmitNamedPropertyLoad(expr);
     } else {
       VisitForStackValue(expr->obj()->AsSuperReference()->this_var());
-      EmitLoadHomeObject(expr->obj()->AsSuperReference());
-      __ Push(result_register());
+      VisitForStackValue(expr->obj()->AsSuperReference()->home_object_var());
       EmitNamedSuperPropertyLoad(expr);
     }
   } else {
@@ -2563,8 +2558,7 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
       EmitKeyedPropertyLoad(expr);
     } else {
       VisitForStackValue(expr->obj()->AsSuperReference()->this_var());
-      EmitLoadHomeObject(expr->obj()->AsSuperReference());
-      __ Push(result_register());
+      VisitForStackValue(expr->obj()->AsSuperReference()->home_object_var());
       VisitForStackValue(expr->key());
       EmitKeyedSuperPropertyLoad(expr);
     }
@@ -2633,8 +2627,7 @@ void FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) {
   // Load the function from the receiver.
   const Register scratch = x10;
   SuperReference* super_ref = callee->AsProperty()->obj()->AsSuperReference();
-  EmitLoadHomeObject(super_ref);
-  __ Push(x0);
+  VisitForStackValue(super_ref->home_object_var());
   VisitForAccumulatorValue(super_ref->this_var());
   __ Push(x0);
   __ Peek(scratch, kPointerSize);
@@ -2693,8 +2686,7 @@ void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) {
   // Load the function from the receiver.
   const Register scratch = x10;
   SuperReference* super_ref = callee->AsProperty()->obj()->AsSuperReference();
-  EmitLoadHomeObject(super_ref);
-  __ Push(x0);
+  VisitForStackValue(super_ref->home_object_var());
   VisitForAccumulatorValue(super_ref->this_var());
   __ Push(x0);
   __ Peek(scratch, kPointerSize);
@@ -4530,7 +4522,8 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
 
       case NAMED_SUPER_PROPERTY: {
         VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
-        EmitLoadHomeObject(prop->obj()->AsSuperReference());
+        VisitForAccumulatorValue(
+            prop->obj()->AsSuperReference()->home_object_var());
         __ Push(result_register());
         const Register scratch = x10;
         __ Peek(scratch, kPointerSize);
@@ -4541,8 +4534,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
 
       case KEYED_SUPER_PROPERTY: {
         VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
-        EmitLoadHomeObject(prop->obj()->AsSuperReference());
-        __ Push(result_register());
+        VisitForStackValue(prop->obj()->AsSuperReference()->home_object_var());
         VisitForAccumulatorValue(prop->key());
         __ Push(result_register());
         const Register scratch1 = x10;
index 4ec93eded0ee289fda1d2658ee82753637f5c48d..6f5701309cf0310edb5e628b27ecaab03afce923 100644 (file)
@@ -174,6 +174,7 @@ void AstNumberingVisitor::VisitSuperReference(SuperReference* node) {
   ReserveFeedbackSlots(node);
   node->set_base_id(ReserveIdRange(SuperReference::num_ids()));
   Visit(node->this_var());
+  Visit(node->home_object_var());
 }
 
 
@@ -525,6 +526,8 @@ bool AstNumberingVisitor::Renumber(FunctionLiteral* node) {
     DisableCrankshaft(kContextAllocatedArguments);
   }
 
+  ReserveFeedbackSlots(node);
+
   VisitDeclarations(scope->declarations());
   if (scope->is_function_scope() && scope->function() != NULL) {
     // Visit the name of the named function expression.
index bfe10f181303591ac8ab7c8151d198606cc4ce80..e9830c33fbdd1eb900c16f9690c33d8e254bfd38 100644 (file)
@@ -248,6 +248,7 @@ class AstValue : public ZoneObject {
   F(empty, "")                                                             \
   F(eval, "eval")                                                          \
   F(get_template_callsite, "$getTemplateCallSite")                         \
+  F(home_object, ".home_object")                                           \
   F(initialize_const_global, "initializeConstGlobal")                      \
   F(initialize_var_global, "initializeVarGlobal")                          \
   F(is_construct_call, "_IsConstructCall")                                 \
index a73c61382322b4c793dc7c399038b6766e482bfa..9b8abad32437cfce5601e9391d3d81291d5e92cc 100644 (file)
@@ -179,7 +179,7 @@ LanguageMode FunctionLiteral::language_mode() const {
 
 bool FunctionLiteral::uses_super_property() const {
   DCHECK_NOT_NULL(scope());
-  return scope()->uses_super_property() || scope()->inner_uses_super_property();
+  return scope()->uses_super_property();
 }
 
 
index 44339c7c9fce037e747863c44cd96f17d8501dd7..241a8a23b4f8550f9315ca5c6b0f85f9ac593073 100644 (file)
--- a/src/ast.h
+++ b/src/ast.h
@@ -2539,6 +2539,26 @@ class FunctionLiteral final : public Expression {
     dont_optimize_reason_ = reason;
   }
 
+  static int num_ids() { return parent_num_ids() + 1; }
+  TypeFeedbackId HomeObjectFeedbackId() { return TypeFeedbackId(local_id(0)); }
+
+  // Type feedback information.
+  virtual FeedbackVectorRequirements ComputeFeedbackRequirements(
+      Isolate* isolate, const ICSlotCache* cache) override {
+    return FeedbackVectorRequirements(0, 1);
+  }
+  void SetFirstFeedbackICSlot(FeedbackVectorICSlot slot,
+                              ICSlotCache* cache) override {
+    DCHECK(!slot.IsInvalid());
+    home_object_feedback_slot_ = slot;
+  }
+  Code::Kind FeedbackICSlotKind(int index) override { return Code::LOAD_IC; }
+
+  FeedbackVectorICSlot HomeObjectFeedbackSlot() {
+    DCHECK(!home_object_feedback_slot_.IsInvalid());
+    return home_object_feedback_slot_;
+  }
+
  protected:
   FunctionLiteral(Zone* zone, const AstRawString* name,
                   AstValueFactory* ast_value_factory, Scope* scope,
@@ -2560,7 +2580,8 @@ class FunctionLiteral final : public Expression {
         expected_property_count_(expected_property_count),
         handler_count_(handler_count),
         parameter_count_(parameter_count),
-        function_token_position_(RelocInfo::kNoPosition) {
+        function_token_position_(RelocInfo::kNoPosition),
+        home_object_feedback_slot_(FeedbackVectorICSlot::Invalid()) {
     bitfield_ = IsExpression::encode(function_type != DECLARATION) |
                 IsAnonymous::encode(function_type == ANONYMOUS_EXPRESSION) |
                 Pretenure::encode(false) |
@@ -2572,6 +2593,8 @@ class FunctionLiteral final : public Expression {
     DCHECK(IsValidFunctionKind(kind));
   }
 
+  static int parent_num_ids() { return Expression::num_ids(); }
+
  private:
   const AstRawString* raw_name_;
   Handle<String> name_;
@@ -2589,6 +2612,9 @@ class FunctionLiteral final : public Expression {
   int parameter_count_;
   int function_token_position_;
 
+  int local_id(int n) const { return base_id() + parent_num_ids() + n; }
+  FeedbackVectorICSlot home_object_feedback_slot_;
+
   unsigned bitfield_;
   class IsExpression : public BitField<bool, 0, 1> {};
   class IsAnonymous : public BitField<bool, 1, 1> {};
@@ -2690,37 +2716,21 @@ class SuperReference final : public Expression {
   DECLARE_NODE_TYPE(SuperReference)
 
   VariableProxy* this_var() const { return this_var_; }
-
-  static int num_ids() { return parent_num_ids(); }
-
-  // Type feedback information.
-  virtual FeedbackVectorRequirements ComputeFeedbackRequirements(
-      Isolate* isolate, const ICSlotCache* cache) override {
-    return FeedbackVectorRequirements(0, 1);
-  }
-  void SetFirstFeedbackICSlot(FeedbackVectorICSlot slot,
-                              ICSlotCache* cache) override {
-    homeobject_feedback_slot_ = slot;
-  }
-  Code::Kind FeedbackICSlotKind(int index) override { return Code::LOAD_IC; }
-
-  FeedbackVectorICSlot HomeObjectFeedbackSlot() {
-    DCHECK(!homeobject_feedback_slot_.IsInvalid());
-    return homeobject_feedback_slot_;
-  }
+  VariableProxy* home_object_var() const { return home_object_var_; }
 
  protected:
-  SuperReference(Zone* zone, VariableProxy* this_var, int pos)
+  SuperReference(Zone* zone, VariableProxy* this_var,
+                 VariableProxy* home_object_var, int pos)
       : Expression(zone, pos),
         this_var_(this_var),
-        homeobject_feedback_slot_(FeedbackVectorICSlot::Invalid()) {
+        home_object_var_(home_object_var) {
     DCHECK(this_var->is_this());
+    DCHECK(home_object_var->raw_name()->IsOneByteEqualTo(".home_object"));
   }
-  static int parent_num_ids() { return Expression::num_ids(); }
 
  private:
   VariableProxy* this_var_;
-  FeedbackVectorICSlot homeobject_feedback_slot_;
+  VariableProxy* home_object_var_;
 };
 
 
@@ -3491,8 +3501,9 @@ class AstNodeFactory final BASE_EMBEDDED {
     return new (zone_) ThisFunction(zone_, pos);
   }
 
-  SuperReference* NewSuperReference(VariableProxy* this_var, int pos) {
-    return new (zone_) SuperReference(zone_, this_var, pos);
+  SuperReference* NewSuperReference(VariableProxy* this_var,
+                                    VariableProxy* home_object_var, int pos) {
+    return new (zone_) SuperReference(zone_, this_var, home_object_var, pos);
   }
 
  private:
index 0b60bd03ffdc937f08d51ee5036da77b62c4e049..194e068ce1a08455ee5862bf35f9737a0c964a34 100644 (file)
@@ -2225,6 +2225,13 @@ void AstGraphBuilder::VisitThrow(Throw* expr) {
 
 
 void AstGraphBuilder::VisitProperty(Property* expr) {
+  if (expr->obj()->IsSuperReference()) {
+    // TODO(turbofan): Implement super here.
+    SetStackOverflow();
+    ast_context()->ProduceValue(jsgraph()->UndefinedConstant());
+    return;
+  }
+
   Node* value;
   VectorSlotPair pair = CreateVectorSlotPair(expr->PropertyFeedbackSlot());
   if (expr->key()->IsPropertyName()) {
index ff3faa88c56a5da565fd840717b063a9a82b45ac..6dfbf573a82ef263813b7cda027181334a1eeb4e 100644 (file)
@@ -676,8 +676,6 @@ class FullCodeGenerator: public AstVisitor {
   // accumulator.
   void EmitKeyedPropertyAssignment(Assignment* expr);
 
-  void EmitLoadHomeObject(SuperReference* expr);
-
   static bool NeedsHomeObject(Expression* expr) {
     return FunctionLiteral::NeedsHomeObject(expr);
   }
index 0993b6c9739e4e62536f71197e9c195b44f5e3a6..f5317047e957625fea43c2fd431026d5adf565cd 100644 (file)
@@ -238,6 +238,11 @@ void FullCodeGenerator::Generate() {
     }
   }
 
+  Variable* home_object_var = scope()->home_object_var();
+  if (home_object_var != nullptr) {
+    __ push(edi);
+  }
+
   ArgumentsAccessStub::HasNewTarget has_new_target =
       IsSubclassConstructor(info->function()->kind())
           ? ArgumentsAccessStub::HAS_NEW_TARGET
@@ -303,6 +308,19 @@ void FullCodeGenerator::Generate() {
     SetVar(arguments, eax, ebx, edx);
   }
 
+  // Possibly set up a local binding to the [[HomeObject]].
+  if (home_object_var != nullptr) {
+    Comment cmnt(masm_, "[ Home object");
+    __ pop(LoadDescriptor::ReceiverRegister());
+    Handle<Symbol> home_object_symbol(isolate()->heap()->home_object_symbol());
+    __ mov(LoadDescriptor::NameRegister(), Immediate(home_object_symbol));
+    __ mov(LoadDescriptor::SlotRegister(),
+           Immediate(SmiFromSlot(function()->HomeObjectFeedbackSlot())));
+    CallLoadIC(NOT_CONTEXTUAL);
+
+    SetVar(home_object_var, eax, ebx, edx);
+  }
+
   if (FLAG_trace) {
     __ CallRuntime(Runtime::kTraceEnter, 0);
   }
@@ -1251,27 +1269,6 @@ void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
 }
 
 
-void FullCodeGenerator::EmitLoadHomeObject(SuperReference* expr) {
-  Comment cnmt(masm_, "[ SuperReference ");
-
-  __ mov(LoadDescriptor::ReceiverRegister(),
-         Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
-
-  Handle<Symbol> home_object_symbol(isolate()->heap()->home_object_symbol());
-  __ mov(LoadDescriptor::NameRegister(), home_object_symbol);
-
-  __ mov(LoadDescriptor::SlotRegister(),
-         Immediate(SmiFromSlot(expr->HomeObjectFeedbackSlot())));
-  CallLoadIC(NOT_CONTEXTUAL);
-
-  __ cmp(eax, isolate()->factory()->undefined_value());
-  Label done;
-  __ j(not_equal, &done);
-  __ CallRuntime(Runtime::kThrowNonMethodError, 0);
-  __ bind(&done);
-}
-
-
 void FullCodeGenerator::EmitSetHomeObjectIfNeeded(Expression* initializer,
                                                   int offset) {
   if (NeedsHomeObject(initializer)) {
@@ -1898,7 +1895,8 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
       break;
     case NAMED_SUPER_PROPERTY:
       VisitForStackValue(property->obj()->AsSuperReference()->this_var());
-      EmitLoadHomeObject(property->obj()->AsSuperReference());
+      VisitForAccumulatorValue(
+          property->obj()->AsSuperReference()->home_object_var());
       __ push(result_register());
       if (expr->is_compound()) {
         __ push(MemOperand(esp, kPointerSize));
@@ -1916,8 +1914,8 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
       break;
     case KEYED_SUPER_PROPERTY:
       VisitForStackValue(property->obj()->AsSuperReference()->this_var());
-      EmitLoadHomeObject(property->obj()->AsSuperReference());
-      __ Push(result_register());
+      VisitForStackValue(
+          property->obj()->AsSuperReference()->home_object_var());
       VisitForAccumulatorValue(property->key());
       __ Push(result_register());
       if (expr->is_compound()) {
@@ -2540,7 +2538,8 @@ void FullCodeGenerator::EmitAssignment(Expression* expr) {
     case NAMED_SUPER_PROPERTY: {
       __ push(eax);
       VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
-      EmitLoadHomeObject(prop->obj()->AsSuperReference());
+      VisitForAccumulatorValue(
+          prop->obj()->AsSuperReference()->home_object_var());
       // stack: value, this; eax: home_object
       Register scratch = ecx;
       Register scratch2 = edx;
@@ -2556,8 +2555,7 @@ void FullCodeGenerator::EmitAssignment(Expression* expr) {
     case KEYED_SUPER_PROPERTY: {
       __ push(eax);
       VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
-      EmitLoadHomeObject(prop->obj()->AsSuperReference());
-      __ push(result_register());
+      VisitForStackValue(prop->obj()->AsSuperReference()->home_object_var());
       VisitForAccumulatorValue(prop->key());
       Register scratch = ecx;
       Register scratch2 = edx;
@@ -2768,8 +2766,7 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
       EmitNamedPropertyLoad(expr);
     } else {
       VisitForStackValue(expr->obj()->AsSuperReference()->this_var());
-      EmitLoadHomeObject(expr->obj()->AsSuperReference());
-      __ push(result_register());
+      VisitForStackValue(expr->obj()->AsSuperReference()->home_object_var());
       EmitNamedSuperPropertyLoad(expr);
     }
   } else {
@@ -2781,8 +2778,7 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
       EmitKeyedPropertyLoad(expr);
     } else {
       VisitForStackValue(expr->obj()->AsSuperReference()->this_var());
-      EmitLoadHomeObject(expr->obj()->AsSuperReference());
-      __ push(result_register());
+      VisitForStackValue(expr->obj()->AsSuperReference()->home_object_var());
       VisitForStackValue(expr->key());
       EmitKeyedSuperPropertyLoad(expr);
     }
@@ -2841,8 +2837,7 @@ void FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) {
   DCHECK(!key->value()->IsSmi());
   // Load the function from the receiver.
   SuperReference* super_ref = callee->AsProperty()->obj()->AsSuperReference();
-  EmitLoadHomeObject(super_ref);
-  __ push(eax);
+  VisitForStackValue(super_ref->home_object_var());
   VisitForAccumulatorValue(super_ref->this_var());
   __ push(eax);
   __ push(eax);
@@ -2898,8 +2893,7 @@ void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) {
   SetSourcePosition(prop->position());
   // Load the function from the receiver.
   SuperReference* super_ref = callee->AsProperty()->obj()->AsSuperReference();
-  EmitLoadHomeObject(super_ref);
-  __ push(eax);
+  VisitForStackValue(super_ref->home_object_var());
   VisitForAccumulatorValue(super_ref->this_var());
   __ push(eax);
   __ push(eax);
@@ -4771,7 +4765,8 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
 
       case NAMED_SUPER_PROPERTY: {
         VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
-        EmitLoadHomeObject(prop->obj()->AsSuperReference());
+        VisitForAccumulatorValue(
+            prop->obj()->AsSuperReference()->home_object_var());
         __ push(result_register());
         __ push(MemOperand(esp, kPointerSize));
         __ push(result_register());
@@ -4781,8 +4776,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
 
       case KEYED_SUPER_PROPERTY: {
         VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
-        EmitLoadHomeObject(prop->obj()->AsSuperReference());
-        __ push(result_register());
+        VisitForStackValue(prop->obj()->AsSuperReference()->home_object_var());
         VisitForAccumulatorValue(prop->key());
         __ push(result_register());
         __ push(MemOperand(esp, 2 * kPointerSize));
index f16030539d4258fe01162638558715ccfb10bb92..eaddb87f4921c3477fe042a78b84b4096c522ae6 100644 (file)
@@ -251,6 +251,11 @@ void FullCodeGenerator::Generate() {
     }
   }
 
+  Variable* home_object_var = scope()->home_object_var();
+  if (home_object_var != nullptr) {
+    __ Push(a1);
+  }
+
   ArgumentsAccessStub::HasNewTarget has_new_target =
       IsSubclassConstructor(info->function()->kind())
           ? ArgumentsAccessStub::HAS_NEW_TARGET
@@ -317,6 +322,19 @@ void FullCodeGenerator::Generate() {
     SetVar(arguments, v0, a1, a2);
   }
 
+  // Possibly set up a local binding to the [[HomeObject]].
+  if (home_object_var != nullptr) {
+    Comment cmnt(masm_, "[ Home object");
+    __ Pop(LoadDescriptor::ReceiverRegister());
+    Handle<Symbol> home_object_symbol(isolate()->heap()->home_object_symbol());
+    __ li(LoadDescriptor::NameRegister(), Operand(home_object_symbol));
+    __ li(LoadDescriptor::SlotRegister(),
+          Operand(SmiFromSlot(function()->HomeObjectFeedbackSlot())));
+    CallLoadIC(NOT_CONTEXTUAL);
+
+    SetVar(home_object_var, v0, a1, a2);
+  }
+
   if (FLAG_trace) {
     __ CallRuntime(Runtime::kTraceEnter, 0);
   }
@@ -1313,26 +1331,6 @@ void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
 }
 
 
-void FullCodeGenerator::EmitLoadHomeObject(SuperReference* expr) {
-  Comment cnmt(masm_, "[ SuperReference ");
-
-  __ lw(LoadDescriptor::ReceiverRegister(),
-        MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
-
-  Handle<Symbol> home_object_symbol(isolate()->heap()->home_object_symbol());
-  __ li(LoadDescriptor::NameRegister(), home_object_symbol);
-
-  __ li(LoadDescriptor::SlotRegister(),
-        Operand(SmiFromSlot(expr->HomeObjectFeedbackSlot())));
-  CallLoadIC(NOT_CONTEXTUAL);
-
-  Label done;
-  __ Branch(&done, ne, v0, Operand(isolate()->factory()->undefined_value()));
-  __ CallRuntime(Runtime::kThrowNonMethodError, 0);
-  __ bind(&done);
-}
-
-
 void FullCodeGenerator::EmitSetHomeObjectIfNeeded(Expression* initializer,
                                                   int offset) {
   if (NeedsHomeObject(initializer)) {
@@ -1966,7 +1964,8 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
       break;
     case NAMED_SUPER_PROPERTY:
       VisitForStackValue(property->obj()->AsSuperReference()->this_var());
-      EmitLoadHomeObject(property->obj()->AsSuperReference());
+      VisitForAccumulatorValue(
+          property->obj()->AsSuperReference()->home_object_var());
       __ Push(result_register());
       if (expr->is_compound()) {
         const Register scratch = a1;
@@ -1977,7 +1976,8 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
     case KEYED_SUPER_PROPERTY: {
       const Register scratch = a1;
       VisitForStackValue(property->obj()->AsSuperReference()->this_var());
-      EmitLoadHomeObject(property->obj()->AsSuperReference());
+      VisitForAccumulatorValue(
+          property->obj()->AsSuperReference()->home_object_var());
       __ Move(scratch, result_register());
       VisitForAccumulatorValue(property->key());
       __ Push(scratch, result_register());
@@ -2610,7 +2610,8 @@ void FullCodeGenerator::EmitAssignment(Expression* expr) {
     case NAMED_SUPER_PROPERTY: {
       __ Push(v0);
       VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
-      EmitLoadHomeObject(prop->obj()->AsSuperReference());
+      VisitForAccumulatorValue(
+          prop->obj()->AsSuperReference()->home_object_var());
       // stack: value, this; v0: home_object
       Register scratch = a2;
       Register scratch2 = a3;
@@ -2626,8 +2627,7 @@ void FullCodeGenerator::EmitAssignment(Expression* expr) {
     case KEYED_SUPER_PROPERTY: {
       __ Push(v0);
       VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
-      EmitLoadHomeObject(prop->obj()->AsSuperReference());
-      __ Push(result_register());
+      VisitForStackValue(prop->obj()->AsSuperReference()->home_object_var());
       VisitForAccumulatorValue(prop->key());
       Register scratch = a2;
       Register scratch2 = a3;
@@ -2844,8 +2844,7 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
       EmitNamedPropertyLoad(expr);
     } else {
       VisitForStackValue(expr->obj()->AsSuperReference()->this_var());
-      EmitLoadHomeObject(expr->obj()->AsSuperReference());
-      __ Push(result_register());
+      VisitForStackValue(expr->obj()->AsSuperReference()->home_object_var());
       EmitNamedSuperPropertyLoad(expr);
     }
   } else {
@@ -2857,8 +2856,7 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
       EmitKeyedPropertyLoad(expr);
     } else {
       VisitForStackValue(expr->obj()->AsSuperReference()->this_var());
-      EmitLoadHomeObject(expr->obj()->AsSuperReference());
-      __ Push(result_register());
+      VisitForStackValue(expr->obj()->AsSuperReference()->home_object_var());
       VisitForStackValue(expr->key());
       EmitKeyedSuperPropertyLoad(expr);
     }
@@ -2921,7 +2919,7 @@ void FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) {
   // Load the function from the receiver.
   const Register scratch = a1;
   SuperReference* super_ref = prop->obj()->AsSuperReference();
-  EmitLoadHomeObject(super_ref);
+  VisitForAccumulatorValue(super_ref->home_object_var());
   __ mov(scratch, v0);
   VisitForAccumulatorValue(super_ref->this_var());
   __ Push(scratch, v0, v0, scratch);
@@ -2979,7 +2977,7 @@ void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) {
   // Load the function from the receiver.
   const Register scratch = a1;
   SuperReference* super_ref = prop->obj()->AsSuperReference();
-  EmitLoadHomeObject(super_ref);
+  VisitForAccumulatorValue(super_ref->home_object_var());
   __ Move(scratch, v0);
   VisitForAccumulatorValue(super_ref->this_var());
   __ Push(scratch, v0, v0, scratch);
@@ -4851,7 +4849,8 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
 
       case NAMED_SUPER_PROPERTY: {
         VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
-        EmitLoadHomeObject(prop->obj()->AsSuperReference());
+        VisitForAccumulatorValue(
+            prop->obj()->AsSuperReference()->home_object_var());
         __ Push(result_register());
         const Register scratch = a1;
         __ lw(scratch, MemOperand(sp, kPointerSize));
@@ -4862,7 +4861,8 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
 
       case KEYED_SUPER_PROPERTY: {
         VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
-        EmitLoadHomeObject(prop->obj()->AsSuperReference());
+        VisitForAccumulatorValue(
+            prop->obj()->AsSuperReference()->home_object_var());
         const Register scratch = a1;
         const Register scratch1 = t0;
         __ Move(scratch, result_register());
index e4f0c7f12492279d89f09192b3a659a408e3a757..2f6036e05eb03046705892723367607bfd1b0db8 100644 (file)
@@ -248,6 +248,11 @@ void FullCodeGenerator::Generate() {
     }
   }
 
+  Variable* home_object_var = scope()->home_object_var();
+  if (home_object_var != nullptr) {
+    __ Push(a1);
+  }
+
   ArgumentsAccessStub::HasNewTarget has_new_target =
       IsSubclassConstructor(info->function()->kind())
           ? ArgumentsAccessStub::HAS_NEW_TARGET
@@ -314,6 +319,19 @@ void FullCodeGenerator::Generate() {
     SetVar(arguments, v0, a1, a2);
   }
 
+  // Possibly set up a local binding to the [[HomeObject]].
+  if (home_object_var != nullptr) {
+    Comment cmnt(masm_, "[ Home object");
+    __ pop(LoadDescriptor::ReceiverRegister());
+    Handle<Symbol> home_object_symbol(isolate()->heap()->home_object_symbol());
+    __ li(LoadDescriptor::NameRegister(), home_object_symbol);
+    __ li(LoadDescriptor::SlotRegister(),
+          Operand(SmiFromSlot(function()->HomeObjectFeedbackSlot())));
+    CallLoadIC(NOT_CONTEXTUAL);
+
+    SetVar(home_object_var, v0, a1, a2);
+  }
+
   if (FLAG_trace) {
     __ CallRuntime(Runtime::kTraceEnter, 0);
   }
@@ -1310,26 +1328,6 @@ void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
 }
 
 
-void FullCodeGenerator::EmitLoadHomeObject(SuperReference* expr) {
-  Comment cnmt(masm_, "[ SuperReference ");
-
-  __ ld(LoadDescriptor::ReceiverRegister(),
-        MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
-
-  Handle<Symbol> home_object_symbol(isolate()->heap()->home_object_symbol());
-  __ li(LoadDescriptor::NameRegister(), home_object_symbol);
-
-  __ li(LoadDescriptor::SlotRegister(),
-        Operand(SmiFromSlot(expr->HomeObjectFeedbackSlot())));
-  CallLoadIC(NOT_CONTEXTUAL);
-
-  Label done;
-  __ Branch(&done, ne, v0, Operand(isolate()->factory()->undefined_value()));
-  __ CallRuntime(Runtime::kThrowNonMethodError, 0);
-  __ bind(&done);
-}
-
-
 void FullCodeGenerator::EmitSetHomeObjectIfNeeded(Expression* initializer,
                                                   int offset) {
   if (NeedsHomeObject(initializer)) {
@@ -1965,7 +1963,8 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
       break;
     case NAMED_SUPER_PROPERTY:
       VisitForStackValue(property->obj()->AsSuperReference()->this_var());
-      EmitLoadHomeObject(property->obj()->AsSuperReference());
+      VisitForAccumulatorValue(
+          property->obj()->AsSuperReference()->home_object_var());
       __ Push(result_register());
       if (expr->is_compound()) {
         const Register scratch = a1;
@@ -1976,7 +1975,8 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
     case KEYED_SUPER_PROPERTY: {
       const Register scratch = a1;
       VisitForStackValue(property->obj()->AsSuperReference()->this_var());
-      EmitLoadHomeObject(property->obj()->AsSuperReference());
+      VisitForAccumulatorValue(
+          property->obj()->AsSuperReference()->home_object_var());
       __ Move(scratch, result_register());
       VisitForAccumulatorValue(property->key());
       __ Push(scratch, result_register());
@@ -2609,7 +2609,8 @@ void FullCodeGenerator::EmitAssignment(Expression* expr) {
     case NAMED_SUPER_PROPERTY: {
       __ Push(v0);
       VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
-      EmitLoadHomeObject(prop->obj()->AsSuperReference());
+      VisitForAccumulatorValue(
+          prop->obj()->AsSuperReference()->home_object_var());
       // stack: value, this; v0: home_object
       Register scratch = a2;
       Register scratch2 = a3;
@@ -2625,8 +2626,7 @@ void FullCodeGenerator::EmitAssignment(Expression* expr) {
     case KEYED_SUPER_PROPERTY: {
       __ Push(v0);
       VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
-      EmitLoadHomeObject(prop->obj()->AsSuperReference());
-      __ Push(result_register());
+      VisitForStackValue(prop->obj()->AsSuperReference()->home_object_var());
       VisitForAccumulatorValue(prop->key());
       Register scratch = a2;
       Register scratch2 = a3;
@@ -2847,8 +2847,7 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
       EmitNamedPropertyLoad(expr);
     } else {
       VisitForStackValue(expr->obj()->AsSuperReference()->this_var());
-      EmitLoadHomeObject(expr->obj()->AsSuperReference());
-      __ Push(result_register());
+      VisitForStackValue(expr->obj()->AsSuperReference()->home_object_var());
       EmitNamedSuperPropertyLoad(expr);
     }
   } else {
@@ -2860,8 +2859,7 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
       EmitKeyedPropertyLoad(expr);
     } else {
       VisitForStackValue(expr->obj()->AsSuperReference()->this_var());
-      EmitLoadHomeObject(expr->obj()->AsSuperReference());
-      __ Push(result_register());
+      VisitForStackValue(expr->obj()->AsSuperReference()->home_object_var());
       VisitForStackValue(expr->key());
       EmitKeyedSuperPropertyLoad(expr);
     }
@@ -2924,7 +2922,7 @@ void FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) {
   // Load the function from the receiver.
   const Register scratch = a1;
   SuperReference* super_ref = prop->obj()->AsSuperReference();
-  EmitLoadHomeObject(super_ref);
+  VisitForAccumulatorValue(super_ref->home_object_var());
   __ mov(scratch, v0);
   VisitForAccumulatorValue(super_ref->this_var());
   __ Push(scratch, v0, v0, scratch);
@@ -2982,7 +2980,7 @@ void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) {
   // Load the function from the receiver.
   const Register scratch = a1;
   SuperReference* super_ref = prop->obj()->AsSuperReference();
-  EmitLoadHomeObject(super_ref);
+  VisitForAccumulatorValue(super_ref->home_object_var());
   __ Move(scratch, v0);
   VisitForAccumulatorValue(super_ref->this_var());
   __ Push(scratch, v0, v0, scratch);
@@ -4854,7 +4852,8 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
 
       case NAMED_SUPER_PROPERTY: {
         VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
-        EmitLoadHomeObject(prop->obj()->AsSuperReference());
+        VisitForAccumulatorValue(
+            prop->obj()->AsSuperReference()->home_object_var());
         __ Push(result_register());
         const Register scratch = a1;
         __ ld(scratch, MemOperand(sp, kPointerSize));
@@ -4865,7 +4864,8 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
 
       case KEYED_SUPER_PROPERTY: {
         VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
-        EmitLoadHomeObject(prop->obj()->AsSuperReference());
+        VisitForAccumulatorValue(
+            prop->obj()->AsSuperReference()->home_object_var());
         const Register scratch = a1;
         const Register scratch1 = a4;
         __ Move(scratch, result_register());
index ee0f7dc6804848109197ed9878835d791e3d77f4..196853c0236e3b8fca9d2dca5f67481138d9fa17 100644 (file)
@@ -749,8 +749,13 @@ Expression* ParserTraits::ThisExpression(Scope* scope, AstNodeFactory* factory,
 
 Expression* ParserTraits::SuperReference(Scope* scope, AstNodeFactory* factory,
                                          int pos) {
+  // TODO(arv): Split into SuperProperty and SuperCall?
+  VariableProxy* home_object_proxy = scope->NewUnresolved(
+      factory, parser_->ast_value_factory()->home_object_string(),
+      Variable::NORMAL, pos);
+
   return factory->NewSuperReference(
-      ThisExpression(scope, factory, pos)->AsVariableProxy(),
+      ThisExpression(scope, factory, pos)->AsVariableProxy(), home_object_proxy,
       pos);
 }
 
@@ -1138,7 +1143,8 @@ FunctionLiteral* Parser::ParseLazy(Isolate* isolate, ParseInfo* info,
     bool ok = true;
 
     if (shared_info->is_arrow()) {
-      Scope* scope = NewScope(scope_, ARROW_SCOPE);
+      Scope* scope =
+          NewScope(scope_, ARROW_SCOPE, FunctionKind::kArrowFunction);
       scope->set_start_position(shared_info->start_position());
       ExpressionClassifier formals_classifier;
       bool has_rest = false;
index cda26df2803a1d6290bec2e279c3150ef84523bb..eba677c94bb945da45e6f2b4f3fbc3fbbc3e2845 100644 (file)
@@ -724,8 +724,7 @@ class ParserTraits {
 
   Expression* ThisExpression(Scope* scope, AstNodeFactory* factory,
                              int pos = RelocInfo::kNoPosition);
-  Expression* SuperReference(Scope* scope, AstNodeFactory* factory,
-                             int pos = RelocInfo::kNoPosition);
+  Expression* SuperReference(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 3dca827c92738d398bb2dd2639d81a19ca082f34..2644b4374ad8c16deb50ee22db604f045a3d6fd3 100644 (file)
@@ -110,7 +110,7 @@ PreParser::PreParseResult PreParser::PreParseLazyFunction(
   FunctionState top_state(&function_state_, &scope_, top_scope, kNormalFunction,
                           &top_factory);
   scope_->SetLanguageMode(language_mode);
-  Scope* function_scope = NewScope(scope_, FUNCTION_SCOPE);
+  Scope* function_scope = NewScope(scope_, FUNCTION_SCOPE, kind);
   PreParserFactory function_factory(NULL);
   FunctionState function_state(&function_state_, &scope_, function_scope, kind,
                                &function_factory);
@@ -1028,7 +1028,7 @@ PreParser::Expression PreParser::ParseFunctionLiteral(
 
   // Parse function body.
   bool outer_is_script_scope = scope_->is_script_scope();
-  Scope* function_scope = NewScope(scope_, FUNCTION_SCOPE);
+  Scope* function_scope = NewScope(scope_, FUNCTION_SCOPE, kind);
   PreParserFactory factory(NULL);
   FunctionState function_state(&function_state_, &scope_, function_scope, kind,
                                &factory);
index d38aaaaa26e7f1fa3876c041b708d123c054660a..2fe5db1d08e9e0f1b63d68c69950ca29ae31371a 100644 (file)
@@ -339,12 +339,17 @@ class ParserBase : public Traits {
     Mode old_mode_;
   };
 
-  Scope* NewScope(Scope* parent, ScopeType scope_type,
-                  FunctionKind kind = kNormalFunction) {
+  Scope* NewScope(Scope* parent, ScopeType scope_type) {
+    // Must always pass the function kind for FUNCTION_SCOPE and ARROW_SCOPE.
+    DCHECK(scope_type != FUNCTION_SCOPE);
+    DCHECK(scope_type != ARROW_SCOPE);
+    return NewScope(parent, scope_type, kNormalFunction);
+  }
+
+  Scope* NewScope(Scope* parent, ScopeType scope_type, FunctionKind kind) {
     DCHECK(ast_value_factory());
     DCHECK(scope_type != MODULE_SCOPE || allow_harmony_modules());
-    DCHECK((scope_type == FUNCTION_SCOPE && IsValidFunctionKind(kind)) ||
-           kind == kNormalFunction);
+    DCHECK(scope_type != ARROW_SCOPE || IsArrowFunction(kind));
     Scope* result = new (zone())
         Scope(zone(), parent, scope_type, ast_value_factory(), kind);
     result->Initialize();
@@ -1711,7 +1716,8 @@ class PreParserTraits {
   }
 
   static PreParserExpression SuperReference(Scope* scope,
-                                            PreParserFactory* factory) {
+                                            PreParserFactory* factory,
+                                            int pos) {
     return PreParserExpression::Default();
   }
 
@@ -2393,7 +2399,8 @@ ParserBase<Traits>::ParsePrimaryExpression(ExpressionClassifier* classifier,
         classifier->RecordBindingPatternError(scanner()->location(),
                                               MessageTemplate::kUnexpectedToken,
                                               Token::String(Token::RPAREN));
-        Scope* scope = this->NewScope(scope_, ARROW_SCOPE);
+        Scope* scope =
+            this->NewScope(scope_, ARROW_SCOPE, FunctionKind::kArrowFunction);
         scope->set_start_position(beg_pos);
         ExpressionClassifier args_classifier;
         bool has_rest = false;
@@ -2920,7 +2927,8 @@ ParserBase<Traits>::ParseAssignmentExpression(bool accept_IN,
                                   CHECK_OK);
     Scanner::Location loc(lhs_location.beg_pos, scanner()->location().end_pos);
     bool has_rest = false;
-    Scope* scope = this->NewScope(scope_, ARROW_SCOPE);
+    Scope* scope =
+        this->NewScope(scope_, ARROW_SCOPE, FunctionKind::kArrowFunction);
     scope->set_start_position(lhs_location.beg_pos);
     Scanner::Location duplicate_loc = Scanner::Location::invalid();
     this->ParseArrowFunctionFormalParameters(scope, expression, loc, &has_rest,
@@ -3507,7 +3515,7 @@ ParserBase<Traits>::ParseStrongSuperCallExpression(
   Consume(Token::SUPER);
   int pos = position();
   Scanner::Location super_loc = scanner()->location();
-  ExpressionT expr = this->SuperReference(scope_, factory());
+  ExpressionT expr = this->SuperReference(scope_, factory(), pos);
 
   if (peek() != Token::LPAREN) {
     ReportMessage(MessageTemplate::kStrongConstructorSuper);
@@ -3556,21 +3564,23 @@ typename ParserBase<Traits>::ExpressionT
 ParserBase<Traits>::ParseSuperExpression(bool is_new,
                                          ExpressionClassifier* classifier,
                                          bool* ok) {
+  int pos = position();
   Expect(Token::SUPER, CHECK_OK);
 
-  // TODO(wingo): Does this actually work with lazily compiled arrows?
-  FunctionState* function_state = function_state_;
-  while (IsArrowFunction(function_state->kind())) {
-    function_state = function_state->outer();
+  Scope* scope = scope_->DeclarationScope();
+
+  while (scope->is_eval_scope() || scope->is_arrow_scope()) {
+    scope = scope->outer_scope();
+    DCHECK_NOT_NULL(scope);
+    scope = scope->DeclarationScope();
   }
-  // TODO(arv): Handle eval scopes similarly.
 
-  FunctionKind kind = function_state->kind();
+  FunctionKind kind = scope->function_kind();
   if (IsConciseMethod(kind) || IsAccessorFunction(kind) ||
       i::IsConstructor(kind)) {
     if (peek() == Token::PERIOD || peek() == Token::LBRACK) {
-      scope_->RecordSuperPropertyUsage();
-      return this->SuperReference(scope_, factory());
+      scope->RecordSuperPropertyUsage();
+      return this->SuperReference(scope_, factory(), pos);
     }
     // new super() is never allowed.
     // super() is only allowed in derived constructor
@@ -3582,8 +3592,10 @@ ParserBase<Traits>::ParseSuperExpression(bool is_new,
         *ok = false;
         return this->EmptyExpression();
       }
-      function_state->set_super_location(scanner()->location());
-      return this->SuperReference(scope_, factory());
+      // 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);
     }
   }
 
index 60c14dbdc8d752af1cb209897c97eb7d944f553e..21a8805c54aad396364829e66110c72752cfd3c2 100644 (file)
@@ -154,12 +154,13 @@ void Scope::SetDefaults(ScopeType scope_type, Scope* outer_scope,
   function_kind_ = function_kind;
   block_scope_is_class_scope_ = false;
   scope_name_ = ast_value_factory_->empty_string();
-  dynamics_ = NULL;
-  receiver_ = NULL;
+  dynamics_ = nullptr;
+  receiver_ = nullptr;
   new_target_ = nullptr;
-  function_ = NULL;
-  arguments_ = NULL;
-  illegal_redecl_ = NULL;
+  function_ = nullptr;
+  arguments_ = nullptr;
+  home_object_ = nullptr;
+  illegal_redecl_ = nullptr;
   scope_inside_with_ = false;
   scope_contains_with_ = false;
   scope_calls_eval_ = false;
@@ -172,7 +173,6 @@ void Scope::SetDefaults(ScopeType scope_type, Scope* outer_scope,
   outer_scope_calls_sloppy_eval_ = false;
   inner_scope_calls_eval_ = false;
   inner_scope_uses_arguments_ = false;
-  inner_scope_uses_super_property_ = false;
   force_eager_compilation_ = false;
   force_context_allocation_ = (outer_scope != NULL && !is_function_scope())
       ? outer_scope->has_forced_context_allocation() : false;
@@ -337,6 +337,17 @@ void Scope::Initialize() {
                        Variable::ARGUMENTS,
                        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);
+  }
 }
 
 
@@ -929,8 +940,6 @@ void Scope::Print(int n) {
   if (inner_scope_uses_arguments_) {
     Indent(n1, "// inner scope uses 'arguments'\n");
   }
-  if (inner_scope_uses_super_property_)
-    Indent(n1, "// inner scope uses 'super' property\n");
   if (outer_scope_calls_sloppy_eval_) {
     Indent(n1, "// outer scope calls 'eval' in sloppy context\n");
   }
@@ -1287,10 +1296,6 @@ void Scope::PropagateScopeInfo(bool outer_scope_calls_sloppy_eval ) {
       if (inner->scope_uses_arguments_ || inner->inner_scope_uses_arguments_) {
         inner_scope_uses_arguments_ = true;
       }
-      if (inner->scope_uses_super_property_ ||
-          inner->inner_scope_uses_super_property_) {
-        inner_scope_uses_super_property_ = true;
-      }
     }
     if (inner->force_eager_compilation_) {
       force_eager_compilation_ = true;
@@ -1398,6 +1403,18 @@ 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
index 01df8f9d77e2d355a3ab8b17a8f7b85d5cd31990..d56018532152909538635d95cdb50286ddfc0d34 100644 (file)
@@ -409,6 +409,16 @@ class Scope: public ZoneObject {
     return arguments_;
   }
 
+  // A local variable to the [[HomeObject]] used by methods if we need to
+  // allocate it; NULL otherwise.
+  Variable* home_object_var() const {
+    DCHECK(home_object_ == nullptr ||
+           (is_function_scope() && (IsConciseMethod(function_kind()) ||
+                                    IsAccessorFunction(function_kind()) ||
+                                    IsConstructor(function_kind()))));
+    return home_object_;
+  }
+
   // Declarations list.
   ZoneList<Declaration*>* declarations() { return &decls_; }
 
@@ -567,6 +577,8 @@ class Scope: public ZoneObject {
   Variable* new_target_;
   // Convenience variable; function scopes only.
   Variable* arguments_;
+  // Convenience variable; method scopes only.
+  Variable* home_object_;
   // Module descriptor; module scopes only.
   ModuleDescriptor* module_descriptor_;
 
index 74f69bbaf01a35c4e2fd0e72891c77edce12838c..efe5e8d77cc5dee413fca8ce759b79666ade2312 100644 (file)
@@ -234,6 +234,11 @@ void FullCodeGenerator::Generate() {
     }
   }
 
+  Variable* home_object_var = scope()->home_object_var();
+  if (home_object_var != nullptr) {
+    __ Push(rdi);
+  }
+
   ArgumentsAccessStub::HasNewTarget has_new_target =
       IsSubclassConstructor(info->function()->kind())
           ? ArgumentsAccessStub::HAS_NEW_TARGET
@@ -301,6 +306,20 @@ void FullCodeGenerator::Generate() {
     SetVar(arguments, rax, rbx, rdx);
   }
 
+  // Possibly set up a local binding to the [[HomeObject]].
+  // Variable* home_object_var = scope()->home_object_var();
+  if (home_object_var != nullptr) {
+    Comment cmnt(masm_, "[ Home object");
+    __ Pop(LoadDescriptor::ReceiverRegister());
+    Handle<Symbol> home_object_symbol(isolate()->heap()->home_object_symbol());
+    __ Move(LoadDescriptor::NameRegister(), home_object_symbol);
+    __ Move(LoadDescriptor::SlotRegister(),
+            SmiFromSlot(function()->HomeObjectFeedbackSlot()));
+    CallLoadIC(NOT_CONTEXTUAL);
+
+    SetVar(home_object_var, rax, rbx, rdx);
+  }
+
   if (FLAG_trace) {
     __ CallRuntime(Runtime::kTraceEnter, 0);
   }
@@ -1285,27 +1304,6 @@ void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
 }
 
 
-void FullCodeGenerator::EmitLoadHomeObject(SuperReference* expr) {
-  Comment cnmt(masm_, "[ SuperReference ");
-
-  __ movp(LoadDescriptor::ReceiverRegister(),
-          Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
-
-  Handle<Symbol> home_object_symbol(isolate()->heap()->home_object_symbol());
-  __ Move(LoadDescriptor::NameRegister(), home_object_symbol);
-
-  __ Move(LoadDescriptor::SlotRegister(),
-          SmiFromSlot(expr->HomeObjectFeedbackSlot()));
-  CallLoadIC(NOT_CONTEXTUAL);
-
-  __ Cmp(rax, isolate()->factory()->undefined_value());
-  Label done;
-  __ j(not_equal, &done);
-  __ CallRuntime(Runtime::kThrowNonMethodError, 0);
-  __ bind(&done);
-}
-
-
 void FullCodeGenerator::EmitSetHomeObjectIfNeeded(Expression* initializer,
                                                   int offset) {
   if (NeedsHomeObject(initializer)) {
@@ -1939,7 +1937,8 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
       break;
     case NAMED_SUPER_PROPERTY:
       VisitForStackValue(property->obj()->AsSuperReference()->this_var());
-      EmitLoadHomeObject(property->obj()->AsSuperReference());
+      VisitForAccumulatorValue(
+          property->obj()->AsSuperReference()->home_object_var());
       __ Push(result_register());
       if (expr->is_compound()) {
         __ Push(MemOperand(rsp, kPointerSize));
@@ -1948,8 +1947,8 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
       break;
     case KEYED_SUPER_PROPERTY:
       VisitForStackValue(property->obj()->AsSuperReference()->this_var());
-      EmitLoadHomeObject(property->obj()->AsSuperReference());
-      __ Push(result_register());
+      VisitForStackValue(
+          property->obj()->AsSuperReference()->home_object_var());
       VisitForAccumulatorValue(property->key());
       __ Push(result_register());
       if (expr->is_compound()) {
@@ -2540,7 +2539,8 @@ void FullCodeGenerator::EmitAssignment(Expression* expr) {
     case NAMED_SUPER_PROPERTY: {
       __ Push(rax);
       VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
-      EmitLoadHomeObject(prop->obj()->AsSuperReference());
+      VisitForAccumulatorValue(
+          prop->obj()->AsSuperReference()->home_object_var());
       // stack: value, this; rax: home_object
       Register scratch = rcx;
       Register scratch2 = rdx;
@@ -2556,8 +2556,7 @@ void FullCodeGenerator::EmitAssignment(Expression* expr) {
     case KEYED_SUPER_PROPERTY: {
       __ Push(rax);
       VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
-      EmitLoadHomeObject(prop->obj()->AsSuperReference());
-      __ Push(result_register());
+      VisitForStackValue(prop->obj()->AsSuperReference()->home_object_var());
       VisitForAccumulatorValue(prop->key());
       Register scratch = rcx;
       Register scratch2 = rdx;
@@ -2765,8 +2764,7 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
       EmitNamedPropertyLoad(expr);
     } else {
       VisitForStackValue(expr->obj()->AsSuperReference()->this_var());
-      EmitLoadHomeObject(expr->obj()->AsSuperReference());
-      __ Push(result_register());
+      VisitForStackValue(expr->obj()->AsSuperReference()->home_object_var());
       EmitNamedSuperPropertyLoad(expr);
     }
   } else {
@@ -2778,8 +2776,7 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
       EmitKeyedPropertyLoad(expr);
     } else {
       VisitForStackValue(expr->obj()->AsSuperReference()->this_var());
-      EmitLoadHomeObject(expr->obj()->AsSuperReference());
-      __ Push(result_register());
+      VisitForStackValue(expr->obj()->AsSuperReference()->home_object_var());
       VisitForStackValue(expr->key());
       EmitKeyedSuperPropertyLoad(expr);
     }
@@ -2838,8 +2835,7 @@ void FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) {
   DCHECK(!key->value()->IsSmi());
   // Load the function from the receiver.
   SuperReference* super_ref = prop->obj()->AsSuperReference();
-  EmitLoadHomeObject(super_ref);
-  __ Push(rax);
+  VisitForStackValue(super_ref->home_object_var());
   VisitForAccumulatorValue(super_ref->this_var());
   __ Push(rax);
   __ Push(rax);
@@ -2896,8 +2892,7 @@ void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) {
   SetSourcePosition(prop->position());
   // Load the function from the receiver.
   SuperReference* super_ref = prop->obj()->AsSuperReference();
-  EmitLoadHomeObject(super_ref);
-  __ Push(rax);
+  VisitForStackValue(super_ref->home_object_var());
   VisitForAccumulatorValue(super_ref->this_var());
   __ Push(rax);
   __ Push(rax);
@@ -4791,7 +4786,8 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
 
       case NAMED_SUPER_PROPERTY: {
         VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
-        EmitLoadHomeObject(prop->obj()->AsSuperReference());
+        VisitForAccumulatorValue(
+            prop->obj()->AsSuperReference()->home_object_var());
         __ Push(result_register());
         __ Push(MemOperand(rsp, kPointerSize));
         __ Push(result_register());
@@ -4801,8 +4797,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
 
       case KEYED_SUPER_PROPERTY: {
         VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
-        EmitLoadHomeObject(prop->obj()->AsSuperReference());
-        __ Push(result_register());
+        VisitForStackValue(prop->obj()->AsSuperReference()->home_object_var());
         VisitForAccumulatorValue(prop->key());
         __ Push(result_register());
         __ Push(MemOperand(rsp, 2 * kPointerSize));
index 57704f9c1ee023364c00eed7eda6aa7a2beda1f0..e62517a25fc1da292cf714a5f195c03c21c6c6e3 100644 (file)
@@ -310,10 +310,10 @@ TEST(FeedbackVectorPreservedAcrossRecompiles) {
 
   // Verify that we gathered feedback.
   int expected_slots = 0;
-  int expected_ic_slots = 1;
+  int expected_ic_slots = 2;
   CHECK_EQ(expected_slots, feedback_vector->Slots());
   CHECK_EQ(expected_ic_slots, feedback_vector->ICSlots());
-  FeedbackVectorICSlot slot_for_a(0);
+  FeedbackVectorICSlot slot_for_a(1);
   Object* object = feedback_vector->Get(slot_for_a);
   CHECK(object->IsWeakCell() &&
         WeakCell::cast(object)->value()->IsJSFunction());
@@ -362,7 +362,7 @@ TEST(FeedbackVectorUnaffectedByScopeChanges) {
   // Now a feedback vector is allocated.
   CHECK(f->shared()->is_compiled());
   int expected_slots = 0;
-  int expected_ic_slots = 2;
+  int expected_ic_slots = 3;
   CHECK_EQ(expected_slots, f->shared()->feedback_vector()->Slots());
   CHECK_EQ(expected_ic_slots, f->shared()->feedback_vector()->ICSlots());
 }
index 0750f82b89f5ccaa8b36efb18ebc24c1229c5115..f1f894e02d7b8c8e1eff063e2abb90a34f975f1a 100644 (file)
@@ -173,7 +173,7 @@ TEST(VectorICProfilerStatistics) {
   CHECK_EQ(0, feedback_info->ic_generic_count());
   Handle<TypeFeedbackVector> feedback_vector =
       handle(f->shared()->feedback_vector(), isolate);
-  int ic_slot = 0;
+  int ic_slot = 1;
   CallICNexus nexus(feedback_vector, FeedbackVectorICSlot(ic_slot));
   CHECK_EQ(1, feedback_vector->ic_with_type_info_count());
   CHECK_EQ(0, feedback_vector->ic_generic_count());
@@ -222,7 +222,7 @@ TEST(VectorCallICStates) {
   // There should be one IC.
   Handle<TypeFeedbackVector> feedback_vector =
       Handle<TypeFeedbackVector>(f->shared()->feedback_vector(), isolate);
-  FeedbackVectorICSlot slot(0);
+  FeedbackVectorICSlot slot(1);
   CallICNexus nexus(feedback_vector, slot);
   CHECK_EQ(MONOMORPHIC, nexus.StateFromFeedback());
   // CallIC doesn't return map feedback.
@@ -264,7 +264,7 @@ TEST(VectorLoadICStates) {
   // There should be one IC.
   Handle<TypeFeedbackVector> feedback_vector =
       Handle<TypeFeedbackVector>(f->shared()->feedback_vector(), isolate);
-  FeedbackVectorICSlot slot(0);
+  FeedbackVectorICSlot slot(1);
   LoadICNexus nexus(feedback_vector, slot);
   CHECK_EQ(PREMONOMORPHIC, nexus.StateFromFeedback());
 
@@ -322,8 +322,8 @@ TEST(VectorLoadICSlotSharing) {
   // There should be one IC slot.
   Handle<TypeFeedbackVector> feedback_vector =
       Handle<TypeFeedbackVector>(f->shared()->feedback_vector(), isolate);
-  CHECK_EQ(1, feedback_vector->ICSlots());
-  FeedbackVectorICSlot slot(0);
+  CHECK_EQ(2, feedback_vector->ICSlots());
+  FeedbackVectorICSlot slot(1);
   LoadICNexus nexus(feedback_vector, slot);
   CHECK_EQ(MONOMORPHIC, nexus.StateFromFeedback());
 }
@@ -346,7 +346,7 @@ TEST(VectorLoadICOnSmi) {
   // There should be one IC.
   Handle<TypeFeedbackVector> feedback_vector =
       Handle<TypeFeedbackVector>(f->shared()->feedback_vector(), isolate);
-  FeedbackVectorICSlot slot(0);
+  FeedbackVectorICSlot slot(1);
   LoadICNexus nexus(feedback_vector, slot);
   CHECK_EQ(PREMONOMORPHIC, nexus.StateFromFeedback());
 
index 9894eda42ff9db69b402827b229d04c6ad5956b8..fb113019d85abbea4b991e3d7481298b79f47f8c 100644 (file)
@@ -3322,10 +3322,10 @@ TEST(IncrementalMarkingPreservesMonomorphicCallIC) {
 
   Handle<TypeFeedbackVector> feedback_vector(f->shared()->feedback_vector());
 
-  int expected_slots = 2;
+  int expected_slots = 3;
   CHECK_EQ(expected_slots, feedback_vector->ICSlots());
-  int slot1 = 0;
-  int slot2 = 1;
+  int slot1 = 1;
+  int slot2 = 2;
   CHECK(feedback_vector->Get(FeedbackVectorICSlot(slot1))->IsWeakCell());
   CHECK(feedback_vector->Get(FeedbackVectorICSlot(slot2))->IsWeakCell());
 
@@ -3448,14 +3448,14 @@ TEST(IncrementalMarkingPreservesMonomorphicIC) {
               CcTest::global()->Get(v8_str("f"))));
 
   Code* ic_before = FindFirstIC(f->shared()->code(), Code::LOAD_IC);
-  CheckVectorIC(f, 0, MONOMORPHIC);
+  CheckVectorIC(f, 1, MONOMORPHIC);
   CHECK(ic_before->ic_state() == DEFAULT);
 
   SimulateIncrementalMarking(CcTest::heap());
   CcTest::heap()->CollectAllGarbage();
 
   Code* ic_after = FindFirstIC(f->shared()->code(), Code::LOAD_IC);
-  CheckVectorIC(f, 0, MONOMORPHIC);
+  CheckVectorIC(f, 1, MONOMORPHIC);
   CHECK(ic_after->ic_state() == DEFAULT);
 }
 
@@ -3480,7 +3480,7 @@ TEST(IncrementalMarkingClearsMonomorphicIC) {
       *v8::Handle<v8::Function>::Cast(CcTest::global()->Get(v8_str("f"))));
 
   Code* ic_before = FindFirstIC(f->shared()->code(), Code::LOAD_IC);
-  CheckVectorIC(f, 0, MONOMORPHIC);
+  CheckVectorIC(f, 1, MONOMORPHIC);
   CHECK(ic_before->ic_state() == DEFAULT);
 
   // Fire context dispose notification.
@@ -3489,7 +3489,7 @@ TEST(IncrementalMarkingClearsMonomorphicIC) {
   CcTest::heap()->CollectAllGarbage();
 
   Code* ic_after = FindFirstIC(f->shared()->code(), Code::LOAD_IC);
-  CheckVectorICCleared(f, 0);
+  CheckVectorICCleared(f, 1);
   CHECK(ic_after->ic_state() == DEFAULT);
 }
 
@@ -3521,7 +3521,7 @@ TEST(IncrementalMarkingPreservesPolymorphicIC) {
       *v8::Handle<v8::Function>::Cast(CcTest::global()->Get(v8_str("f"))));
 
   Code* ic_before = FindFirstIC(f->shared()->code(), Code::LOAD_IC);
-  CheckVectorIC(f, 0, POLYMORPHIC);
+  CheckVectorIC(f, 1, POLYMORPHIC);
   CHECK(ic_before->ic_state() == DEFAULT);
 
   // Fire context dispose notification.
@@ -3529,7 +3529,7 @@ TEST(IncrementalMarkingPreservesPolymorphicIC) {
   CcTest::heap()->CollectAllGarbage();
 
   Code* ic_after = FindFirstIC(f->shared()->code(), Code::LOAD_IC);
-  CheckVectorIC(f, 0, POLYMORPHIC);
+  CheckVectorIC(f, 1, POLYMORPHIC);
   CHECK(ic_after->ic_state() == DEFAULT);
 }
 
@@ -3561,7 +3561,7 @@ TEST(IncrementalMarkingClearsPolymorphicIC) {
       *v8::Handle<v8::Function>::Cast(CcTest::global()->Get(v8_str("f"))));
 
   Code* ic_before = FindFirstIC(f->shared()->code(), Code::LOAD_IC);
-  CheckVectorIC(f, 0, POLYMORPHIC);
+  CheckVectorIC(f, 1, POLYMORPHIC);
   CHECK(ic_before->ic_state() == DEFAULT);
 
   // Fire context dispose notification.
@@ -3569,7 +3569,7 @@ TEST(IncrementalMarkingClearsPolymorphicIC) {
   SimulateIncrementalMarking(CcTest::heap());
   CcTest::heap()->CollectAllGarbage();
 
-  CheckVectorICCleared(f, 0);
+  CheckVectorICCleared(f, 1);
   CHECK(ic_before->ic_state() == DEFAULT);
 }
 
@@ -4719,12 +4719,12 @@ TEST(MonomorphicStaysMonomorphicAfterGC) {
     CompileRun("(testIC())");
   }
   heap->CollectAllGarbage();
-  CheckIC(loadIC->code(), Code::LOAD_IC, loadIC->shared(), 0, MONOMORPHIC);
+  CheckIC(loadIC->code(), Code::LOAD_IC, loadIC->shared(), 1, MONOMORPHIC);
   {
     v8::HandleScope scope(CcTest::isolate());
     CompileRun("(testIC())");
   }
-  CheckIC(loadIC->code(), Code::LOAD_IC, loadIC->shared(), 0, MONOMORPHIC);
+  CheckIC(loadIC->code(), Code::LOAD_IC, loadIC->shared(), 1, MONOMORPHIC);
 }
 
 
@@ -4755,12 +4755,12 @@ TEST(PolymorphicStaysPolymorphicAfterGC) {
     CompileRun("(testIC())");
   }
   heap->CollectAllGarbage();
-  CheckIC(loadIC->code(), Code::LOAD_IC, loadIC->shared(), 0, POLYMORPHIC);
+  CheckIC(loadIC->code(), Code::LOAD_IC, loadIC->shared(), 1, POLYMORPHIC);
   {
     v8::HandleScope scope(CcTest::isolate());
     CompileRun("(testIC())");
   }
-  CheckIC(loadIC->code(), Code::LOAD_IC, loadIC->shared(), 0, POLYMORPHIC);
+  CheckIC(loadIC->code(), Code::LOAD_IC, loadIC->shared(), 1, POLYMORPHIC);
 }
 
 
index 03afabc29f2695f84c509c9a87036bd78fd30b40..ffc01ceb94421d39aef074c34690abd550637f97 100644 (file)
@@ -976,9 +976,9 @@ TEST(ScopeUsesArgumentsSuperThis) {
     SUPER_PROPERTY = 1 << 1,
     THIS = 1 << 2,
     INNER_ARGUMENTS = 1 << 3,
-    INNER_SUPER_PROPERTY = 1 << 4,
   };
 
+  // clang-format off
   static const struct {
     const char* body;
     int expected;
@@ -992,7 +992,7 @@ TEST(ScopeUsesArgumentsSuperThis) {
     {"return this + arguments[0] + super.x",
      ARGUMENTS | SUPER_PROPERTY | THIS},
     {"return x => this + x", THIS},
-    {"return x => super.f() + x", INNER_SUPER_PROPERTY},
+    {"return x => super.f() + x", SUPER_PROPERTY},
     {"this.foo = 42;", THIS},
     {"this.foo();", THIS},
     {"if (foo()) { this.f() }", THIS},
@@ -1018,15 +1018,15 @@ TEST(ScopeUsesArgumentsSuperThis) {
     {"\"use strict\"; while (true) { let x; this, arguments; }",
      INNER_ARGUMENTS | THIS},
     {"\"use strict\"; while (true) { let x; this, super.f(), arguments; }",
-     INNER_ARGUMENTS | INNER_SUPER_PROPERTY | THIS},
+     INNER_ARGUMENTS | SUPER_PROPERTY | THIS},
     {"\"use strict\"; if (foo()) { let x; this.f() }", THIS},
-    {"\"use strict\"; if (foo()) { let x; super.f() }",
-     INNER_SUPER_PROPERTY},
+    {"\"use strict\"; if (foo()) { let x; super.f() }", SUPER_PROPERTY},
     {"\"use strict\"; if (1) {"
      "  let x; return { m() { return this + super.m() + arguments } }"
      "}",
      NONE},
   };
+  // clang-format on
 
   i::Isolate* isolate = CcTest::i_isolate();
   i::Factory* factory = isolate->factory();
@@ -1042,7 +1042,6 @@ TEST(ScopeUsesArgumentsSuperThis) {
     for (unsigned i = 0; i < arraysize(source_data); ++i) {
       // Super property is only allowed in constructor and method.
       if (((source_data[i].expected & SUPER_PROPERTY) ||
-           (source_data[i].expected & INNER_SUPER_PROPERTY) ||
            (source_data[i].expected == NONE)) && j != 2) {
         continue;
       }
@@ -1090,8 +1089,6 @@ TEST(ScopeUsesArgumentsSuperThis) {
       }
       CHECK_EQ((source_data[i].expected & INNER_ARGUMENTS) != 0,
                scope->inner_uses_arguments());
-      CHECK_EQ((source_data[i].expected & INNER_SUPER_PROPERTY) != 0,
-               scope->inner_uses_super_property());
     }
   }
 }
index c2d456c8774eaf155aa4060e4a25271bb98b9095..3d713517ce14d0d50aa52396113e2f577018d871 100644 (file)
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// Flags: --harmony-classes --allow-natives-syntax
+// Flags: --harmony-classes --harmony-arrow-functions --allow-natives-syntax
 
 
 (function TestHomeObject() {
 
   assertEquals(42, o.g().next().value);
 })();
+
+
+(function TestSuperPropertyInEval() {
+  var y = 3;
+  var p  = {
+    m() { return 1; },
+    get x() { return 2; }
+  };
+  var o = {
+    __proto__: p,
+    eval() {
+      assertSame(super.x, eval('super.x'));
+      assertSame(super.m(), eval('super.m()'));
+      // Global eval.
+      assertThrows('super.x', SyntaxError);
+      assertThrows('super.m()', SyntaxError);
+      return eval('super.m()');
+    }
+  };
+  assertSame(1, o.eval());
+})();
+
+
+(function TestSuperPropertyInArrow() {
+  var y = 3;
+  var p  = {
+    m() { return 1; },
+    get x() { return 2; }
+  };
+  var o = {
+    __proto__: p,
+    arrow() {
+      assertSame(super.x, (() => super.x)());
+      assertSame(super.m(), (() => super.m())());
+      return (() => super.m())();
+    }
+  };
+  assertSame(1, o.arrow());
+})();
index 988cef22e2fdc959d2ae7de0878a48d748d44ac6..1af7ab2e234f97b3d48ef94935ab908a5cef034a 100644 (file)
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// Flags: --harmony-classes --allow-natives-syntax
+// Flags: --harmony-classes --harmony-arrow-functions --allow-natives-syntax
+
 
 (function TestSuperNamedLoads() {
   function Base() { }
@@ -2053,6 +2054,7 @@ TestKeyedSetterCreatingOwnPropertiesNonConfigurable(42, 43, 44);
   assertInstanceof(f, Number);
 }());
 
+
 (function TestSuperCallErrorCases() {
   'use strict';
   class T extends Object {
@@ -2064,3 +2066,44 @@ TestKeyedSetterCreatingOwnPropertiesNonConfigurable(42, 43, 44);
   T.__proto__ = null;
   assertThrows(function() { new T(); }, TypeError);
 }());
+
+
+(function TestSuperPropertyInEval() {
+  'use strict';
+  let y = 3;
+  class Base {
+    m() { return 1; }
+    get x() { return 2; }
+  }
+  class Derived extends Base {
+    eval() {
+      assertSame(super.x, eval('super.x'));
+      assertSame(super.m(), eval('super.m()'));
+      // Global eval.
+      assertThrows('super.x', SyntaxError);
+      assertThrows('super.m()', SyntaxError);
+      return eval('super.m()');
+    }
+  }
+  let d = new Derived();
+  assertSame(1, d.eval());
+})();
+
+
+(function TestSuperPropertyInArrow() {
+  'use strict';
+  let y = 3;
+  class Base {
+    m() { return 1; }
+    get x() { return 2; }
+  }
+  class Derived extends Base {
+    arrow() {
+      assertSame(super.x, (() => super.x)());
+      assertSame(super.m(), (() => super.m())());
+      return (() => super.m())();
+    }
+  }
+  let d = new Derived();
+  assertSame(1, d.arrow());
+})();