Revert "Revert "Upgrade to 5.0.71.48"" DO NOT MERGE

This reverts commit f2e3994fa5148cc3d9946666f0b0596290192b0e,
and updates the x64 makefile properly so it doesn't break that
build.

FPIIM-449

Change-Id: Ib83e35bfbae6af627451c926a9650ec57c045605
(cherry picked from commit 109988c7ccb6f3fd1a58574fa3dfb88beaef6632)
diff --git a/src/ast/ast-expression-rewriter.cc b/src/ast/ast-expression-rewriter.cc
index 49cc7f6..edee91d 100644
--- a/src/ast/ast-expression-rewriter.cc
+++ b/src/ast/ast-expression-rewriter.cc
@@ -398,10 +398,10 @@
 }
 
 
-void AstExpressionRewriter::VisitRewritableAssignmentExpression(
-    RewritableAssignmentExpression* node) {
+void AstExpressionRewriter::VisitRewritableExpression(
+    RewritableExpression* node) {
   REWRITE_THIS(node);
-  AST_REWRITE_PROPERTY(Expression, node, expression);
+  AST_REWRITE(Expression, node->expression(), node->Rewrite(replacement));
 }
 
 
diff --git a/src/ast/ast-expression-rewriter.h b/src/ast/ast-expression-rewriter.h
index 916842a..1da3fa8 100644
--- a/src/ast/ast-expression-rewriter.h
+++ b/src/ast/ast-expression-rewriter.h
@@ -8,9 +8,7 @@
 #include "src/allocation.h"
 #include "src/ast/ast.h"
 #include "src/ast/scopes.h"
-#include "src/effects.h"
 #include "src/type-info.h"
-#include "src/types.h"
 #include "src/zone.h"
 
 namespace v8 {
diff --git a/src/ast/ast-expression-visitor.cc b/src/ast/ast-expression-visitor.cc
index 6b2550c..dbf4ea4 100644
--- a/src/ast/ast-expression-visitor.cc
+++ b/src/ast/ast-expression-visitor.cc
@@ -208,6 +208,7 @@
 
 
 void AstExpressionVisitor::VisitDoExpression(DoExpression* expr) {
+  VisitExpression(expr);
   RECURSE(VisitBlock(expr->block()));
   RECURSE(VisitVariableProxy(expr->result()));
 }
@@ -399,8 +400,8 @@
 }
 
 
-void AstExpressionVisitor::VisitRewritableAssignmentExpression(
-    RewritableAssignmentExpression* expr) {
+void AstExpressionVisitor::VisitRewritableExpression(
+    RewritableExpression* expr) {
   VisitExpression(expr);
   RECURSE(Visit(expr->expression()));
 }
diff --git a/src/ast/ast-expression-visitor.h b/src/ast/ast-expression-visitor.h
index cda624d..545a45c 100644
--- a/src/ast/ast-expression-visitor.h
+++ b/src/ast/ast-expression-visitor.h
@@ -8,9 +8,7 @@
 #include "src/allocation.h"
 #include "src/ast/ast.h"
 #include "src/ast/scopes.h"
-#include "src/effects.h"
 #include "src/type-info.h"
-#include "src/types.h"
 #include "src/zone.h"
 
 namespace v8 {
diff --git a/src/ast/ast-literal-reindexer.cc b/src/ast/ast-literal-reindexer.cc
index fce33e7..1f79b12 100644
--- a/src/ast/ast-literal-reindexer.cc
+++ b/src/ast/ast-literal-reindexer.cc
@@ -44,7 +44,8 @@
 
 
 void AstLiteralReindexer::VisitDoExpression(DoExpression* node) {
-  // TODO(caitp): literals in do expressions need re-indexing too.
+  Visit(node->block());
+  Visit(node->result());
 }
 
 
@@ -76,8 +77,8 @@
 }
 
 
-void AstLiteralReindexer::VisitRewritableAssignmentExpression(
-    RewritableAssignmentExpression* node) {
+void AstLiteralReindexer::VisitRewritableExpression(
+    RewritableExpression* node) {
   Visit(node->expression());
 }
 
@@ -187,6 +188,8 @@
 
 
 void AstLiteralReindexer::VisitSpread(Spread* node) {
+  // This is reachable because ParserBase::ParseArrowFunctionLiteral calls
+  // ReindexLiterals before calling RewriteDestructuringAssignments.
   Visit(node->expression());
 }
 
diff --git a/src/ast/ast-numbering.cc b/src/ast/ast-numbering.cc
index 6c2b696..272f9bd 100644
--- a/src/ast/ast-numbering.cc
+++ b/src/ast/ast-numbering.cc
@@ -306,7 +306,6 @@
 void AstNumberingVisitor::VisitTryCatchStatement(TryCatchStatement* node) {
   IncrementNodeCount();
   DisableOptimization(kTryCatchStatement);
-  node->set_base_id(ReserveIdRange(TryCatchStatement::num_ids()));
   Visit(node->try_block());
   Visit(node->catch_block());
 }
@@ -315,7 +314,6 @@
 void AstNumberingVisitor::VisitTryFinallyStatement(TryFinallyStatement* node) {
   IncrementNodeCount();
   DisableOptimization(kTryFinallyStatement);
-  node->set_base_id(ReserveIdRange(TryFinallyStatement::num_ids()));
   Visit(node->try_block());
   Visit(node->finally_block());
 }
@@ -372,11 +370,7 @@
 }
 
 
-void AstNumberingVisitor::VisitSpread(Spread* node) {
-  IncrementNodeCount();
-  DisableCrankshaft(kSpread);
-  Visit(node->expression());
-}
+void AstNumberingVisitor::VisitSpread(Spread* node) { UNREACHABLE(); }
 
 
 void AstNumberingVisitor::VisitEmptyParentheses(EmptyParentheses* node) {
@@ -510,6 +504,9 @@
 
 void AstNumberingVisitor::VisitCall(Call* node) {
   IncrementNodeCount();
+  if (node->tail_call_mode() == TailCallMode::kAllow) {
+    DisableOptimization(kTailCall);
+  }
   ReserveFeedbackSlots(node);
   node->set_base_id(ReserveIdRange(Call::num_ids()));
   Visit(node->expression());
@@ -557,10 +554,10 @@
 }
 
 
-void AstNumberingVisitor::VisitRewritableAssignmentExpression(
-    RewritableAssignmentExpression* node) {
+void AstNumberingVisitor::VisitRewritableExpression(
+    RewritableExpression* node) {
   IncrementNodeCount();
-  node->set_base_id(ReserveIdRange(RewritableAssignmentExpression::num_ids()));
+  node->set_base_id(ReserveIdRange(RewritableExpression::num_ids()));
   Visit(node->expression());
 }
 
diff --git a/src/ast/ast-value-factory.cc b/src/ast/ast-value-factory.cc
index 2e17fbc..189d4cc 100644
--- a/src/ast/ast-value-factory.cc
+++ b/src/ast/ast-value-factory.cc
@@ -172,6 +172,8 @@
       if (symbol_name_[0] == 'i') {
         DCHECK_EQ(0, strcmp(symbol_name_, "iterator_symbol"));
         value_ = isolate->factory()->iterator_symbol();
+      } else if (strcmp(symbol_name_, "hasInstance_symbol") == 0) {
+        value_ = isolate->factory()->has_instance_symbol();
       } else {
         DCHECK_EQ(0, strcmp(symbol_name_, "home_object_symbol"));
         value_ = isolate->factory()->home_object_symbol();
diff --git a/src/ast/ast-value-factory.h b/src/ast/ast-value-factory.h
index 4ae912e..85e8277 100644
--- a/src/ast/ast-value-factory.h
+++ b/src/ast/ast-value-factory.h
@@ -255,6 +255,7 @@
   F(dot_catch, ".catch")                        \
   F(empty, "")                                  \
   F(eval, "eval")                               \
+  F(function, "function")                       \
   F(get_space, "get ")                          \
   F(let, "let")                                 \
   F(native, "native")                           \
@@ -263,9 +264,11 @@
   F(proto, "__proto__")                         \
   F(prototype, "prototype")                     \
   F(rest_parameter, ".rest_parameter")          \
+  F(return, "return")                           \
   F(set_space, "set ")                          \
   F(this, "this")                               \
   F(this_function, ".this_function")            \
+  F(throw, "throw")                             \
   F(undefined, "undefined")                     \
   F(use_asm, "use asm")                         \
   F(use_strong, "use strong")                   \
diff --git a/src/ast/ast.cc b/src/ast/ast.cc
index 69e7351..9b2c638 100644
--- a/src/ast/ast.cc
+++ b/src/ast/ast.cc
@@ -5,6 +5,8 @@
 #include "src/ast/ast.h"
 
 #include <cmath>  // For isfinite.
+
+#include "src/ast/prettyprinter.h"
 #include "src/ast/scopes.h"
 #include "src/builtins.h"
 #include "src/code-stubs.h"
@@ -32,6 +34,25 @@
 // ----------------------------------------------------------------------------
 // Implementation of other node functionality.
 
+#ifdef DEBUG
+
+void AstNode::Print() { Print(Isolate::Current()); }
+
+
+void AstNode::Print(Isolate* isolate) {
+  AstPrinter::PrintOut(isolate, this);
+}
+
+
+void AstNode::PrettyPrint() { PrettyPrint(Isolate::Current()); }
+
+
+void AstNode::PrettyPrint(Isolate* isolate) {
+  PrettyPrinter::PrintOut(isolate, this);
+}
+
+#endif  // DEBUG
+
 
 bool Expression::IsSmiLiteral() const {
   return IsLiteral() && AsLiteral()->value()->IsSmi();
@@ -254,14 +275,21 @@
   }
 }
 
+bool ObjectLiteralProperty::NeedsSetFunctionName() const {
+  return is_computed_name_ &&
+         (value_->IsAnonymousFunctionDefinition() ||
+          (value_->IsFunctionLiteral() &&
+           IsConciseMethod(value_->AsFunctionLiteral()->kind())));
+}
 
 void ClassLiteral::AssignFeedbackVectorSlots(Isolate* isolate,
                                              FeedbackVectorSpec* spec,
                                              FeedbackVectorSlotCache* cache) {
   // This logic that computes the number of slots needed for vector store
   // ICs must mirror FullCodeGenerator::VisitClassLiteral.
+  prototype_slot_ = spec->AddLoadICSlot();
   if (NeedsProxySlot()) {
-    slot_ = spec->AddStoreICSlot();
+    proxy_slot_ = spec->AddStoreICSlot();
   }
 
   for (int i = 0; i < properties()->length(); i++) {
@@ -476,10 +504,11 @@
 
 
 void ArrayLiteral::BuildConstantElements(Isolate* isolate) {
+  DCHECK_LT(first_spread_index_, 0);
+
   if (!constant_elements_.is_null()) return;
 
-  int constants_length =
-      first_spread_index_ >= 0 ? first_spread_index_ : values()->length();
+  int constants_length = values()->length();
 
   // Allocate a fixed array to hold all the object literals.
   Handle<JSArray> array = isolate->factory()->NewJSArray(
@@ -487,7 +516,7 @@
       Strength::WEAK, INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE);
 
   // Fill in the literals.
-  bool is_simple = (first_spread_index_ < 0);
+  bool is_simple = true;
   int depth_acc = 1;
   bool is_holey = false;
   int array_index = 0;
@@ -553,7 +582,7 @@
   int array_index = 0;
   for (; array_index < values()->length(); array_index++) {
     Expression* subexpr = values()->at(array_index);
-    if (subexpr->IsSpread()) break;
+    DCHECK(!subexpr->IsSpread());
     if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue;
 
     // We'll reuse the same literal slot for all of the non-constant
@@ -797,14 +826,12 @@
   }
 }
 
-
 CaseClause::CaseClause(Zone* zone, Expression* label,
                        ZoneList<Statement*>* statements, int pos)
     : Expression(zone, pos),
       label_(label),
       statements_(statements),
-      compare_type_(Type::None(zone)) {}
-
+      compare_type_(Type::None()) {}
 
 uint32_t Literal::Hash() {
   return raw_value()->IsString()
diff --git a/src/ast/ast.h b/src/ast/ast.h
index 7f00955..dcb440d 100644
--- a/src/ast/ast.h
+++ b/src/ast/ast.h
@@ -91,7 +91,7 @@
   V(CaseClause)                 \
   V(EmptyParentheses)           \
   V(DoExpression)               \
-  V(RewritableAssignmentExpression)
+  V(RewritableExpression)
 
 #define AST_NODE_LIST(V)                        \
   DECLARATION_NODE_LIST(V)                      \
@@ -196,15 +196,18 @@
   virtual NodeType node_type() const = 0;
   int position() const { return position_; }
 
+#ifdef DEBUG
+  void PrettyPrint(Isolate* isolate);
+  void PrettyPrint();
+  void Print(Isolate* isolate);
+  void Print();
+#endif  // DEBUG
+
   // Type testing & conversion functions overridden by concrete subclasses.
 #define DECLARE_NODE_FUNCTIONS(type) \
-  bool Is##type() const { return node_type() == AstNode::k##type; } \
-  type* As##type() { \
-    return Is##type() ? reinterpret_cast<type*>(this) : NULL; \
-  } \
-  const type* As##type() const { \
-    return Is##type() ? reinterpret_cast<const type*>(this) : NULL; \
-  }
+  V8_INLINE bool Is##type() const;   \
+  V8_INLINE type* As##type();        \
+  V8_INLINE const type* As##type() const;
   AST_NODE_LIST(DECLARE_NODE_FUNCTIONS)
 #undef DECLARE_NODE_FUNCTIONS
 
@@ -237,7 +240,6 @@
 
   bool IsEmpty() { return AsEmptyStatement() != NULL; }
   virtual bool IsJump() const { return false; }
-  virtual void MarkTail() {}
 };
 
 
@@ -317,6 +319,10 @@
   // names because [] for string objects is handled only by keyed ICs.
   virtual bool IsPropertyName() const { return false; }
 
+  // True iff the expression is a class or function expression without
+  // a syntactic name.
+  virtual bool IsAnonymousFunctionDefinition() const { return false; }
+
   // True iff the expression is a literal represented as a smi.
   bool IsSmiLiteral() const;
 
@@ -365,14 +371,6 @@
   BailoutId id() const { return BailoutId(local_id(0)); }
   TypeFeedbackId test_id() const { return TypeFeedbackId(local_id(1)); }
 
-  // Parenthesized expressions in the form `( Expression )`.
-  void set_is_parenthesized() {
-    bit_field_ = ParenthesizedField::update(bit_field_, true);
-  }
-  bool is_parenthesized() const {
-    return ParenthesizedField::decode(bit_field_);
-  }
-
  protected:
   Expression(Zone* zone, int pos)
       : AstNode(pos),
@@ -395,8 +393,6 @@
   int base_id_;
   Bounds bounds_;
   class ToBooleanTypesField : public BitField16<uint16_t, 0, 9> {};
-  class ParenthesizedField
-      : public BitField16<bool, ToBooleanTypesField::kNext, 1> {};
   uint16_t bit_field_;
   // Ends with 16-bit field; deriving classes in turn begin with
   // 16-bit fields for optimum packing efficiency.
@@ -471,10 +467,6 @@
         && labels() == NULL;  // Good enough as an approximation...
   }
 
-  void MarkTail() override {
-    if (!statements_.is_empty()) statements_.last()->MarkTail();
-  }
-
   Scope* scope() const { return scope_; }
   void set_scope(Scope* scope) { scope_ = scope; }
 
@@ -505,8 +497,6 @@
   VariableProxy* result() { return result_; }
   void set_result(VariableProxy* v) { result_ = v; }
 
-  void MarkTail() override { block_->MarkTail(); }
-
  protected:
   DoExpression(Zone* zone, Block* block, VariableProxy* result, int pos)
       : Expression(zone, pos), block_(block), result_(result) {
@@ -555,24 +545,10 @@
     return mode() == VAR ? kCreatedInitialized : kNeedsInitialization;
   }
 
-  bool is_class_declaration() const { return is_class_declaration_; }
-
-  // VariableDeclarations can be grouped into consecutive declaration
-  // groups. Each VariableDeclaration is associated with the start position of
-  // the group it belongs to. The positions are used for strong mode scope
-  // checks for classes and functions.
-  int declaration_group_start() const { return declaration_group_start_; }
-
  protected:
   VariableDeclaration(Zone* zone, VariableProxy* proxy, VariableMode mode,
-                      Scope* scope, int pos, bool is_class_declaration = false,
-                      int declaration_group_start = -1)
-      : Declaration(zone, proxy, mode, scope, pos),
-        is_class_declaration_(is_class_declaration),
-        declaration_group_start_(declaration_group_start) {}
-
-  bool is_class_declaration_;
-  int declaration_group_start_;
+                      Scope* scope, int pos)
+      : Declaration(zone, proxy, mode, scope, pos) {}
 };
 
 
@@ -820,6 +796,10 @@
                                  FeedbackVectorSlotCache* cache) override;
   FeedbackVectorSlot EachFeedbackSlot() const { return each_slot_; }
 
+  static const char* VisitModeString(VisitMode mode) {
+    return mode == ITERATE ? "for-of" : "for-in";
+  }
+
  protected:
   ForEachStatement(Zone* zone, ZoneList<const AstRawString*>* labels, int pos)
       : IterationStatement(zone, labels, pos), each_(NULL), subject_(NULL) {}
@@ -857,9 +837,9 @@
 
   static int num_ids() { return parent_num_ids() + 6; }
   BailoutId BodyId() const { return BailoutId(local_id(0)); }
-  BailoutId PrepareId() const { return BailoutId(local_id(1)); }
-  BailoutId EnumId() const { return BailoutId(local_id(2)); }
-  BailoutId ToObjectId() const { return BailoutId(local_id(3)); }
+  BailoutId EnumId() const { return BailoutId(local_id(1)); }
+  BailoutId ToObjectId() const { return BailoutId(local_id(2)); }
+  BailoutId PrepareId() const { return BailoutId(local_id(3)); }
   BailoutId FilterId() const { return BailoutId(local_id(4)); }
   BailoutId AssignmentId() const { return BailoutId(local_id(5)); }
   BailoutId ContinueId() const override { return EntryId(); }
@@ -885,11 +865,13 @@
   void Initialize(Expression* each,
                   Expression* subject,
                   Statement* body,
+                  Variable* iterator,
                   Expression* assign_iterator,
                   Expression* next_result,
                   Expression* result_done,
                   Expression* assign_each) {
     ForEachStatement::Initialize(each, subject, body);
+    iterator_ = iterator;
     assign_iterator_ = assign_iterator;
     next_result_ = next_result;
     result_done_ = result_done;
@@ -900,6 +882,10 @@
     return subject();
   }
 
+  Variable* iterator() const {
+    return iterator_;
+  }
+
   // iterator = subject[Symbol.iterator]()
   Expression* assign_iterator() const {
     return assign_iterator_;
@@ -934,6 +920,7 @@
  protected:
   ForOfStatement(Zone* zone, ZoneList<const AstRawString*>* labels, int pos)
       : ForEachStatement(zone, labels, pos),
+        iterator_(NULL),
         assign_iterator_(NULL),
         next_result_(NULL),
         result_done_(NULL),
@@ -943,6 +930,7 @@
  private:
   int local_id(int n) const { return base_id() + parent_num_ids() + n; }
 
+  Variable* iterator_;
   Expression* assign_iterator_;
   Expression* next_result_;
   Expression* result_done_;
@@ -957,7 +945,6 @@
   void set_expression(Expression* e) { expression_ = e; }
   Expression* expression() const { return expression_; }
   bool IsJump() const override { return expression_->IsThrow(); }
-  void MarkTail() override { expression_->MarkTail(); }
 
  protected:
   ExpressionStatement(Zone* zone, Expression* expression, int pos)
@@ -1039,8 +1026,6 @@
   BailoutId ToObjectId() const { return BailoutId(local_id(0)); }
   BailoutId EntryId() const { return BailoutId(local_id(1)); }
 
-  void MarkTail() override { statement_->MarkTail(); }
-
  protected:
   WithStatement(Zone* zone, Scope* scope, Expression* expression,
                 Statement* statement, int pos)
@@ -1083,10 +1068,6 @@
   BailoutId EntryId() const { return BailoutId(local_id(0)); }
   TypeFeedbackId CompareId() { return TypeFeedbackId(local_id(1)); }
 
-  void MarkTail() override {
-    if (!statements_->is_empty()) statements_->last()->MarkTail();
-  }
-
   Type* compare_type() { return compare_type_; }
   void set_compare_type(Type* type) { compare_type_ = type; }
 
@@ -1119,10 +1100,6 @@
 
   void set_tag(Expression* t) { tag_ = t; }
 
-  void MarkTail() override {
-    if (!cases_->is_empty()) cases_->last()->MarkTail();
-  }
-
  protected:
   SwitchStatement(Zone* zone, ZoneList<const AstRawString*>* labels, int pos)
       : BreakableStatement(zone, labels, TARGET_FOR_ANONYMOUS, pos),
@@ -1160,11 +1137,6 @@
         && HasElseStatement() && else_statement()->IsJump();
   }
 
-  void MarkTail() override {
-    then_statement_->MarkTail();
-    else_statement_->MarkTail();
-  }
-
   void set_base_id(int id) { base_id_ = id; }
   static int num_ids() { return parent_num_ids() + 3; }
   BailoutId IfId() const { return BailoutId(local_id(0)); }
@@ -1201,27 +1173,12 @@
   Block* try_block() const { return try_block_; }
   void set_try_block(Block* b) { try_block_ = b; }
 
-  void set_base_id(int id) { base_id_ = id; }
-  static int num_ids() { return parent_num_ids() + 1; }
-  BailoutId HandlerId() const { return BailoutId(local_id(0)); }
-
  protected:
   TryStatement(Zone* zone, Block* try_block, int pos)
-      : Statement(zone, pos),
-        try_block_(try_block),
-        base_id_(BailoutId::None().ToInt()) {}
-  static int parent_num_ids() { return 0; }
-
-  int base_id() const {
-    DCHECK(!BailoutId(base_id_).IsNone());
-    return base_id_;
-  }
+      : Statement(zone, pos), try_block_(try_block) {}
 
  private:
-  int local_id(int n) const { return base_id() + parent_num_ids() + n; }
-
   Block* try_block_;
-  int base_id_;
 };
 
 
@@ -1234,8 +1191,6 @@
   Block* catch_block() const { return catch_block_; }
   void set_catch_block(Block* b) { catch_block_ = b; }
 
-  void MarkTail() override { catch_block_->MarkTail(); }
-
  protected:
   TryCatchStatement(Zone* zone, Block* try_block, Scope* scope,
                     Variable* variable, Block* catch_block, int pos)
@@ -1258,8 +1213,6 @@
   Block* finally_block() const { return finally_block_; }
   void set_finally_block(Block* b) { finally_block_ = b; }
 
-  void MarkTail() override { finally_block_->MarkTail(); }
-
  protected:
   TryFinallyStatement(Zone* zone, Block* try_block, Block* finally_block,
                       int pos)
@@ -1472,6 +1425,8 @@
 
   void set_receiver_type(Handle<Map> map) { receiver_type_ = map; }
 
+  bool NeedsSetFunctionName() const;
+
  protected:
   friend class AstNodeFactory;
 
@@ -1510,6 +1465,9 @@
   bool may_store_doubles() const { return may_store_doubles_; }
   bool has_function() const { return has_function_; }
   bool has_elements() const { return has_elements_; }
+  bool has_shallow_properties() const {
+    return depth() == 1 && !has_elements() && !may_store_doubles();
+  }
 
   // Decide if a property should be in the object boilerplate.
   static bool IsBoilerplateProperty(Property* property);
@@ -1526,7 +1484,7 @@
   int ComputeFlags(bool disable_mementos = false) const {
     int flags = fast_elements() ? kFastElements : kNoFlags;
     flags |= has_function() ? kHasFunction : kNoFlags;
-    if (depth() == 1 && !has_elements() && !may_store_doubles()) {
+    if (has_shallow_properties()) {
       flags |= kShallowProperties;
     }
     if (disable_mementos) {
@@ -1683,6 +1641,19 @@
     return flags;
   }
 
+  // Provide a mechanism for iterating through values to rewrite spreads.
+  ZoneList<Expression*>::iterator FirstSpread() const {
+    return (first_spread_index_ >= 0) ? values_->begin() + first_spread_index_
+                                      : values_->end();
+  }
+  ZoneList<Expression*>::iterator EndValue() const { return values_->end(); }
+
+  // Rewind an array literal omitting everything from the first spread on.
+  void RewindSpreads() {
+    values_->Rewind(first_spread_index_);
+    first_spread_index_ = -1;
+  }
+
   enum Flags {
     kNoFlags = 0,
     kShallowElements = 1,
@@ -1975,7 +1946,10 @@
     bit_field_ = IsUninitializedField::update(bit_field_, b);
   }
 
-  bool is_tail() const { return IsTailField::decode(bit_field_); }
+  TailCallMode tail_call_mode() const {
+    return IsTailField::decode(bit_field_) ? TailCallMode::kAllow
+                                           : TailCallMode::kDisallow;
+  }
   void MarkTail() override {
     bit_field_ = IsTailField::update(bit_field_, true);
   }
@@ -2349,7 +2323,7 @@
         op_(op),
         left_(left),
         right_(right),
-        combined_type_(Type::None(zone)) {
+        combined_type_(Type::None()) {
     DCHECK(Token::IsCompareOp(op));
   }
   static int parent_num_ids() { return Expression::num_ids(); }
@@ -2372,17 +2346,20 @@
   Expression* expression() const { return expression_; }
   void set_expression(Expression* e) { expression_ = e; }
 
+  int expression_position() const { return expr_pos_; }
+
   static int num_ids() { return parent_num_ids(); }
 
  protected:
-  Spread(Zone* zone, Expression* expression, int pos)
-      : Expression(zone, pos), expression_(expression) {}
+  Spread(Zone* zone, Expression* expression, int pos, int expr_pos)
+      : Expression(zone, pos), expression_(expression), expr_pos_(expr_pos) {}
   static int parent_num_ids() { return Expression::num_ids(); }
 
  private:
   int local_id(int n) const { return base_id() + parent_num_ids() + n; }
 
   Expression* expression_;
+  int expr_pos_;
 };
 
 
@@ -2505,18 +2482,32 @@
 };
 
 
-class RewritableAssignmentExpression : public Expression {
+// The RewritableExpression class is a wrapper for AST nodes that wait
+// for some potential rewriting.  However, even if such nodes are indeed
+// rewritten, the RewritableExpression wrapper nodes will survive in the
+// final AST and should be just ignored, i.e., they should be treated as
+// equivalent to the wrapped nodes.  For this reason and to simplify later
+// phases, RewritableExpressions are considered as exceptions of AST nodes
+// in the following sense:
+//
+// 1. IsRewritableExpression and AsRewritableExpression behave as usual.
+// 2. All other Is* and As* methods are practically delegated to the
+//    wrapped node, i.e. IsArrayLiteral() will return true iff the
+//    wrapped node is an array literal.
+//
+// Furthermore, an invariant that should be respected is that the wrapped
+// node is not a RewritableExpression.
+class RewritableExpression : public Expression {
  public:
-  DECLARE_NODE_TYPE(RewritableAssignmentExpression)
+  DECLARE_NODE_TYPE(RewritableExpression)
 
-  Expression* expression() { return expr_; }
+  Expression* expression() const { return expr_; }
   bool is_rewritten() const { return is_rewritten_; }
 
-  void set_expression(Expression* e) { expr_ = e; }
-
   void Rewrite(Expression* new_expression) {
     DCHECK(!is_rewritten());
     DCHECK_NOT_NULL(new_expression);
+    DCHECK(!new_expression->IsRewritableExpression());
     expr_ = new_expression;
     is_rewritten_ = true;
   }
@@ -2524,10 +2515,12 @@
   static int num_ids() { return parent_num_ids(); }
 
  protected:
-  RewritableAssignmentExpression(Zone* zone, Expression* expression)
+  RewritableExpression(Zone* zone, Expression* expression)
       : Expression(zone, expression->position()),
         is_rewritten_(false),
-        expr_(expression) {}
+        expr_(expression) {
+    DCHECK(!expression->IsRewritableExpression());
+  }
 
  private:
   int local_id(int n) const { return base_id() + parent_num_ids() + n; }
@@ -2555,26 +2548,6 @@
   void set_generator_object(Expression* e) { generator_object_ = e; }
   void set_expression(Expression* e) { expression_ = e; }
 
-  // Type feedback information.
-  bool HasFeedbackSlots() const { return yield_kind() == kDelegating; }
-  void AssignFeedbackVectorSlots(Isolate* isolate, FeedbackVectorSpec* spec,
-                                 FeedbackVectorSlotCache* cache) override {
-    if (HasFeedbackSlots()) {
-      yield_first_feedback_slot_ = spec->AddKeyedLoadICSlot();
-      keyed_load_feedback_slot_ = spec->AddLoadICSlot();
-      done_feedback_slot_ = spec->AddLoadICSlot();
-    }
-  }
-
-  FeedbackVectorSlot KeyedLoadFeedbackSlot() {
-    DCHECK(!HasFeedbackSlots() || !yield_first_feedback_slot_.IsInvalid());
-    return yield_first_feedback_slot_;
-  }
-
-  FeedbackVectorSlot DoneFeedbackSlot() { return keyed_load_feedback_slot_; }
-
-  FeedbackVectorSlot ValueFeedbackSlot() { return done_feedback_slot_; }
-
  protected:
   Yield(Zone* zone, Expression* generator_object, Expression* expression,
         Kind yield_kind, int pos)
@@ -2587,9 +2560,6 @@
   Expression* generator_object_;
   Expression* expression_;
   Kind yield_kind_;
-  FeedbackVectorSlot yield_first_feedback_slot_;
-  FeedbackVectorSlot keyed_load_feedback_slot_;
-  FeedbackVectorSlot done_feedback_slot_;
 };
 
 
@@ -2615,15 +2585,13 @@
     kAnonymousExpression,
     kNamedExpression,
     kDeclaration,
-    kGlobalOrEval
+    kAccessorOrMethod
   };
 
   enum ParameterFlag { kNoDuplicateParameters, kHasDuplicateParameters };
 
   enum EagerCompileHint { kShouldEagerCompile, kShouldLazyCompile };
 
-  enum ArityRestriction { kNormalArity, kGetterArity, kSetterArity };
-
   DECLARE_NODE_TYPE(FunctionLiteral)
 
   Handle<String> name() const { return raw_name_->string(); }
@@ -2636,8 +2604,13 @@
   int start_position() const;
   int end_position() const;
   int SourceSize() const { return end_position() - start_position(); }
-  bool is_expression() const { return IsExpression::decode(bitfield_); }
-  bool is_anonymous() const { return IsAnonymous::decode(bitfield_); }
+  bool is_declaration() const { return IsDeclaration::decode(bitfield_); }
+  bool is_named_expression() const {
+    return IsNamedExpression::decode(bitfield_);
+  }
+  bool is_anonymous_expression() const {
+    return IsAnonymousExpression::decode(bitfield_);
+  }
   LanguageMode language_mode() const;
 
   static bool NeedsHomeObject(Expression* expr);
@@ -2729,6 +2702,10 @@
     dont_optimize_reason_ = reason;
   }
 
+  bool IsAnonymousFunctionDefinition() const final {
+    return is_anonymous_expression();
+  }
+
  protected:
   FunctionLiteral(Zone* zone, const AstString* name,
                   AstValueFactory* ast_value_factory, Scope* scope,
@@ -2737,7 +2714,7 @@
                   FunctionType function_type,
                   ParameterFlag has_duplicate_parameters,
                   EagerCompileHint eager_compile_hint, FunctionKind kind,
-                  int position)
+                  int position, bool is_function)
       : Expression(zone, position),
         raw_name_(name),
         scope_(scope),
@@ -2750,26 +2727,28 @@
         parameter_count_(parameter_count),
         function_token_position_(RelocInfo::kNoPosition) {
     bitfield_ =
-        IsExpression::encode(function_type != kDeclaration) |
-        IsAnonymous::encode(function_type == kAnonymousExpression) |
+        IsDeclaration::encode(function_type == kDeclaration) |
+        IsNamedExpression::encode(function_type == kNamedExpression) |
+        IsAnonymousExpression::encode(function_type == kAnonymousExpression) |
         Pretenure::encode(false) |
         HasDuplicateParameters::encode(has_duplicate_parameters ==
                                        kHasDuplicateParameters) |
-        IsFunction::encode(function_type != kGlobalOrEval) |
+        IsFunction::encode(is_function) |
         ShouldEagerCompile::encode(eager_compile_hint == kShouldEagerCompile) |
         FunctionKindBits::encode(kind) | ShouldBeUsedOnceHint::encode(false);
     DCHECK(IsValidFunctionKind(kind));
   }
 
  private:
-  class IsExpression : public BitField16<bool, 0, 1> {};
-  class IsAnonymous : public BitField16<bool, 1, 1> {};
-  class Pretenure : public BitField16<bool, 2, 1> {};
-  class HasDuplicateParameters : public BitField16<bool, 3, 1> {};
-  class IsFunction : public BitField16<bool, 4, 1> {};
-  class ShouldEagerCompile : public BitField16<bool, 5, 1> {};
-  class FunctionKindBits : public BitField16<FunctionKind, 6, 8> {};
-  class ShouldBeUsedOnceHint : public BitField16<bool, 15, 1> {};
+  class IsDeclaration : public BitField16<bool, 0, 1> {};
+  class IsNamedExpression : public BitField16<bool, 1, 1> {};
+  class IsAnonymousExpression : public BitField16<bool, 2, 1> {};
+  class Pretenure : public BitField16<bool, 3, 1> {};
+  class HasDuplicateParameters : public BitField16<bool, 4, 1> {};
+  class IsFunction : public BitField16<bool, 5, 1> {};
+  class ShouldEagerCompile : public BitField16<bool, 6, 1> {};
+  class ShouldBeUsedOnceHint : public BitField16<bool, 7, 1> {};
+  class FunctionKindBits : public BitField16<FunctionKind, 8, 8> {};
 
   // Start with 16-bit field, which should get packed together
   // with Expression's trailing 16-bit field.
@@ -2796,13 +2775,6 @@
 
   DECLARE_NODE_TYPE(ClassLiteral)
 
-  Handle<String> name() const { return raw_name_->string(); }
-  const AstRawString* raw_name() const { return raw_name_; }
-  void set_raw_name(const AstRawString* name) {
-    DCHECK_NULL(raw_name_);
-    raw_name_ = name;
-  }
-
   Scope* scope() const { return scope_; }
   VariableProxy* class_variable_proxy() const { return class_variable_proxy_; }
   Expression* extends() const { return extends_; }
@@ -2817,13 +2789,14 @@
   BailoutId DeclsId() const { return BailoutId(local_id(1)); }
   BailoutId ExitId() { return BailoutId(local_id(2)); }
   BailoutId CreateLiteralId() const { return BailoutId(local_id(3)); }
+  BailoutId PrototypeId() { return BailoutId(local_id(4)); }
 
   // Return an AST id for a property that is used in simulate instructions.
-  BailoutId GetIdForProperty(int i) { return BailoutId(local_id(i + 4)); }
+  BailoutId GetIdForProperty(int i) { return BailoutId(local_id(i + 5)); }
 
   // Unlike other AST nodes, this number of bailout IDs allocated for an
   // ClassLiteral can vary, so num_ids() is not a static method.
-  int num_ids() const { return parent_num_ids() + 4 + properties()->length(); }
+  int num_ids() const { return parent_num_ids() + 5 + properties()->length(); }
 
   // Object literals need one feedback slot for each non-trivial value, as well
   // as some slots for home objects.
@@ -2835,15 +2808,19 @@
            class_variable_proxy()->var()->IsUnallocated();
   }
 
-  FeedbackVectorSlot ProxySlot() const { return slot_; }
+  FeedbackVectorSlot PrototypeSlot() const { return prototype_slot_; }
+  FeedbackVectorSlot ProxySlot() const { return proxy_slot_; }
+
+  bool IsAnonymousFunctionDefinition() const final {
+    return constructor()->raw_name()->length() == 0;
+  }
 
  protected:
-  ClassLiteral(Zone* zone, const AstRawString* name, Scope* scope,
-               VariableProxy* class_variable_proxy, Expression* extends,
-               FunctionLiteral* constructor, ZoneList<Property*>* properties,
-               int start_position, int end_position)
+  ClassLiteral(Zone* zone, Scope* scope, VariableProxy* class_variable_proxy,
+               Expression* extends, FunctionLiteral* constructor,
+               ZoneList<Property*>* properties, int start_position,
+               int end_position)
       : Expression(zone, start_position),
-        raw_name_(name),
         scope_(scope),
         class_variable_proxy_(class_variable_proxy),
         extends_(extends),
@@ -2856,14 +2833,14 @@
  private:
   int local_id(int n) const { return base_id() + parent_num_ids() + n; }
 
-  const AstRawString* raw_name_;
   Scope* scope_;
   VariableProxy* class_variable_proxy_;
   Expression* extends_;
   FunctionLiteral* constructor_;
   ZoneList<Property*>* properties_;
   int end_position_;
-  FeedbackVectorSlot slot_;
+  FeedbackVectorSlot prototype_slot_;
+  FeedbackVectorSlot proxy_slot_;
 };
 
 
@@ -3095,12 +3072,11 @@
 
   AstValueFactory* ast_value_factory() const { return ast_value_factory_; }
 
-  VariableDeclaration* NewVariableDeclaration(
-      VariableProxy* proxy, VariableMode mode, Scope* scope, int pos,
-      bool is_class_declaration = false, int declaration_group_start = -1) {
+  VariableDeclaration* NewVariableDeclaration(VariableProxy* proxy,
+                                              VariableMode mode, Scope* scope,
+                                              int pos) {
     return new (parser_zone_)
-        VariableDeclaration(parser_zone_, proxy, mode, scope, pos,
-                            is_class_declaration, declaration_group_start);
+        VariableDeclaration(parser_zone_, proxy, mode, scope, pos);
   }
 
   FunctionDeclaration* NewFunctionDeclaration(VariableProxy* proxy,
@@ -3389,8 +3365,8 @@
         CompareOperation(local_zone_, op, left, right, pos);
   }
 
-  Spread* NewSpread(Expression* expression, int pos) {
-    return new (local_zone_) Spread(local_zone_, expression, pos);
+  Spread* NewSpread(Expression* expression, int pos, int expr_pos) {
+    return new (local_zone_) Spread(local_zone_, expression, pos, expr_pos);
   }
 
   Conditional* NewConditional(Expression* condition,
@@ -3401,12 +3377,9 @@
         local_zone_, condition, then_expression, else_expression, position);
   }
 
-  RewritableAssignmentExpression* NewRewritableAssignmentExpression(
-      Expression* expression) {
+  RewritableExpression* NewRewritableExpression(Expression* expression) {
     DCHECK_NOT_NULL(expression);
-    DCHECK(expression->IsAssignment());
-    return new (local_zone_)
-        RewritableAssignmentExpression(local_zone_, expression);
+    return new (local_zone_) RewritableExpression(local_zone_, expression);
   }
 
   Assignment* NewAssignment(Token::Value op,
@@ -3449,16 +3422,31 @@
         parser_zone_, name, ast_value_factory_, scope, body,
         materialized_literal_count, expected_property_count, parameter_count,
         function_type, has_duplicate_parameters, eager_compile_hint, kind,
-        position);
+        position, true);
   }
 
-  ClassLiteral* NewClassLiteral(const AstRawString* name, Scope* scope,
-                                VariableProxy* proxy, Expression* extends,
+  // Creates a FunctionLiteral representing a top-level script, the
+  // result of an eval (top-level or otherwise), or the result of calling
+  // the Function constructor.
+  FunctionLiteral* NewScriptOrEvalFunctionLiteral(
+      Scope* scope, ZoneList<Statement*>* body, int materialized_literal_count,
+      int expected_property_count) {
+    return new (parser_zone_) FunctionLiteral(
+        parser_zone_, ast_value_factory_->empty_string(), ast_value_factory_,
+        scope, body, materialized_literal_count, expected_property_count, 0,
+        FunctionLiteral::kAnonymousExpression,
+        FunctionLiteral::kNoDuplicateParameters,
+        FunctionLiteral::kShouldLazyCompile, FunctionKind::kNormalFunction, 0,
+        false);
+  }
+
+  ClassLiteral* NewClassLiteral(Scope* scope, VariableProxy* proxy,
+                                Expression* extends,
                                 FunctionLiteral* constructor,
                                 ZoneList<ObjectLiteral::Property*>* properties,
                                 int start_position, int end_position) {
     return new (parser_zone_)
-        ClassLiteral(parser_zone_, name, scope, proxy, extends, constructor,
+        ClassLiteral(parser_zone_, scope, proxy, extends, constructor,
                      properties, start_position, end_position);
   }
 
@@ -3529,6 +3517,46 @@
 };
 
 
+// Type testing & conversion functions overridden by concrete subclasses.
+// Inline functions for AstNode.
+
+#define DECLARE_NODE_FUNCTIONS(type)                                          \
+  bool AstNode::Is##type() const {                                            \
+    NodeType mine = node_type();                                              \
+    if (mine == AstNode::kRewritableExpression &&                             \
+        AstNode::k##type != AstNode::kRewritableExpression)                   \
+      mine = reinterpret_cast<const RewritableExpression*>(this)              \
+                 ->expression()                                               \
+                 ->node_type();                                               \
+    return mine == AstNode::k##type;                                          \
+  }                                                                           \
+  type* AstNode::As##type() {                                                 \
+    NodeType mine = node_type();                                              \
+    AstNode* result = this;                                                   \
+    if (mine == AstNode::kRewritableExpression &&                             \
+        AstNode::k##type != AstNode::kRewritableExpression) {                 \
+      result =                                                                \
+          reinterpret_cast<const RewritableExpression*>(this)->expression();  \
+      mine = result->node_type();                                             \
+    }                                                                         \
+    return mine == AstNode::k##type ? reinterpret_cast<type*>(result) : NULL; \
+  }                                                                           \
+  const type* AstNode::As##type() const {                                     \
+    NodeType mine = node_type();                                              \
+    const AstNode* result = this;                                             \
+    if (mine == AstNode::kRewritableExpression &&                             \
+        AstNode::k##type != AstNode::kRewritableExpression) {                 \
+      result =                                                                \
+          reinterpret_cast<const RewritableExpression*>(this)->expression();  \
+      mine = result->node_type();                                             \
+    }                                                                         \
+    return mine == AstNode::k##type ? reinterpret_cast<const type*>(result)   \
+                                    : NULL;                                   \
+  }
+AST_NODE_LIST(DECLARE_NODE_FUNCTIONS)
+#undef DECLARE_NODE_FUNCTIONS
+
+
 }  // namespace internal
 }  // namespace v8
 
diff --git a/src/ast/modules.cc b/src/ast/modules.cc
index 225cd8d..f895756 100644
--- a/src/ast/modules.cc
+++ b/src/ast/modules.cc
@@ -13,7 +13,6 @@
 void ModuleDescriptor::AddLocalExport(const AstRawString* export_name,
                                       const AstRawString* local_name,
                                       Zone* zone, bool* ok) {
-  DCHECK(!IsFrozen());
   void* key = const_cast<AstRawString*>(export_name);
 
   ZoneAllocationPolicy allocator(zone);
diff --git a/src/ast/modules.h b/src/ast/modules.h
index e3c66dc..1fdf526 100644
--- a/src/ast/modules.h
+++ b/src/ast/modules.h
@@ -26,8 +26,7 @@
   // ---------------------------------------------------------------------------
   // Mutators.
 
-  // Add a name to the list of exports. If it already exists, or this descriptor
-  // is frozen, that's an error.
+  // Add a name to the list of exports. If it already exists, that's an error.
   void AddLocalExport(const AstRawString* export_name,
                       const AstRawString* local_name, Zone* zone, bool* ok);
 
@@ -35,30 +34,22 @@
   // if not already present.
   void AddModuleRequest(const AstRawString* module_specifier, Zone* zone);
 
-  // Do not allow any further refinements, directly or through unification.
-  void Freeze() { frozen_ = true; }
-
   // Assign an index.
   void Allocate(int index) {
-    DCHECK(IsFrozen() && index_ == -1);
+    DCHECK_EQ(-1, index_);
     index_ = index;
   }
 
   // ---------------------------------------------------------------------------
   // Accessors.
 
-  // Check whether this is closed (i.e. fully determined).
-  bool IsFrozen() { return frozen_; }
-
   int Length() {
-    DCHECK(IsFrozen());
     ZoneHashMap* exports = exports_;
     return exports ? exports->occupancy() : 0;
   }
 
   // The context slot in the hosting script context pointing to this module.
   int Index() {
-    DCHECK(IsFrozen());
     return index_;
   }
 
@@ -104,12 +95,8 @@
   // Implementation.
  private:
   explicit ModuleDescriptor(Zone* zone)
-      : frozen_(false),
-        exports_(NULL),
-        requested_modules_(1, zone),
-        index_(-1) {}
+      : exports_(NULL), requested_modules_(1, zone), index_(-1) {}
 
-  bool frozen_;
   ZoneHashMap* exports_;   // Module exports and their types (allocated lazily)
   ZoneList<const AstRawString*> requested_modules_;
   int index_;
diff --git a/src/ast/prettyprinter.cc b/src/ast/prettyprinter.cc
index 1f6b8c3..0e9986a 100644
--- a/src/ast/prettyprinter.cc
+++ b/src/ast/prettyprinter.cc
@@ -412,8 +412,7 @@
 }
 
 
-void CallPrinter::VisitRewritableAssignmentExpression(
-    RewritableAssignmentExpression* node) {
+void CallPrinter::VisitRewritableExpression(RewritableExpression* node) {
   Find(node->expression());
 }
 
@@ -719,7 +718,7 @@
 
 void PrettyPrinter::VisitClassLiteral(ClassLiteral* node) {
   Print("(class ");
-  PrintLiteral(node->name(), false);
+  PrintLiteral(node->constructor()->name(), false);
   if (node->extends()) {
     Print(" extends ");
     Visit(node->extends());
@@ -929,8 +928,7 @@
 }
 
 
-void PrettyPrinter::VisitRewritableAssignmentExpression(
-    RewritableAssignmentExpression* node) {
+void PrettyPrinter::VisitRewritableExpression(RewritableExpression* node) {
   Visit(node->expression());
 }
 
@@ -1203,6 +1201,14 @@
 }
 
 
+void AstPrinter::PrintOut(Isolate* isolate, AstNode* node) {
+  AstPrinter printer(isolate);
+  printer.Init();
+  printer.Visit(node);
+  PrintF("%s", printer.Output());
+}
+
+
 void AstPrinter::PrintDeclarations(ZoneList<Declaration*>* declarations) {
   if (declarations->length() > 0) {
     IndentedScope indent(this, "DECLS");
@@ -1390,6 +1396,10 @@
   PrintIndentedVisit("FOR", node->each());
   PrintIndentedVisit("OF", node->iterable());
   PrintIndentedVisit("BODY", node->body());
+  PrintIndentedVisit("INIT", node->assign_iterator());
+  PrintIndentedVisit("NEXT", node->next_result());
+  PrintIndentedVisit("EACH", node->assign_each());
+  PrintIndentedVisit("DONE", node->result_done());
 }
 
 
@@ -1429,9 +1439,7 @@
 
 void AstPrinter::VisitClassLiteral(ClassLiteral* node) {
   IndentedScope indent(this, "CLASS LITERAL", node->position());
-  if (node->raw_name() != nullptr) {
-    PrintLiteralIndented("NAME", node->name(), false);
-  }
+  PrintLiteralIndented("NAME", node->constructor()->name(), false);
   if (node->extends() != nullptr) {
     PrintIndentedVisit("EXTENDS", node->extends());
   }
@@ -1544,31 +1552,36 @@
 
 
 void AstPrinter::VisitVariableProxy(VariableProxy* node) {
-  Variable* var = node->var();
   EmbeddedVector<char, 128> buf;
   int pos =
       FormatSlotNode(&buf, node, "VAR PROXY", node->VariableFeedbackSlot());
 
-  switch (var->location()) {
-    case VariableLocation::UNALLOCATED:
-      break;
-    case VariableLocation::PARAMETER:
-      SNPrintF(buf + pos, " parameter[%d]", var->index());
-      break;
-    case VariableLocation::LOCAL:
-      SNPrintF(buf + pos, " local[%d]", var->index());
-      break;
-    case VariableLocation::CONTEXT:
-      SNPrintF(buf + pos, " context[%d]", var->index());
-      break;
-    case VariableLocation::GLOBAL:
-      SNPrintF(buf + pos, " global[%d]", var->index());
-      break;
-    case VariableLocation::LOOKUP:
-      SNPrintF(buf + pos, " lookup");
-      break;
+  if (!node->is_resolved()) {
+    SNPrintF(buf + pos, " unresolved");
+    PrintLiteralWithModeIndented(buf.start(), nullptr, node->name());
+  } else {
+    Variable* var = node->var();
+    switch (var->location()) {
+      case VariableLocation::UNALLOCATED:
+        break;
+      case VariableLocation::PARAMETER:
+        SNPrintF(buf + pos, " parameter[%d]", var->index());
+        break;
+      case VariableLocation::LOCAL:
+        SNPrintF(buf + pos, " local[%d]", var->index());
+        break;
+      case VariableLocation::CONTEXT:
+        SNPrintF(buf + pos, " context[%d]", var->index());
+        break;
+      case VariableLocation::GLOBAL:
+        SNPrintF(buf + pos, " global[%d]", var->index());
+        break;
+      case VariableLocation::LOOKUP:
+        SNPrintF(buf + pos, " lookup");
+        break;
+    }
+    PrintLiteralWithModeIndented(buf.start(), var, node->name());
   }
-  PrintLiteralWithModeIndented(buf.start(), var, node->name());
 }
 
 
@@ -1580,7 +1593,9 @@
 
 
 void AstPrinter::VisitYield(Yield* node) {
-  IndentedScope indent(this, "YIELD", node->position());
+  EmbeddedVector<char, 128> buf;
+  SNPrintF(buf, "YIELD (kind %d)", node->yield_kind());
+  IndentedScope indent(this, buf.start(), node->position());
   Visit(node->expression());
 }
 
@@ -1608,7 +1623,9 @@
 
 void AstPrinter::VisitCall(Call* node) {
   EmbeddedVector<char, 128> buf;
-  FormatSlotNode(&buf, node, "CALL", node->CallFeedbackICSlot());
+  const char* name =
+      node->tail_call_mode() == TailCallMode::kAllow ? "TAIL CALL" : "CALL";
+  FormatSlotNode(&buf, node, name, node->CallFeedbackICSlot());
   IndentedScope indent(this, buf.start());
 
   Visit(node->expression());
@@ -1686,8 +1703,7 @@
 }
 
 
-void AstPrinter::VisitRewritableAssignmentExpression(
-    RewritableAssignmentExpression* node) {
+void AstPrinter::VisitRewritableExpression(RewritableExpression* node) {
   Visit(node->expression());
 }
 
diff --git a/src/ast/prettyprinter.h b/src/ast/prettyprinter.h
index 7e4dcdc..0186203 100644
--- a/src/ast/prettyprinter.h
+++ b/src/ast/prettyprinter.h
@@ -104,6 +104,9 @@
 
   const char* PrintProgram(FunctionLiteral* program);
 
+  // Print a node to stdout.
+  static void PrintOut(Isolate* isolate, AstNode* node);
+
   // Individual nodes
 #define DECLARE_VISIT(type) virtual void Visit##type(type* node);
   AST_NODE_LIST(DECLARE_VISIT)
diff --git a/src/ast/scopeinfo.cc b/src/ast/scopeinfo.cc
index 668879f..4ffc020 100644
--- a/src/ast/scopeinfo.cc
+++ b/src/ast/scopeinfo.cc
@@ -19,16 +19,12 @@
   ZoneList<Variable*> stack_locals(scope->StackLocalCount(), zone);
   ZoneList<Variable*> context_locals(scope->ContextLocalCount(), zone);
   ZoneList<Variable*> context_globals(scope->ContextGlobalCount(), zone);
-  ZoneList<Variable*> strong_mode_free_variables(0, zone);
 
   scope->CollectStackAndContextLocals(&stack_locals, &context_locals,
-                                      &context_globals,
-                                      &strong_mode_free_variables);
+                                      &context_globals);
   const int stack_local_count = stack_locals.length();
   const int context_local_count = context_locals.length();
   const int context_global_count = context_globals.length();
-  const int strong_mode_free_variable_count =
-      strong_mode_free_variables.length();
   // Make sure we allocate the correct amount.
   DCHECK_EQ(scope->ContextLocalCount(), context_local_count);
   DCHECK_EQ(scope->ContextGlobalCount(), context_global_count);
@@ -77,7 +73,6 @@
   const int length = kVariablePartIndex + parameter_count +
                      (1 + stack_local_count) + 2 * context_local_count +
                      2 * context_global_count +
-                     3 * strong_mode_free_variable_count +
                      (has_receiver ? 1 : 0) + (has_function_name ? 2 : 0);
 
   Factory* factory = isolate->factory();
@@ -104,7 +99,6 @@
   scope_info->SetStackLocalCount(stack_local_count);
   scope_info->SetContextLocalCount(context_local_count);
   scope_info->SetContextGlobalCount(context_global_count);
-  scope_info->SetStrongModeFreeVariableCount(strong_mode_free_variable_count);
 
   int index = kVariablePartIndex;
   // Add parameters.
@@ -173,25 +167,6 @@
     scope_info->set(index++, Smi::FromInt(value));
   }
 
-  DCHECK(index == scope_info->StrongModeFreeVariableNameEntriesIndex());
-  for (int i = 0; i < strong_mode_free_variable_count; ++i) {
-    scope_info->set(index++, *strong_mode_free_variables[i]->name());
-  }
-
-  DCHECK(index == scope_info->StrongModeFreeVariablePositionEntriesIndex());
-  for (int i = 0; i < strong_mode_free_variable_count; ++i) {
-    // Unfortunately, the source code positions are stored as int even though
-    // int32_t would be enough (given the maximum source code length).
-    Handle<Object> start_position = factory->NewNumberFromInt(
-        static_cast<int32_t>(strong_mode_free_variables[i]
-                                 ->strong_mode_reference_start_position()));
-    scope_info->set(index++, *start_position);
-    Handle<Object> end_position = factory->NewNumberFromInt(
-        static_cast<int32_t>(strong_mode_free_variables[i]
-                                 ->strong_mode_reference_end_position()));
-    scope_info->set(index++, *end_position);
-  }
-
   // If the receiver is allocated, add its index.
   DCHECK(index == scope_info->ReceiverEntryIndex());
   if (has_receiver) {
@@ -226,7 +201,6 @@
   const int stack_local_count = 0;
   const int context_local_count = 1;
   const int context_global_count = 0;
-  const int strong_mode_free_variable_count = 0;
   const bool has_simple_parameters = true;
   const VariableAllocationInfo receiver_info = CONTEXT;
   const VariableAllocationInfo function_name_info = NONE;
@@ -237,7 +211,6 @@
   const int length = kVariablePartIndex + parameter_count +
                      (1 + stack_local_count) + 2 * context_local_count +
                      2 * context_global_count +
-                     3 * strong_mode_free_variable_count +
                      (has_receiver ? 1 : 0) + (has_function_name ? 2 : 0);
 
   Factory* factory = isolate->factory();
@@ -259,7 +232,6 @@
   scope_info->SetStackLocalCount(stack_local_count);
   scope_info->SetContextLocalCount(context_local_count);
   scope_info->SetContextGlobalCount(context_global_count);
-  scope_info->SetStrongModeFreeVariableCount(strong_mode_free_variable_count);
 
   int index = kVariablePartIndex;
   const int first_slot_index = 0;
@@ -276,9 +248,6 @@
                          ContextLocalMaybeAssignedFlag::encode(kNotAssigned);
   scope_info->set(index++, Smi::FromInt(value));
 
-  DCHECK(index == scope_info->StrongModeFreeVariableNameEntriesIndex());
-  DCHECK(index == scope_info->StrongModeFreeVariablePositionEntriesIndex());
-
   // And here we record that this scopeinfo binds a receiver.
   DCHECK(index == scope_info->ReceiverEntryIndex());
   const int receiver_index = Context::MIN_CONTEXT_SLOTS + 0;
@@ -482,35 +451,6 @@
 }
 
 
-String* ScopeInfo::StrongModeFreeVariableName(int var) {
-  DCHECK(0 <= var && var < StrongModeFreeVariableCount());
-  int info_index = StrongModeFreeVariableNameEntriesIndex() + var;
-  return String::cast(get(info_index));
-}
-
-
-int ScopeInfo::StrongModeFreeVariableStartPosition(int var) {
-  DCHECK(0 <= var && var < StrongModeFreeVariableCount());
-  int info_index = StrongModeFreeVariablePositionEntriesIndex() + var * 2;
-  int32_t value = 0;
-  bool ok = get(info_index)->ToInt32(&value);
-  USE(ok);
-  DCHECK(ok);
-  return value;
-}
-
-
-int ScopeInfo::StrongModeFreeVariableEndPosition(int var) {
-  DCHECK(0 <= var && var < StrongModeFreeVariableCount());
-  int info_index = StrongModeFreeVariablePositionEntriesIndex() + var * 2 + 1;
-  int32_t value = 0;
-  bool ok = get(info_index)->ToInt32(&value);
-  USE(ok);
-  DCHECK(ok);
-  return value;
-}
-
-
 int ScopeInfo::StackSlotIndex(String* name) {
   DCHECK(name->IsInternalizedString());
   if (length() > 0) {
@@ -691,20 +631,8 @@
 }
 
 
-int ScopeInfo::StrongModeFreeVariableNameEntriesIndex() {
-  return ContextGlobalInfoEntriesIndex() + ContextGlobalCount();
-}
-
-
-int ScopeInfo::StrongModeFreeVariablePositionEntriesIndex() {
-  return StrongModeFreeVariableNameEntriesIndex() +
-         StrongModeFreeVariableCount();
-}
-
-
 int ScopeInfo::ReceiverEntryIndex() {
-  return StrongModeFreeVariablePositionEntriesIndex() +
-         2 * StrongModeFreeVariableCount();
+  return ContextGlobalInfoEntriesIndex() + ContextGlobalCount();
 }
 
 
diff --git a/src/ast/scopes.cc b/src/ast/scopes.cc
index c2b05b7..7c87ce3 100644
--- a/src/ast/scopes.cc
+++ b/src/ast/scopes.cc
@@ -27,12 +27,10 @@
       zone_(zone) {}
 VariableMap::~VariableMap() {}
 
-
 Variable* VariableMap::Declare(Scope* scope, const AstRawString* name,
                                VariableMode mode, Variable::Kind kind,
                                InitializationFlag initialization_flag,
-                               MaybeAssignedFlag maybe_assigned_flag,
-                               int declaration_group_start) {
+                               MaybeAssignedFlag maybe_assigned_flag) {
   // AstRawStrings are unambiguous, i.e., the same string is always represented
   // by the same AstRawString*.
   // FIXME(marja): fix the type of Lookup.
@@ -42,14 +40,8 @@
   if (p->value == NULL) {
     // The variable has not been declared yet -> insert it.
     DCHECK(p->key == name);
-    if (kind == Variable::CLASS) {
-      p->value = new (zone())
-          ClassVariable(scope, name, mode, initialization_flag,
-                        maybe_assigned_flag, declaration_group_start);
-    } else {
-      p->value = new (zone()) Variable(
-          scope, name, mode, kind, initialization_flag, maybe_assigned_flag);
-    }
+    p->value = new (zone()) Variable(scope, name, mode, kind,
+                                     initialization_flag, maybe_assigned_flag);
   }
   return reinterpret_cast<Variable*>(p->value);
 }
@@ -103,8 +95,7 @@
       sloppy_block_function_map_(zone),
       already_resolved_(false),
       ast_value_factory_(ast_value_factory),
-      zone_(zone),
-      class_declaration_group_start_(-1) {
+      zone_(zone) {
   SetDefaults(scope_type, outer_scope, Handle<ScopeInfo>::null(),
               function_kind);
   // The outermost scope must be a script scope.
@@ -112,7 +103,6 @@
   DCHECK(!HasIllegalRedeclaration());
 }
 
-
 Scope::Scope(Zone* zone, Scope* inner_scope, ScopeType scope_type,
              Handle<ScopeInfo> scope_info, AstValueFactory* value_factory)
     : inner_scopes_(4, zone),
@@ -125,8 +115,7 @@
       sloppy_block_function_map_(zone),
       already_resolved_(true),
       ast_value_factory_(value_factory),
-      zone_(zone),
-      class_declaration_group_start_(-1) {
+      zone_(zone) {
   SetDefaults(scope_type, NULL, scope_info);
   if (!scope_info.is_null()) {
     num_heap_slots_ = scope_info_->ContextLength();
@@ -137,7 +126,6 @@
   AddInnerScope(inner_scope);
 }
 
-
 Scope::Scope(Zone* zone, Scope* inner_scope,
              const AstRawString* catch_variable_name,
              AstValueFactory* value_factory)
@@ -151,8 +139,7 @@
       sloppy_block_function_map_(zone),
       already_resolved_(true),
       ast_value_factory_(value_factory),
-      zone_(zone),
-      class_declaration_group_start_(-1) {
+      zone_(zone) {
   SetDefaults(CATCH_SCOPE, NULL, Handle<ScopeInfo>::null());
   AddInnerScope(inner_scope);
   ++num_var_or_const_;
@@ -528,19 +515,17 @@
   return var;
 }
 
-
 Variable* Scope::DeclareLocal(const AstRawString* name, VariableMode mode,
                               InitializationFlag init_flag, Variable::Kind kind,
-                              MaybeAssignedFlag maybe_assigned_flag,
-                              int declaration_group_start) {
+                              MaybeAssignedFlag maybe_assigned_flag) {
   DCHECK(!already_resolved());
   // This function handles VAR, LET, and CONST modes.  DYNAMIC variables are
-  // introduces during variable allocation, and TEMPORARY variables are
+  // introduced during variable allocation, and TEMPORARY variables are
   // allocated via NewTemporary().
   DCHECK(IsDeclaredVariableMode(mode));
   ++num_var_or_const_;
   return variables_.Declare(this, name, mode, kind, init_flag,
-                            maybe_assigned_flag, declaration_group_start);
+                            maybe_assigned_flag);
 }
 
 
@@ -660,11 +645,9 @@
   int order_;
 };
 
-
-void Scope::CollectStackAndContextLocals(
-    ZoneList<Variable*>* stack_locals, ZoneList<Variable*>* context_locals,
-    ZoneList<Variable*>* context_globals,
-    ZoneList<Variable*>* strong_mode_free_variables) {
+void Scope::CollectStackAndContextLocals(ZoneList<Variable*>* stack_locals,
+                                         ZoneList<Variable*>* context_locals,
+                                         ZoneList<Variable*>* context_globals) {
   DCHECK(stack_locals != NULL);
   DCHECK(context_locals != NULL);
   DCHECK(context_globals != NULL);
@@ -691,11 +674,6 @@
        p != NULL;
        p = variables_.Next(p)) {
     Variable* var = reinterpret_cast<Variable*>(p->value);
-    if (strong_mode_free_variables && var->has_strong_mode_reference() &&
-        var->mode() == DYNAMIC_GLOBAL) {
-      strong_mode_free_variables->Add(var, zone());
-    }
-
     if (var->is_used()) {
       vars.Add(VarAndOrder(var, p->order), zone());
     }
@@ -1017,9 +995,7 @@
   if (HasTrivialOuterContext()) {
     Indent(n1, "// scope has trivial outer context\n");
   }
-  if (is_strong(language_mode())) {
-    Indent(n1, "// strong mode scope\n");
-  } else if (is_strict(language_mode())) {
+  if (is_strict(language_mode())) {
     Indent(n1, "// strict mode scope\n");
   }
   if (scope_inside_with_) Indent(n1, "// scope inside 'with'\n");
@@ -1204,10 +1180,6 @@
 
   switch (binding_kind) {
     case BOUND:
-      // We found a variable binding.
-      if (is_strong(language_mode())) {
-        if (!CheckStrongModeDeclaration(proxy, var)) return false;
-      }
       break;
 
     case BOUND_EVAL_SHADOWED:
@@ -1245,126 +1217,12 @@
   DCHECK(var != NULL);
   if (proxy->is_assigned()) var->set_maybe_assigned();
 
-  if (is_strong(language_mode())) {
-    // Record that the variable is referred to from strong mode. Also, record
-    // the position.
-    var->RecordStrongModeReference(proxy->position(), proxy->end_position());
-  }
-
   proxy->BindTo(var);
 
   return true;
 }
 
 
-bool Scope::CheckStrongModeDeclaration(VariableProxy* proxy, Variable* var) {
-  // Check for declaration-after use (for variables) in strong mode. Note that
-  // we can only do this in the case where we have seen the declaration. And we
-  // always allow referencing functions (for now).
-
-  // This might happen during lazy compilation; we don't keep track of
-  // initializer positions for variables stored in ScopeInfo, so we cannot check
-  // bindings against them. TODO(marja, rossberg): remove this hack.
-  if (var->initializer_position() == RelocInfo::kNoPosition) return true;
-
-  // Allow referencing the class name from methods of that class, even though
-  // the initializer position for class names is only after the body.
-  Scope* scope = this;
-  while (scope) {
-    if (scope->ClassVariableForMethod() == var) return true;
-    scope = scope->outer_scope();
-  }
-
-  // Allow references from methods to classes declared later, if we detect no
-  // problematic dependency cycles. Note that we can be inside multiple methods
-  // at the same time, and it's enough if we find one where the reference is
-  // allowed.
-  if (var->is_class() &&
-      var->AsClassVariable()->declaration_group_start() >= 0) {
-    for (scope = this; scope && scope != var->scope();
-         scope = scope->outer_scope()) {
-      ClassVariable* class_var = scope->ClassVariableForMethod();
-      // A method is referring to some other class, possibly declared
-      // later. Referring to a class declared earlier is always OK and covered
-      // by the code outside this if. Here we only need to allow special cases
-      // for referring to a class which is declared later.
-
-      // Referring to a class C declared later is OK under the following
-      // circumstances:
-
-      // 1. The class declarations are in a consecutive group with no other
-      // declarations or statements in between, and
-
-      // 2. There is no dependency cycle where the first edge is an
-      // initialization time dependency (computed property name or extends
-      // clause) from C to something that depends on this class directly or
-      // transitively.
-      if (class_var &&
-          class_var->declaration_group_start() ==
-              var->AsClassVariable()->declaration_group_start()) {
-        return true;
-      }
-
-      // TODO(marja,rossberg): implement the dependency cycle detection. Here we
-      // undershoot the target and allow referring to any class in the same
-      // consectuive declaration group.
-
-      // The cycle detection can work roughly like this: 1) detect init-time
-      // references here (they are free variables which are inside the class
-      // scope but not inside a method scope - no parser changes needed to
-      // detect them) 2) if we encounter an init-time reference here, allow it,
-      // but record it for a later dependency cycle check 3) also record
-      // non-init-time references here 4) after scope analysis is done, analyse
-      // the dependency cycles: an illegal cycle is one starting with an
-      // init-time reference and leading back to the starting point with either
-      // non-init-time and init-time references.
-    }
-  }
-
-  // If both the use and the declaration are inside an eval scope (possibly
-  // indirectly), or one of them is, we need to check whether they are inside
-  // the same eval scope or different ones.
-
-  // TODO(marja,rossberg): Detect errors across different evals (depends on the
-  // future of eval in strong mode).
-  const Scope* eval_for_use = NearestOuterEvalScope();
-  const Scope* eval_for_declaration = var->scope()->NearestOuterEvalScope();
-
-  if (proxy->position() != RelocInfo::kNoPosition &&
-      proxy->position() < var->initializer_position() && !var->is_function() &&
-      eval_for_use == eval_for_declaration) {
-    DCHECK(proxy->end_position() != RelocInfo::kNoPosition);
-    ReportMessage(proxy->position(), proxy->end_position(),
-                  MessageTemplate::kStrongUseBeforeDeclaration,
-                  proxy->raw_name());
-    return false;
-  }
-  return true;
-}
-
-
-ClassVariable* Scope::ClassVariableForMethod() const {
-  // TODO(marja, rossberg): This fails to find a class variable in the following
-  // cases:
-  // let A = class { ... }
-  // It needs to be investigated whether this causes any practical problems.
-  if (!is_function_scope()) return nullptr;
-  if (IsInObjectLiteral(function_kind_)) return nullptr;
-  if (!IsConciseMethod(function_kind_) && !IsClassConstructor(function_kind_) &&
-      !IsAccessorFunction(function_kind_)) {
-    return nullptr;
-  }
-  DCHECK_NOT_NULL(outer_scope_);
-  // The class scope contains at most one variable, the class name.
-  DCHECK(outer_scope_->variables_.occupancy() <= 1);
-  if (outer_scope_->variables_.occupancy() == 0) return nullptr;
-  VariableMap::Entry* p = outer_scope_->variables_.Start();
-  Variable* var = reinterpret_cast<Variable*>(p->value);
-  if (!var->is_class()) return nullptr;
-  return var->AsClassVariable();
-}
-
-
 bool Scope::ResolveVariablesRecursively(ParseInfo* info,
                                         AstNodeFactory* factory) {
   DCHECK(info->script_scope()->is_script_scope());
@@ -1646,7 +1504,7 @@
   }
 
   // If scope is already resolved, we still need to allocate
-  // variables in inner scopes which might not had been resolved yet.
+  // variables in inner scopes which might not have been resolved yet.
   if (already_resolved()) return;
   // The number of slots required for variables.
   num_heap_slots_ = Context::MIN_CONTEXT_SLOTS;
diff --git a/src/ast/scopes.h b/src/ast/scopes.h
index 6c261f6..76f761d 100644
--- a/src/ast/scopes.h
+++ b/src/ast/scopes.h
@@ -24,8 +24,7 @@
 
   Variable* Declare(Scope* scope, const AstRawString* name, VariableMode mode,
                     Variable::Kind kind, InitializationFlag initialization_flag,
-                    MaybeAssignedFlag maybe_assigned_flag = kNotAssigned,
-                    int declaration_group_start = -1);
+                    MaybeAssignedFlag maybe_assigned_flag = kNotAssigned);
 
   Variable* Lookup(const AstRawString* name);
 
@@ -163,8 +162,7 @@
   // declared before, the previously declared variable is returned.
   Variable* DeclareLocal(const AstRawString* name, VariableMode mode,
                          InitializationFlag init_flag, Variable::Kind kind,
-                         MaybeAssignedFlag maybe_assigned_flag = kNotAssigned,
-                         int declaration_group_start = -1);
+                         MaybeAssignedFlag maybe_assigned_flag = kNotAssigned);
 
   // Declare an implicit global variable in this scope which must be a
   // script scope.  The variable was introduced (possibly from an inner
@@ -377,12 +375,6 @@
              IsClassConstructor(function_kind())));
   }
 
-  const Scope* NearestOuterEvalScope() const {
-    if (is_eval_scope()) return this;
-    if (outer_scope() == nullptr) return nullptr;
-    return outer_scope()->NearestOuterEvalScope();
-  }
-
   // ---------------------------------------------------------------------------
   // Accessors.
 
@@ -428,7 +420,24 @@
   // Returns the default function arity excluding default or rest parameters.
   int default_function_length() const { return arity_; }
 
-  int num_parameters() const { return params_.length(); }
+  // Returns the number of formal parameters, up to but not including the
+  // rest parameter index (if the function has rest parameters), i.e. it
+  // says 2 for
+  //
+  //   function foo(a, b) { ... }
+  //
+  // and
+  //
+  //   function foo(a, b, ...c) { ... }
+  //
+  // but for
+  //
+  //   function foo(a, b, c = 1) { ... }
+  //
+  // we return 3 here.
+  int num_parameters() const {
+    return has_rest_parameter() ? params_.length() - 1 : params_.length();
+  }
 
   // A function can have at most one rest parameter. Returns Variable* or NULL.
   Variable* rest_parameter(int* index) const {
@@ -486,25 +495,15 @@
   // The ModuleDescriptor for this scope; only for module scopes.
   ModuleDescriptor* module() const { return module_descriptor_; }
 
-
-  void set_class_declaration_group_start(int position) {
-    class_declaration_group_start_ = position;
-  }
-
-  int class_declaration_group_start() const {
-    return class_declaration_group_start_;
-  }
-
   // ---------------------------------------------------------------------------
   // Variable allocation.
 
   // Collect stack and context allocated local variables in this scope. Note
   // that the function variable - if present - is not collected and should be
   // handled separately.
-  void CollectStackAndContextLocals(
-      ZoneList<Variable*>* stack_locals, ZoneList<Variable*>* context_locals,
-      ZoneList<Variable*>* context_globals,
-      ZoneList<Variable*>* strong_mode_free_variables = nullptr);
+  void CollectStackAndContextLocals(ZoneList<Variable*>* stack_locals,
+                                    ZoneList<Variable*>* context_locals,
+                                    ZoneList<Variable*>* context_globals);
 
   // Current number of var or const locals.
   int num_var_or_const() { return num_var_or_const_; }
@@ -767,12 +766,6 @@
   MUST_USE_RESULT
   bool ResolveVariablesRecursively(ParseInfo* info, AstNodeFactory* factory);
 
-  bool CheckStrongModeDeclaration(VariableProxy* proxy, Variable* var);
-
-  // If this scope is a method scope of a class, return the corresponding
-  // class variable, otherwise nullptr.
-  ClassVariable* ClassVariableForMethod() const;
-
   // Scope analysis.
   void PropagateScopeInfo(bool outer_scope_calls_sloppy_eval);
   bool HasTrivialContext() const;
@@ -837,10 +830,6 @@
   Zone* zone_;
 
   PendingCompilationErrorHandler pending_error_handler_;
-
-  // For tracking which classes are declared consecutively. Needed for strong
-  // mode.
-  int class_declaration_group_start_;
 };
 
 }  // namespace internal
diff --git a/src/ast/variables.cc b/src/ast/variables.cc
index 8e00782..7b9a5d2 100644
--- a/src/ast/variables.cc
+++ b/src/ast/variables.cc
@@ -40,9 +40,6 @@
       location_(VariableLocation::UNALLOCATED),
       index_(-1),
       initializer_position_(RelocInfo::kNoPosition),
-      has_strong_mode_reference_(false),
-      strong_mode_reference_start_position_(RelocInfo::kNoPosition),
-      strong_mode_reference_end_position_(RelocInfo::kNoPosition),
       local_if_not_shadowed_(NULL),
       is_from_eval_(false),
       force_context_allocation_(false),
diff --git a/src/ast/variables.h b/src/ast/variables.h
index ca5d1cd..b8bb07e 100644
--- a/src/ast/variables.h
+++ b/src/ast/variables.h
@@ -15,12 +15,9 @@
 // variables. Variables themselves are never directly referred to from the AST,
 // they are maintained by scopes, and referred to from VariableProxies and Slots
 // after binding and variable allocation.
-
-class ClassVariable;
-
 class Variable: public ZoneObject {
  public:
-  enum Kind { NORMAL, FUNCTION, CLASS, THIS, ARGUMENTS };
+  enum Kind { NORMAL, FUNCTION, THIS, ARGUMENTS };
 
   Variable(Scope* scope, const AstRawString* name, VariableMode mode, Kind kind,
            InitializationFlag initialization_flag,
@@ -84,7 +81,6 @@
   }
 
   bool is_function() const { return kind_ == FUNCTION; }
-  bool is_class() const { return kind_ == CLASS; }
   bool is_this() const { return kind_ == THIS; }
   bool is_arguments() const { return kind_ == ARGUMENTS; }
 
@@ -98,11 +94,6 @@
     return is_this() || *name() == *isolate->factory()->this_string();
   }
 
-  ClassVariable* AsClassVariable() {
-    DCHECK(is_class());
-    return reinterpret_cast<ClassVariable*>(this);
-  }
-
   // True if the variable is named eval and not known to be shadowed.
   bool is_possibly_eval(Isolate* isolate) const {
     return IsVariable(isolate->factory()->eval_string());
@@ -132,24 +123,6 @@
 
   static int CompareIndex(Variable* const* v, Variable* const* w);
 
-  void RecordStrongModeReference(int start_position, int end_position) {
-    // Record the earliest reference to the variable. Used in error messages for
-    // strong mode references to undeclared variables.
-    if (has_strong_mode_reference_ &&
-        strong_mode_reference_start_position_ < start_position)
-      return;
-    has_strong_mode_reference_ = true;
-    strong_mode_reference_start_position_ = start_position;
-    strong_mode_reference_end_position_ = end_position;
-  }
-
-  bool has_strong_mode_reference() const { return has_strong_mode_reference_; }
-  int strong_mode_reference_start_position() const {
-    return strong_mode_reference_start_position_;
-  }
-  int strong_mode_reference_end_position() const {
-    return strong_mode_reference_end_position_;
-  }
   PropertyAttributes DeclarationPropertyAttributes() const {
     int property_attributes = NONE;
     if (IsImmutableVariableMode(mode_)) {
@@ -169,11 +142,6 @@
   VariableLocation location_;
   int index_;
   int initializer_position_;
-  // Tracks whether the variable is bound to a VariableProxy which is in strong
-  // mode, and if yes, the source location of the reference.
-  bool has_strong_mode_reference_;
-  int strong_mode_reference_start_position_;
-  int strong_mode_reference_end_position_;
 
   // If this field is set, this variable references the stored locally bound
   // variable, but it might be shadowed by variable bindings introduced by
@@ -190,28 +158,6 @@
   InitializationFlag initialization_flag_;
   MaybeAssignedFlag maybe_assigned_;
 };
-
-class ClassVariable : public Variable {
- public:
-  ClassVariable(Scope* scope, const AstRawString* name, VariableMode mode,
-                InitializationFlag initialization_flag,
-                MaybeAssignedFlag maybe_assigned_flag = kNotAssigned,
-                int declaration_group_start = -1)
-      : Variable(scope, name, mode, Variable::CLASS, initialization_flag,
-                 maybe_assigned_flag),
-        declaration_group_start_(declaration_group_start) {}
-
-  int declaration_group_start() const { return declaration_group_start_; }
-  void set_declaration_group_start(int declaration_group_start) {
-    declaration_group_start_ = declaration_group_start;
-  }
-
- private:
-  // For classes we keep track of consecutive groups of delcarations. They are
-  // needed for strong mode scoping checks. TODO(marja, rossberg): Implement
-  // checks for functions too.
-  int declaration_group_start_;
-};
 }  // namespace internal
 }  // namespace v8