// Copyright 2012 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef V8_AST_H_
#define V8_AST_H_

#include "src/assembler.h"
#include "src/ast-value-factory.h"
#include "src/bailout-reason.h"
#include "src/base/flags.h"
#include "src/base/smart-pointers.h"
#include "src/factory.h"
#include "src/isolate.h"
#include "src/list.h"
#include "src/modules.h"
#include "src/regexp/jsregexp.h"
#include "src/runtime/runtime.h"
#include "src/small-pointer-list.h"
#include "src/token.h"
#include "src/types.h"
#include "src/utils.h"
#include "src/variables.h"

namespace v8 {
namespace internal {

// The abstract syntax tree is an intermediate, light-weight
// representation of the parsed JavaScript code suitable for
// compilation to native code.

// Nodes are allocated in a separate zone, which allows faster
// allocation and constant-time deallocation of the entire syntax
// tree.


// ----------------------------------------------------------------------------
// Nodes of the abstract syntax tree. Only concrete classes are
// enumerated here.

#define DECLARATION_NODE_LIST(V) \
  V(VariableDeclaration)         \
  V(FunctionDeclaration)         \
  V(ImportDeclaration)           \
  V(ExportDeclaration)

#define STATEMENT_NODE_LIST(V)                  \
  V(Block)                                      \
  V(ExpressionStatement)                        \
  V(EmptyStatement)                             \
  V(IfStatement)                                \
  V(ContinueStatement)                          \
  V(BreakStatement)                             \
  V(ReturnStatement)                            \
  V(WithStatement)                              \
  V(SwitchStatement)                            \
  V(DoWhileStatement)                           \
  V(WhileStatement)                             \
  V(ForStatement)                               \
  V(ForInStatement)                             \
  V(ForOfStatement)                             \
  V(TryCatchStatement)                          \
  V(TryFinallyStatement)                        \
  V(DebuggerStatement)

#define EXPRESSION_NODE_LIST(V) \
  V(FunctionLiteral)            \
  V(ClassLiteral)               \
  V(NativeFunctionLiteral)      \
  V(Conditional)                \
  V(VariableProxy)              \
  V(Literal)                    \
  V(RegExpLiteral)              \
  V(ObjectLiteral)              \
  V(ArrayLiteral)               \
  V(Assignment)                 \
  V(Yield)                      \
  V(Throw)                      \
  V(Property)                   \
  V(Call)                       \
  V(CallNew)                    \
  V(CallRuntime)                \
  V(UnaryOperation)             \
  V(CountOperation)             \
  V(BinaryOperation)            \
  V(CompareOperation)           \
  V(Spread)                     \
  V(ThisFunction)               \
  V(SuperPropertyReference)     \
  V(SuperCallReference)         \
  V(CaseClause)                 \
  V(EmptyParentheses)

#define AST_NODE_LIST(V)                        \
  DECLARATION_NODE_LIST(V)                      \
  STATEMENT_NODE_LIST(V)                        \
  EXPRESSION_NODE_LIST(V)

// Forward declarations
class AstNodeFactory;
class AstVisitor;
class Declaration;
class Module;
class BreakableStatement;
class Expression;
class IterationStatement;
class MaterializedLiteral;
class Statement;
class TypeFeedbackOracle;

class RegExpAlternative;
class RegExpAssertion;
class RegExpAtom;
class RegExpBackReference;
class RegExpCapture;
class RegExpCharacterClass;
class RegExpCompiler;
class RegExpDisjunction;
class RegExpEmpty;
class RegExpLookahead;
class RegExpQuantifier;
class RegExpText;

#define DEF_FORWARD_DECLARATION(type) class type;
AST_NODE_LIST(DEF_FORWARD_DECLARATION)
#undef DEF_FORWARD_DECLARATION


// Typedef only introduced to avoid unreadable code.
typedef ZoneList<Handle<String>> ZoneStringList;
typedef ZoneList<Handle<Object>> ZoneObjectList;


#define DECLARE_NODE_TYPE(type)                                          \
  void Accept(AstVisitor* v) override;                                   \
  AstNode::NodeType node_type() const final { return AstNode::k##type; } \
  friend class AstNodeFactory;


class FeedbackVectorRequirements {
 public:
  FeedbackVectorRequirements(int slots, int ic_slots)
      : slots_(slots), ic_slots_(ic_slots) {}

  int slots() const { return slots_; }
  int ic_slots() const { return ic_slots_; }

 private:
  int slots_;
  int ic_slots_;
};


class ICSlotCache {
 public:
  explicit ICSlotCache(Zone* zone)
      : zone_(zone),
        hash_map_(HashMap::PointersMatch, ZoneHashMap::kDefaultHashMapCapacity,
                  ZoneAllocationPolicy(zone)) {}

  void Put(Variable* variable, FeedbackVectorICSlot slot) {
    ZoneHashMap::Entry* entry = hash_map_.LookupOrInsert(
        variable, ComputePointerHash(variable), ZoneAllocationPolicy(zone_));
    entry->value = reinterpret_cast<void*>(slot.ToInt());
  }

  ZoneHashMap::Entry* Get(Variable* variable) const {
    return hash_map_.Lookup(variable, ComputePointerHash(variable));
  }

 private:
  Zone* zone_;
  ZoneHashMap hash_map_;
};


class AstProperties final BASE_EMBEDDED {
 public:
  enum Flag {
    kNoFlags = 0,
    kDontSelfOptimize = 1 << 0,
    kDontCrankshaft = 1 << 1
  };

  typedef base::Flags<Flag> Flags;

  explicit AstProperties(Zone* zone) : node_count_(0), spec_(zone) {}

  Flags& flags() { return flags_; }
  Flags flags() const { return flags_; }
  int node_count() { return node_count_; }
  void add_node_count(int count) { node_count_ += count; }

  int slots() const { return spec_.slots(); }
  void increase_slots(int count) { spec_.increase_slots(count); }

  int ic_slots() const { return spec_.ic_slots(); }
  void increase_ic_slots(int count) { spec_.increase_ic_slots(count); }
  void SetKind(int ic_slot, Code::Kind kind) { spec_.SetKind(ic_slot, kind); }
  const ZoneFeedbackVectorSpec* get_spec() const { return &spec_; }

 private:
  Flags flags_;
  int node_count_;
  ZoneFeedbackVectorSpec spec_;
};

DEFINE_OPERATORS_FOR_FLAGS(AstProperties::Flags)


class AstNode: public ZoneObject {
 public:
#define DECLARE_TYPE_ENUM(type) k##type,
  enum NodeType {
    AST_NODE_LIST(DECLARE_TYPE_ENUM)
    kInvalid = -1
  };
#undef DECLARE_TYPE_ENUM

  void* operator new(size_t size, Zone* zone) { return zone->New(size); }

  explicit AstNode(int position): position_(position) {}
  virtual ~AstNode() {}

  virtual void Accept(AstVisitor* v) = 0;
  virtual NodeType node_type() const = 0;
  int position() const { return position_; }

  // 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; \
  }
  AST_NODE_LIST(DECLARE_NODE_FUNCTIONS)
#undef DECLARE_NODE_FUNCTIONS

  virtual BreakableStatement* AsBreakableStatement() { return NULL; }
  virtual IterationStatement* AsIterationStatement() { return NULL; }
  virtual MaterializedLiteral* AsMaterializedLiteral() { return NULL; }

  // The interface for feedback slots, with default no-op implementations for
  // node types which don't actually have this. Note that this is conceptually
  // not really nice, but multiple inheritance would introduce yet another
  // vtable entry per node, something we don't want for space reasons.
  virtual FeedbackVectorRequirements ComputeFeedbackRequirements(
      Isolate* isolate, const ICSlotCache* cache) {
    return FeedbackVectorRequirements(0, 0);
  }
  virtual void SetFirstFeedbackSlot(FeedbackVectorSlot slot) { UNREACHABLE(); }
  virtual void SetFirstFeedbackICSlot(FeedbackVectorICSlot slot,
                                      ICSlotCache* cache) {
    UNREACHABLE();
  }
  // Each ICSlot stores a kind of IC which the participating node should know.
  virtual Code::Kind FeedbackICSlotKind(int index) {
    UNREACHABLE();
    return Code::NUMBER_OF_KINDS;
  }

 private:
  // Hidden to prevent accidental usage. It would have to load the
  // current zone from the TLS.
  void* operator new(size_t size);

  friend class CaseClause;  // Generates AST IDs.

  int position_;
};


class Statement : public AstNode {
 public:
  explicit Statement(Zone* zone, int position) : AstNode(position) {}

  bool IsEmpty() { return AsEmptyStatement() != NULL; }
  virtual bool IsJump() const { return false; }
};


class SmallMapList final {
 public:
  SmallMapList() {}
  SmallMapList(int capacity, Zone* zone) : list_(capacity, zone) {}

  void Reserve(int capacity, Zone* zone) { list_.Reserve(capacity, zone); }
  void Clear() { list_.Clear(); }
  void Sort() { list_.Sort(); }

  bool is_empty() const { return list_.is_empty(); }
  int length() const { return list_.length(); }

  void AddMapIfMissing(Handle<Map> map, Zone* zone) {
    if (!Map::TryUpdate(map).ToHandle(&map)) return;
    for (int i = 0; i < length(); ++i) {
      if (at(i).is_identical_to(map)) return;
    }
    Add(map, zone);
  }

  void FilterForPossibleTransitions(Map* root_map) {
    for (int i = list_.length() - 1; i >= 0; i--) {
      if (at(i)->FindRootMap() != root_map) {
        list_.RemoveElement(list_.at(i));
      }
    }
  }

  void Add(Handle<Map> handle, Zone* zone) {
    list_.Add(handle.location(), zone);
  }

  Handle<Map> at(int i) const {
    return Handle<Map>(list_.at(i));
  }

  Handle<Map> first() const { return at(0); }
  Handle<Map> last() const { return at(length() - 1); }

 private:
  // The list stores pointers to Map*, that is Map**, so it's GC safe.
  SmallPointerList<Map*> list_;

  DISALLOW_COPY_AND_ASSIGN(SmallMapList);
};


class Expression : public AstNode {
 public:
  enum Context {
    // Not assigned a context yet, or else will not be visited during
    // code generation.
    kUninitialized,
    // Evaluated for its side effects.
    kEffect,
    // Evaluated for its value (and side effects).
    kValue,
    // Evaluated for control flow (and side effects).
    kTest
  };

  // True iff the expression is a valid reference expression.
  virtual bool IsValidReferenceExpression() const { return false; }

  // Helpers for ToBoolean conversion.
  virtual bool ToBooleanIsTrue() const { return false; }
  virtual bool ToBooleanIsFalse() const { return false; }

  // Symbols that cannot be parsed as array indices are considered property
  // names.  We do not treat symbols that can be array indexes as property
  // names because [] for string objects is handled only by keyed ICs.
  virtual bool IsPropertyName() const { return false; }

  // True iff the expression is a literal represented as a smi.
  bool IsSmiLiteral() const;

  // True iff the expression is a string literal.
  bool IsStringLiteral() const;

  // True iff the expression is the null literal.
  bool IsNullLiteral() const;

  // True if we can prove that the expression is the undefined literal.
  bool IsUndefinedLiteral(Isolate* isolate) const;

  // True iff the expression is a valid target for an assignment.
  bool IsValidReferenceExpressionOrThis() const;

  // Expression type bounds
  Bounds bounds() const { return bounds_; }
  void set_bounds(Bounds bounds) { bounds_ = bounds; }

  // Type feedback information for assignments and properties.
  virtual bool IsMonomorphic() {
    UNREACHABLE();
    return false;
  }
  virtual SmallMapList* GetReceiverTypes() {
    UNREACHABLE();
    return NULL;
  }
  virtual KeyedAccessStoreMode GetStoreMode() const {
    UNREACHABLE();
    return STANDARD_STORE;
  }
  virtual IcCheckType GetKeyType() const {
    UNREACHABLE();
    return ELEMENT;
  }

  // TODO(rossberg): this should move to its own AST node eventually.
  virtual void RecordToBooleanTypeFeedback(TypeFeedbackOracle* oracle);
  uint16_t to_boolean_types() const {
    return ToBooleanTypesField::decode(bit_field_);
  }

  void set_base_id(int id) { base_id_ = id; }
  static int num_ids() { return parent_num_ids() + 2; }
  BailoutId id() const { return BailoutId(local_id(0)); }
  TypeFeedbackId test_id() const { return TypeFeedbackId(local_id(1)); }

 protected:
  Expression(Zone* zone, int pos)
      : AstNode(pos),
        base_id_(BailoutId::None().ToInt()),
        bounds_(Bounds::Unbounded()),
        bit_field_(0) {}
  static int parent_num_ids() { return 0; }
  void set_to_boolean_types(uint16_t types) {
    bit_field_ = ToBooleanTypesField::update(bit_field_, types);
  }

  int base_id() const {
    DCHECK(!BailoutId(base_id_).IsNone());
    return base_id_;
  }

 private:
  int local_id(int n) const { return base_id() + parent_num_ids() + n; }

  int base_id_;
  Bounds bounds_;
  class ToBooleanTypesField : public BitField16<uint16_t, 0, 9> {};
  uint16_t bit_field_;
  // Ends with 16-bit field; deriving classes in turn begin with
  // 16-bit fields for optimum packing efficiency.
};


class BreakableStatement : public Statement {
 public:
  enum BreakableType {
    TARGET_FOR_ANONYMOUS,
    TARGET_FOR_NAMED_ONLY
  };

  // The labels associated with this statement. May be NULL;
  // if it is != NULL, guaranteed to contain at least one entry.
  ZoneList<const AstRawString*>* labels() const { return labels_; }

  // Type testing & conversion.
  BreakableStatement* AsBreakableStatement() final { return this; }

  // Code generation
  Label* break_target() { return &break_target_; }

  // Testers.
  bool is_target_for_anonymous() const {
    return breakable_type_ == TARGET_FOR_ANONYMOUS;
  }

  void set_base_id(int id) { base_id_ = id; }
  static int num_ids() { return parent_num_ids() + 2; }
  BailoutId EntryId() const { return BailoutId(local_id(0)); }
  BailoutId ExitId() const { return BailoutId(local_id(1)); }

 protected:
  BreakableStatement(Zone* zone, ZoneList<const AstRawString*>* labels,
                     BreakableType breakable_type, int position)
      : Statement(zone, position),
        labels_(labels),
        breakable_type_(breakable_type),
        base_id_(BailoutId::None().ToInt()) {
    DCHECK(labels == NULL || labels->length() > 0);
  }
  static int parent_num_ids() { return 0; }

  int base_id() const {
    DCHECK(!BailoutId(base_id_).IsNone());
    return base_id_;
  }

 private:
  int local_id(int n) const { return base_id() + parent_num_ids() + n; }

  ZoneList<const AstRawString*>* labels_;
  BreakableType breakable_type_;
  Label break_target_;
  int base_id_;
};


class Block final : public BreakableStatement {
 public:
  DECLARE_NODE_TYPE(Block)

  void AddStatement(Statement* statement, Zone* zone) {
    statements_.Add(statement, zone);
  }

  ZoneList<Statement*>* statements() { return &statements_; }
  bool ignore_completion_value() const { return ignore_completion_value_; }

  static int num_ids() { return parent_num_ids() + 1; }
  BailoutId DeclsId() const { return BailoutId(local_id(0)); }

  bool IsJump() const override {
    return !statements_.is_empty() && statements_.last()->IsJump()
        && labels() == NULL;  // Good enough as an approximation...
  }

  Scope* scope() const { return scope_; }
  void set_scope(Scope* scope) { scope_ = scope; }

 protected:
  Block(Zone* zone, ZoneList<const AstRawString*>* labels, int capacity,
        bool ignore_completion_value, int pos)
      : BreakableStatement(zone, labels, TARGET_FOR_NAMED_ONLY, pos),
        statements_(capacity, zone),
        ignore_completion_value_(ignore_completion_value),
        scope_(NULL) {}
  static int parent_num_ids() { return BreakableStatement::num_ids(); }

 private:
  int local_id(int n) const { return base_id() + parent_num_ids() + n; }

  ZoneList<Statement*> statements_;
  bool ignore_completion_value_;
  Scope* scope_;
};


class Declaration : public AstNode {
 public:
  VariableProxy* proxy() const { return proxy_; }
  VariableMode mode() const { return mode_; }
  Scope* scope() const { return scope_; }
  virtual InitializationFlag initialization() const = 0;
  virtual bool IsInlineable() const;

 protected:
  Declaration(Zone* zone, VariableProxy* proxy, VariableMode mode, Scope* scope,
              int pos)
      : AstNode(pos), mode_(mode), proxy_(proxy), scope_(scope) {
    DCHECK(IsDeclaredVariableMode(mode));
  }

 private:
  VariableMode mode_;
  VariableProxy* proxy_;

  // Nested scope from which the declaration originated.
  Scope* scope_;
};


class VariableDeclaration final : public Declaration {
 public:
  DECLARE_NODE_TYPE(VariableDeclaration)

  InitializationFlag initialization() const override {
    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_;
};


class FunctionDeclaration final : public Declaration {
 public:
  DECLARE_NODE_TYPE(FunctionDeclaration)

  FunctionLiteral* fun() const { return fun_; }
  InitializationFlag initialization() const override {
    return kCreatedInitialized;
  }
  bool IsInlineable() const override;

 protected:
  FunctionDeclaration(Zone* zone,
                      VariableProxy* proxy,
                      VariableMode mode,
                      FunctionLiteral* fun,
                      Scope* scope,
                      int pos)
      : Declaration(zone, proxy, mode, scope, pos),
        fun_(fun) {
    DCHECK(mode == VAR || mode == LET || mode == CONST);
    DCHECK(fun != NULL);
  }

 private:
  FunctionLiteral* fun_;
};


class ImportDeclaration final : public Declaration {
 public:
  DECLARE_NODE_TYPE(ImportDeclaration)

  const AstRawString* import_name() const { return import_name_; }
  const AstRawString* module_specifier() const { return module_specifier_; }
  void set_module_specifier(const AstRawString* module_specifier) {
    DCHECK(module_specifier_ == NULL);
    module_specifier_ = module_specifier;
  }
  InitializationFlag initialization() const override {
    return kNeedsInitialization;
  }

 protected:
  ImportDeclaration(Zone* zone, VariableProxy* proxy,
                    const AstRawString* import_name,
                    const AstRawString* module_specifier, Scope* scope, int pos)
      : Declaration(zone, proxy, IMPORT, scope, pos),
        import_name_(import_name),
        module_specifier_(module_specifier) {}

 private:
  const AstRawString* import_name_;
  const AstRawString* module_specifier_;
};


class ExportDeclaration final : public Declaration {
 public:
  DECLARE_NODE_TYPE(ExportDeclaration)

  InitializationFlag initialization() const override {
    return kCreatedInitialized;
  }

 protected:
  ExportDeclaration(Zone* zone, VariableProxy* proxy, Scope* scope, int pos)
      : Declaration(zone, proxy, LET, scope, pos) {}
};


class Module : public AstNode {
 public:
  ModuleDescriptor* descriptor() const { return descriptor_; }
  Block* body() const { return body_; }

 protected:
  Module(Zone* zone, int pos)
      : AstNode(pos), descriptor_(ModuleDescriptor::New(zone)), body_(NULL) {}
  Module(Zone* zone, ModuleDescriptor* descriptor, int pos, Block* body = NULL)
      : AstNode(pos), descriptor_(descriptor), body_(body) {}

 private:
  ModuleDescriptor* descriptor_;
  Block* body_;
};


class IterationStatement : public BreakableStatement {
 public:
  // Type testing & conversion.
  IterationStatement* AsIterationStatement() final { return this; }

  Statement* body() const { return body_; }

  static int num_ids() { return parent_num_ids() + 1; }
  BailoutId OsrEntryId() const { return BailoutId(local_id(0)); }
  virtual BailoutId ContinueId() const = 0;
  virtual BailoutId StackCheckId() const = 0;

  // Code generation
  Label* continue_target()  { return &continue_target_; }

 protected:
  IterationStatement(Zone* zone, ZoneList<const AstRawString*>* labels, int pos)
      : BreakableStatement(zone, labels, TARGET_FOR_ANONYMOUS, pos),
        body_(NULL) {}
  static int parent_num_ids() { return BreakableStatement::num_ids(); }
  void Initialize(Statement* body) { body_ = body; }

 private:
  int local_id(int n) const { return base_id() + parent_num_ids() + n; }

  Statement* body_;
  Label continue_target_;
};


class DoWhileStatement final : public IterationStatement {
 public:
  DECLARE_NODE_TYPE(DoWhileStatement)

  void Initialize(Expression* cond, Statement* body) {
    IterationStatement::Initialize(body);
    cond_ = cond;
  }

  Expression* cond() const { return cond_; }

  static int num_ids() { return parent_num_ids() + 2; }
  BailoutId ContinueId() const override { return BailoutId(local_id(0)); }
  BailoutId StackCheckId() const override { return BackEdgeId(); }
  BailoutId BackEdgeId() const { return BailoutId(local_id(1)); }

 protected:
  DoWhileStatement(Zone* zone, ZoneList<const AstRawString*>* labels, int pos)
      : IterationStatement(zone, labels, pos), cond_(NULL) {}
  static int parent_num_ids() { return IterationStatement::num_ids(); }

 private:
  int local_id(int n) const { return base_id() + parent_num_ids() + n; }

  Expression* cond_;
};


class WhileStatement final : public IterationStatement {
 public:
  DECLARE_NODE_TYPE(WhileStatement)

  void Initialize(Expression* cond, Statement* body) {
    IterationStatement::Initialize(body);
    cond_ = cond;
  }

  Expression* cond() const { return cond_; }

  static int num_ids() { return parent_num_ids() + 1; }
  BailoutId ContinueId() const override { return EntryId(); }
  BailoutId StackCheckId() const override { return BodyId(); }
  BailoutId BodyId() const { return BailoutId(local_id(0)); }

 protected:
  WhileStatement(Zone* zone, ZoneList<const AstRawString*>* labels, int pos)
      : IterationStatement(zone, labels, pos), cond_(NULL) {}
  static int parent_num_ids() { return IterationStatement::num_ids(); }

 private:
  int local_id(int n) const { return base_id() + parent_num_ids() + n; }

  Expression* cond_;
};


class ForStatement final : public IterationStatement {
 public:
  DECLARE_NODE_TYPE(ForStatement)

  void Initialize(Statement* init,
                  Expression* cond,
                  Statement* next,
                  Statement* body) {
    IterationStatement::Initialize(body);
    init_ = init;
    cond_ = cond;
    next_ = next;
  }

  Statement* init() const { return init_; }
  Expression* cond() const { return cond_; }
  Statement* next() const { return next_; }

  static int num_ids() { return parent_num_ids() + 2; }
  BailoutId ContinueId() const override { return BailoutId(local_id(0)); }
  BailoutId StackCheckId() const override { return BodyId(); }
  BailoutId BodyId() const { return BailoutId(local_id(1)); }

 protected:
  ForStatement(Zone* zone, ZoneList<const AstRawString*>* labels, int pos)
      : IterationStatement(zone, labels, pos),
        init_(NULL),
        cond_(NULL),
        next_(NULL) {}
  static int parent_num_ids() { return IterationStatement::num_ids(); }

 private:
  int local_id(int n) const { return base_id() + parent_num_ids() + n; }

  Statement* init_;
  Expression* cond_;
  Statement* next_;
};


class ForEachStatement : public IterationStatement {
 public:
  enum VisitMode {
    ENUMERATE,   // for (each in subject) body;
    ITERATE      // for (each of subject) body;
  };

  void Initialize(Expression* each, Expression* subject, Statement* body) {
    IterationStatement::Initialize(body);
    each_ = each;
    subject_ = subject;
  }

  Expression* each() const { return each_; }
  Expression* subject() const { return subject_; }

  FeedbackVectorRequirements ComputeFeedbackRequirements(
      Isolate* isolate, const ICSlotCache* cache) override;
  void SetFirstFeedbackICSlot(FeedbackVectorICSlot slot,
                              ICSlotCache* cache) override {
    each_slot_ = slot;
  }
  Code::Kind FeedbackICSlotKind(int index) override;
  FeedbackVectorICSlot EachFeedbackSlot() const { return each_slot_; }

 protected:
  ForEachStatement(Zone* zone, ZoneList<const AstRawString*>* labels, int pos)
      : IterationStatement(zone, labels, pos),
        each_(NULL),
        subject_(NULL),
        each_slot_(FeedbackVectorICSlot::Invalid()) {}

 private:
  Expression* each_;
  Expression* subject_;
  FeedbackVectorICSlot each_slot_;
};


class ForInStatement final : public ForEachStatement {
 public:
  DECLARE_NODE_TYPE(ForInStatement)

  Expression* enumerable() const {
    return subject();
  }

  // Type feedback information.
  FeedbackVectorRequirements ComputeFeedbackRequirements(
      Isolate* isolate, const ICSlotCache* cache) override {
    FeedbackVectorRequirements base =
        ForEachStatement::ComputeFeedbackRequirements(isolate, cache);
    DCHECK(base.slots() == 0 && base.ic_slots() <= 1);
    return FeedbackVectorRequirements(1, base.ic_slots());
  }
  void SetFirstFeedbackSlot(FeedbackVectorSlot slot) override {
    for_in_feedback_slot_ = slot;
  }

  FeedbackVectorSlot ForInFeedbackSlot() {
    DCHECK(!for_in_feedback_slot_.IsInvalid());
    return for_in_feedback_slot_;
  }

  enum ForInType { FAST_FOR_IN, SLOW_FOR_IN };
  ForInType for_in_type() const { return for_in_type_; }
  void set_for_in_type(ForInType type) { for_in_type_ = type; }

  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 FilterId() const { return BailoutId(local_id(4)); }
  BailoutId AssignmentId() const { return BailoutId(local_id(5)); }
  BailoutId ContinueId() const override { return EntryId(); }
  BailoutId StackCheckId() const override { return BodyId(); }

 protected:
  ForInStatement(Zone* zone, ZoneList<const AstRawString*>* labels, int pos)
      : ForEachStatement(zone, labels, pos),
        for_in_type_(SLOW_FOR_IN),
        for_in_feedback_slot_(FeedbackVectorSlot::Invalid()) {}
  static int parent_num_ids() { return ForEachStatement::num_ids(); }

 private:
  int local_id(int n) const { return base_id() + parent_num_ids() + n; }

  ForInType for_in_type_;
  FeedbackVectorSlot for_in_feedback_slot_;
};


class ForOfStatement final : public ForEachStatement {
 public:
  DECLARE_NODE_TYPE(ForOfStatement)

  void Initialize(Expression* each,
                  Expression* subject,
                  Statement* body,
                  Expression* assign_iterator,
                  Expression* next_result,
                  Expression* result_done,
                  Expression* assign_each) {
    ForEachStatement::Initialize(each, subject, body);
    assign_iterator_ = assign_iterator;
    next_result_ = next_result;
    result_done_ = result_done;
    assign_each_ = assign_each;
  }

  Expression* iterable() const {
    return subject();
  }

  // iterator = subject[Symbol.iterator]()
  Expression* assign_iterator() const {
    return assign_iterator_;
  }

  // result = iterator.next()  // with type check
  Expression* next_result() const {
    return next_result_;
  }

  // result.done
  Expression* result_done() const {
    return result_done_;
  }

  // each = result.value
  Expression* assign_each() const {
    return assign_each_;
  }

  BailoutId ContinueId() const override { return EntryId(); }
  BailoutId StackCheckId() const override { return BackEdgeId(); }

  static int num_ids() { return parent_num_ids() + 1; }
  BailoutId BackEdgeId() const { return BailoutId(local_id(0)); }

 protected:
  ForOfStatement(Zone* zone, ZoneList<const AstRawString*>* labels, int pos)
      : ForEachStatement(zone, labels, pos),
        assign_iterator_(NULL),
        next_result_(NULL),
        result_done_(NULL),
        assign_each_(NULL) {}
  static int parent_num_ids() { return ForEachStatement::num_ids(); }

 private:
  int local_id(int n) const { return base_id() + parent_num_ids() + n; }

  Expression* assign_iterator_;
  Expression* next_result_;
  Expression* result_done_;
  Expression* assign_each_;
};


class ExpressionStatement final : public Statement {
 public:
  DECLARE_NODE_TYPE(ExpressionStatement)

  void set_expression(Expression* e) { expression_ = e; }
  Expression* expression() const { return expression_; }
  bool IsJump() const override { return expression_->IsThrow(); }

 protected:
  ExpressionStatement(Zone* zone, Expression* expression, int pos)
      : Statement(zone, pos), expression_(expression) { }

 private:
  Expression* expression_;
};


class JumpStatement : public Statement {
 public:
  bool IsJump() const final { return true; }

 protected:
  explicit JumpStatement(Zone* zone, int pos) : Statement(zone, pos) {}
};


class ContinueStatement final : public JumpStatement {
 public:
  DECLARE_NODE_TYPE(ContinueStatement)

  IterationStatement* target() const { return target_; }

 protected:
  explicit ContinueStatement(Zone* zone, IterationStatement* target, int pos)
      : JumpStatement(zone, pos), target_(target) { }

 private:
  IterationStatement* target_;
};


class BreakStatement final : public JumpStatement {
 public:
  DECLARE_NODE_TYPE(BreakStatement)

  BreakableStatement* target() const { return target_; }

 protected:
  explicit BreakStatement(Zone* zone, BreakableStatement* target, int pos)
      : JumpStatement(zone, pos), target_(target) { }

 private:
  BreakableStatement* target_;
};


class ReturnStatement final : public JumpStatement {
 public:
  DECLARE_NODE_TYPE(ReturnStatement)

  Expression* expression() const { return expression_; }

 protected:
  explicit ReturnStatement(Zone* zone, Expression* expression, int pos)
      : JumpStatement(zone, pos), expression_(expression) { }

 private:
  Expression* expression_;
};


class WithStatement final : public Statement {
 public:
  DECLARE_NODE_TYPE(WithStatement)

  Scope* scope() { return scope_; }
  Expression* expression() const { return expression_; }
  Statement* statement() const { return statement_; }

  void set_base_id(int id) { base_id_ = id; }
  static int num_ids() { return parent_num_ids() + 1; }
  BailoutId EntryId() const { return BailoutId(local_id(0)); }

 protected:
  WithStatement(Zone* zone, Scope* scope, Expression* expression,
                Statement* statement, int pos)
      : Statement(zone, pos),
        scope_(scope),
        expression_(expression),
        statement_(statement),
        base_id_(BailoutId::None().ToInt()) {}
  static int parent_num_ids() { return 0; }

  int base_id() const {
    DCHECK(!BailoutId(base_id_).IsNone());
    return base_id_;
  }

 private:
  int local_id(int n) const { return base_id() + parent_num_ids() + n; }

  Scope* scope_;
  Expression* expression_;
  Statement* statement_;
  int base_id_;
};


class CaseClause final : public Expression {
 public:
  DECLARE_NODE_TYPE(CaseClause)

  bool is_default() const { return label_ == NULL; }
  Expression* label() const {
    CHECK(!is_default());
    return label_;
  }
  Label* body_target() { return &body_target_; }
  ZoneList<Statement*>* statements() const { return statements_; }

  static int num_ids() { return parent_num_ids() + 2; }
  BailoutId EntryId() const { return BailoutId(local_id(0)); }
  TypeFeedbackId CompareId() { return TypeFeedbackId(local_id(1)); }

  Type* compare_type() { return compare_type_; }
  void set_compare_type(Type* type) { compare_type_ = type; }

 protected:
  static int parent_num_ids() { return Expression::num_ids(); }

 private:
  CaseClause(Zone* zone, Expression* label, ZoneList<Statement*>* statements,
             int pos);
  int local_id(int n) const { return base_id() + parent_num_ids() + n; }

  Expression* label_;
  Label body_target_;
  ZoneList<Statement*>* statements_;
  Type* compare_type_;
};


class SwitchStatement final : public BreakableStatement {
 public:
  DECLARE_NODE_TYPE(SwitchStatement)

  void Initialize(Expression* tag, ZoneList<CaseClause*>* cases) {
    tag_ = tag;
    cases_ = cases;
  }

  Expression* tag() const { return tag_; }
  ZoneList<CaseClause*>* cases() const { return cases_; }

 protected:
  SwitchStatement(Zone* zone, ZoneList<const AstRawString*>* labels, int pos)
      : BreakableStatement(zone, labels, TARGET_FOR_ANONYMOUS, pos),
        tag_(NULL),
        cases_(NULL) {}

 private:
  Expression* tag_;
  ZoneList<CaseClause*>* cases_;
};


// If-statements always have non-null references to their then- and
// else-parts. When parsing if-statements with no explicit else-part,
// the parser implicitly creates an empty statement. Use the
// HasThenStatement() and HasElseStatement() functions to check if a
// given if-statement has a then- or an else-part containing code.
class IfStatement final : public Statement {
 public:
  DECLARE_NODE_TYPE(IfStatement)

  bool HasThenStatement() const { return !then_statement()->IsEmpty(); }
  bool HasElseStatement() const { return !else_statement()->IsEmpty(); }

  Expression* condition() const { return condition_; }
  Statement* then_statement() const { return then_statement_; }
  Statement* else_statement() const { return else_statement_; }

  bool IsJump() const override {
    return HasThenStatement() && then_statement()->IsJump()
        && HasElseStatement() && else_statement()->IsJump();
  }

  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)); }
  BailoutId ThenId() const { return BailoutId(local_id(1)); }
  BailoutId ElseId() const { return BailoutId(local_id(2)); }

 protected:
  IfStatement(Zone* zone, Expression* condition, Statement* then_statement,
              Statement* else_statement, int pos)
      : Statement(zone, pos),
        condition_(condition),
        then_statement_(then_statement),
        else_statement_(else_statement),
        base_id_(BailoutId::None().ToInt()) {}
  static int parent_num_ids() { return 0; }

  int base_id() const {
    DCHECK(!BailoutId(base_id_).IsNone());
    return base_id_;
  }

 private:
  int local_id(int n) const { return base_id() + parent_num_ids() + n; }

  Expression* condition_;
  Statement* then_statement_;
  Statement* else_statement_;
  int base_id_;
};


class TryStatement : public Statement {
 public:
  Block* try_block() const { return try_block_; }

  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_;
  }

 private:
  int local_id(int n) const { return base_id() + parent_num_ids() + n; }

  Block* try_block_;
  int base_id_;
};


class TryCatchStatement final : public TryStatement {
 public:
  DECLARE_NODE_TYPE(TryCatchStatement)

  Scope* scope() { return scope_; }
  Variable* variable() { return variable_; }
  Block* catch_block() const { return catch_block_; }

 protected:
  TryCatchStatement(Zone* zone, Block* try_block, Scope* scope,
                    Variable* variable, Block* catch_block, int pos)
      : TryStatement(zone, try_block, pos),
        scope_(scope),
        variable_(variable),
        catch_block_(catch_block) {}

 private:
  Scope* scope_;
  Variable* variable_;
  Block* catch_block_;
};


class TryFinallyStatement final : public TryStatement {
 public:
  DECLARE_NODE_TYPE(TryFinallyStatement)

  Block* finally_block() const { return finally_block_; }

 protected:
  TryFinallyStatement(Zone* zone, Block* try_block, Block* finally_block,
                      int pos)
      : TryStatement(zone, try_block, pos), finally_block_(finally_block) {}

 private:
  Block* finally_block_;
};


class DebuggerStatement final : public Statement {
 public:
  DECLARE_NODE_TYPE(DebuggerStatement)

  void set_base_id(int id) { base_id_ = id; }
  static int num_ids() { return parent_num_ids() + 1; }
  BailoutId DebugBreakId() const { return BailoutId(local_id(0)); }

 protected:
  explicit DebuggerStatement(Zone* zone, int pos)
      : Statement(zone, pos), base_id_(BailoutId::None().ToInt()) {}
  static int parent_num_ids() { return 0; }

  int base_id() const {
    DCHECK(!BailoutId(base_id_).IsNone());
    return base_id_;
  }

 private:
  int local_id(int n) const { return base_id() + parent_num_ids() + n; }

  int base_id_;
};


class EmptyStatement final : public Statement {
 public:
  DECLARE_NODE_TYPE(EmptyStatement)

 protected:
  explicit EmptyStatement(Zone* zone, int pos): Statement(zone, pos) {}
};


class Literal final : public Expression {
 public:
  DECLARE_NODE_TYPE(Literal)

  bool IsPropertyName() const override { return value_->IsPropertyName(); }

  Handle<String> AsPropertyName() {
    DCHECK(IsPropertyName());
    return Handle<String>::cast(value());
  }

  const AstRawString* AsRawPropertyName() {
    DCHECK(IsPropertyName());
    return value_->AsString();
  }

  bool ToBooleanIsTrue() const override { return value()->BooleanValue(); }
  bool ToBooleanIsFalse() const override { return !value()->BooleanValue(); }

  Handle<Object> value() const { return value_->value(); }
  const AstValue* raw_value() const { return value_; }

  // Support for using Literal as a HashMap key. NOTE: Currently, this works
  // only for string and number literals!
  uint32_t Hash();
  static bool Match(void* literal1, void* literal2);

  static int num_ids() { return parent_num_ids() + 1; }
  TypeFeedbackId LiteralFeedbackId() const {
    return TypeFeedbackId(local_id(0));
  }

 protected:
  Literal(Zone* zone, const AstValue* value, int position)
      : Expression(zone, position), value_(value) {}
  static int parent_num_ids() { return Expression::num_ids(); }

 private:
  int local_id(int n) const { return base_id() + parent_num_ids() + n; }

  const AstValue* value_;
};


class AstLiteralReindexer;

// Base class for literals that needs space in the corresponding JSFunction.
class MaterializedLiteral : public Expression {
 public:
  virtual MaterializedLiteral* AsMaterializedLiteral() { return this; }

  int literal_index() { return literal_index_; }

  int depth() const {
    // only callable after initialization.
    DCHECK(depth_ >= 1);
    return depth_;
  }

  bool is_strong() const { return is_strong_; }

 protected:
  MaterializedLiteral(Zone* zone, int literal_index, bool is_strong, int pos)
      : Expression(zone, pos),
        literal_index_(literal_index),
        is_simple_(false),
        is_strong_(is_strong),
        depth_(0) {}

  // A materialized literal is simple if the values consist of only
  // constants and simple object and array literals.
  bool is_simple() const { return is_simple_; }
  void set_is_simple(bool is_simple) { is_simple_ = is_simple; }
  friend class CompileTimeValue;

  void set_depth(int depth) {
    DCHECK(depth >= 1);
    depth_ = depth;
  }

  // Populate the constant properties/elements fixed array.
  void BuildConstants(Isolate* isolate);
  friend class ArrayLiteral;
  friend class ObjectLiteral;

  // If the expression is a literal, return the literal value;
  // if the expression is a materialized literal and is simple return a
  // compile time value as encoded by CompileTimeValue::GetValue().
  // Otherwise, return undefined literal as the placeholder
  // in the object literal boilerplate.
  Handle<Object> GetBoilerplateValue(Expression* expression, Isolate* isolate);

 private:
  int literal_index_;
  bool is_simple_;
  bool is_strong_;
  int depth_;

  friend class AstLiteralReindexer;
};


// Property is used for passing information
// about an object literal's properties from the parser
// to the code generator.
class ObjectLiteralProperty final : public ZoneObject {
 public:
  enum Kind {
    CONSTANT,              // Property with constant value (compile time).
    COMPUTED,              // Property with computed value (execution time).
    MATERIALIZED_LITERAL,  // Property value is a materialized literal.
    GETTER, SETTER,        // Property is an accessor function.
    PROTOTYPE              // Property is __proto__.
  };

  Expression* key() { return key_; }
  Expression* value() { return value_; }
  Kind kind() { return kind_; }

  // Type feedback information.
  bool IsMonomorphic() { return !receiver_type_.is_null(); }
  Handle<Map> GetReceiverType() { return receiver_type_; }

  bool IsCompileTimeValue();

  void set_emit_store(bool emit_store);
  bool emit_store();

  bool is_static() const { return is_static_; }
  bool is_computed_name() const { return is_computed_name_; }

  FeedbackVectorICSlot GetSlot(int offset = 0) const {
    if (ic_slot_or_count_ == FeedbackVectorICSlot::Invalid().ToInt()) {
      return FeedbackVectorICSlot::Invalid();
    }
    return FeedbackVectorICSlot(ic_slot_or_count_ + offset);
  }

  int ic_slot_count() const {
    if (ic_slot_or_count_ == FeedbackVectorICSlot::Invalid().ToInt()) {
      return 0;
    }
    return ic_slot_or_count_;
  }

  void set_receiver_type(Handle<Map> map) { receiver_type_ = map; }
  void set_ic_slot_count(int count) {
    // Should only be called once.
    if (count == 0) {
      ic_slot_or_count_ = FeedbackVectorICSlot::Invalid().ToInt();
    } else {
      ic_slot_or_count_ = count;
    }
  }

  int set_base_slot(int slot) {
    if (ic_slot_count() > 0) {
      int count = ic_slot_count();
      ic_slot_or_count_ = slot;
      return count;
    }
    return 0;
  }

 protected:
  friend class AstNodeFactory;

  ObjectLiteralProperty(Expression* key, Expression* value, Kind kind,
                        bool is_static, bool is_computed_name);
  ObjectLiteralProperty(AstValueFactory* ast_value_factory, Expression* key,
                        Expression* value, bool is_static,
                        bool is_computed_name);

 private:
  Expression* key_;
  Expression* value_;
  int ic_slot_or_count_;
  Kind kind_;
  bool emit_store_;
  bool is_static_;
  bool is_computed_name_;
  Handle<Map> receiver_type_;
};


// An object literal has a boilerplate object that is used
// for minimizing the work when constructing it at runtime.
class ObjectLiteral final : public MaterializedLiteral {
 public:
  typedef ObjectLiteralProperty Property;

  DECLARE_NODE_TYPE(ObjectLiteral)

  Handle<FixedArray> constant_properties() const {
    return constant_properties_;
  }
  int properties_count() const { return constant_properties_->length() / 2; }
  ZoneList<Property*>* properties() const { return properties_; }
  bool fast_elements() const { return fast_elements_; }
  bool may_store_doubles() const { return may_store_doubles_; }
  bool has_function() const { return has_function_; }
  bool has_elements() const { return has_elements_; }

  // Decide if a property should be in the object boilerplate.
  static bool IsBoilerplateProperty(Property* property);

  // Populate the constant properties fixed array.
  void BuildConstantProperties(Isolate* isolate);

  // Mark all computed expressions that are bound to a key that
  // is shadowed by a later occurrence of the same key. For the
  // marked expressions, no store code is emitted.
  void CalculateEmitStore(Zone* zone);

  // Assemble bitfield of flags for the CreateObjectLiteral helper.
  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()) {
      flags |= kShallowProperties;
    }
    if (disable_mementos) {
      flags |= kDisableMementos;
    }
    if (is_strong()) {
      flags |= kIsStrong;
    }
    return flags;
  }

  enum Flags {
    kNoFlags = 0,
    kFastElements = 1,
    kHasFunction = 1 << 1,
    kShallowProperties = 1 << 2,
    kDisableMementos = 1 << 3,
    kIsStrong = 1 << 4
  };

  struct Accessors: public ZoneObject {
    Accessors() : getter(NULL), setter(NULL) {}
    ObjectLiteralProperty* getter;
    ObjectLiteralProperty* setter;
  };

  BailoutId CreateLiteralId() const { return BailoutId(local_id(0)); }

  // Return an AST id for a property that is used in simulate instructions.
  BailoutId GetIdForProperty(int i) { return BailoutId(local_id(i + 1)); }

  // Unlike other AST nodes, this number of bailout IDs allocated for an
  // ObjectLiteral can vary, so num_ids() is not a static method.
  int num_ids() const { return parent_num_ids() + 1 + properties()->length(); }

  // Object literals need one feedback slot for each non-trivial value, as well
  // as some slots for home objects.
  FeedbackVectorRequirements ComputeFeedbackRequirements(
      Isolate* isolate, const ICSlotCache* cache) override;
  void SetFirstFeedbackICSlot(FeedbackVectorICSlot slot,
                              ICSlotCache* cache) override {
    slot_ = slot;
  }
  Code::Kind FeedbackICSlotKind(int index) override { return Code::STORE_IC; }

  // After feedback slots were assigned, propagate information to the properties
  // which need it.
  void LayoutFeedbackSlots();

 protected:
  ObjectLiteral(Zone* zone, ZoneList<Property*>* properties, int literal_index,
                int boilerplate_properties, bool has_function, bool is_strong,
                int pos)
      : MaterializedLiteral(zone, literal_index, is_strong, pos),
        properties_(properties),
        boilerplate_properties_(boilerplate_properties),
        fast_elements_(false),
        has_elements_(false),
        may_store_doubles_(false),
        has_function_(has_function),
        slot_(FeedbackVectorICSlot::Invalid()) {
  }
  static int parent_num_ids() { return MaterializedLiteral::num_ids(); }

 private:
  int local_id(int n) const { return base_id() + parent_num_ids() + n; }
  Handle<FixedArray> constant_properties_;
  ZoneList<Property*>* properties_;
  int boilerplate_properties_;
  bool fast_elements_;
  bool has_elements_;
  bool may_store_doubles_;
  bool has_function_;
  FeedbackVectorICSlot slot_;
};


// Node for capturing a regexp literal.
class RegExpLiteral final : public MaterializedLiteral {
 public:
  DECLARE_NODE_TYPE(RegExpLiteral)

  Handle<String> pattern() const { return pattern_->string(); }
  Handle<String> flags() const { return flags_->string(); }

 protected:
  RegExpLiteral(Zone* zone, const AstRawString* pattern,
                const AstRawString* flags, int literal_index, bool is_strong,
                int pos)
      : MaterializedLiteral(zone, literal_index, is_strong, pos),
        pattern_(pattern),
        flags_(flags) {
    set_depth(1);
  }

 private:
  const AstRawString* pattern_;
  const AstRawString* flags_;
};


// An array literal has a literals object that is used
// for minimizing the work when constructing it at runtime.
class ArrayLiteral final : public MaterializedLiteral {
 public:
  DECLARE_NODE_TYPE(ArrayLiteral)

  Handle<FixedArray> constant_elements() const { return constant_elements_; }
  ElementsKind constant_elements_kind() const {
    DCHECK_EQ(2, constant_elements_->length());
    return static_cast<ElementsKind>(
        Smi::cast(constant_elements_->get(0))->value());
  }

  ZoneList<Expression*>* values() const { return values_; }

  BailoutId CreateLiteralId() const { return BailoutId(local_id(0)); }

  // Return an AST id for an element that is used in simulate instructions.
  BailoutId GetIdForElement(int i) { return BailoutId(local_id(i + 1)); }

  // Unlike other AST nodes, this number of bailout IDs allocated for an
  // ArrayLiteral can vary, so num_ids() is not a static method.
  int num_ids() const { return parent_num_ids() + 1 + values()->length(); }

  // Populate the constant elements fixed array.
  void BuildConstantElements(Isolate* isolate);

  // Assemble bitfield of flags for the CreateArrayLiteral helper.
  int ComputeFlags(bool disable_mementos = false) const {
    int flags = depth() == 1 ? kShallowElements : kNoFlags;
    if (disable_mementos) {
      flags |= kDisableMementos;
    }
    if (is_strong()) {
      flags |= kIsStrong;
    }
    return flags;
  }

  enum Flags {
    kNoFlags = 0,
    kShallowElements = 1,
    kDisableMementos = 1 << 1,
    kIsStrong = 1 << 2
  };

 protected:
  ArrayLiteral(Zone* zone, ZoneList<Expression*>* values,
               int first_spread_index, int literal_index, bool is_strong,
               int pos)
      : MaterializedLiteral(zone, literal_index, is_strong, pos),
        values_(values),
        first_spread_index_(first_spread_index) {}
  static int parent_num_ids() { return MaterializedLiteral::num_ids(); }

 private:
  int local_id(int n) const { return base_id() + parent_num_ids() + n; }

  Handle<FixedArray> constant_elements_;
  ZoneList<Expression*>* values_;
  int first_spread_index_;
};


class VariableProxy final : public Expression {
 public:
  DECLARE_NODE_TYPE(VariableProxy)

  bool IsValidReferenceExpression() const override {
    return !is_this() && !is_new_target();
  }

  bool IsArguments() const { return is_resolved() && var()->is_arguments(); }

  Handle<String> name() const { return raw_name()->string(); }
  const AstRawString* raw_name() const {
    return is_resolved() ? var_->raw_name() : raw_name_;
  }

  Variable* var() const {
    DCHECK(is_resolved());
    return var_;
  }
  void set_var(Variable* v) {
    DCHECK(!is_resolved());
    DCHECK_NOT_NULL(v);
    var_ = v;
  }

  bool is_this() const { return IsThisField::decode(bit_field_); }

  bool is_assigned() const { return IsAssignedField::decode(bit_field_); }
  void set_is_assigned() {
    bit_field_ = IsAssignedField::update(bit_field_, true);
  }

  bool is_resolved() const { return IsResolvedField::decode(bit_field_); }
  void set_is_resolved() {
    bit_field_ = IsResolvedField::update(bit_field_, true);
  }

  bool is_new_target() const { return IsNewTargetField::decode(bit_field_); }
  void set_is_new_target() {
    bit_field_ = IsNewTargetField::update(bit_field_, true);
  }

  int end_position() const { return end_position_; }

  // Bind this proxy to the variable var.
  void BindTo(Variable* var);

  bool UsesVariableFeedbackSlot() const {
    return var()->IsUnallocated() || var()->IsLookupSlot();
  }

  virtual FeedbackVectorRequirements ComputeFeedbackRequirements(
      Isolate* isolate, const ICSlotCache* cache) override;

  void SetFirstFeedbackICSlot(FeedbackVectorICSlot slot,
                              ICSlotCache* cache) override;
  Code::Kind FeedbackICSlotKind(int index) override { return Code::LOAD_IC; }
  FeedbackVectorICSlot VariableFeedbackSlot() {
    return variable_feedback_slot_;
  }

  static int num_ids() { return parent_num_ids() + 1; }
  BailoutId BeforeId() const { return BailoutId(local_id(0)); }

 protected:
  VariableProxy(Zone* zone, Variable* var, int start_position,
                int end_position);

  VariableProxy(Zone* zone, const AstRawString* name,
                Variable::Kind variable_kind, int start_position,
                int end_position);
  static int parent_num_ids() { return Expression::num_ids(); }
  int local_id(int n) const { return base_id() + parent_num_ids() + n; }

  class IsThisField : public BitField8<bool, 0, 1> {};
  class IsAssignedField : public BitField8<bool, 1, 1> {};
  class IsResolvedField : public BitField8<bool, 2, 1> {};
  class IsNewTargetField : public BitField8<bool, 3, 1> {};

  // Start with 16-bit (or smaller) field, which should get packed together
  // with Expression's trailing 16-bit field.
  uint8_t bit_field_;
  FeedbackVectorICSlot variable_feedback_slot_;
  union {
    const AstRawString* raw_name_;  // if !is_resolved_
    Variable* var_;                 // if is_resolved_
  };
  // Position is stored in the AstNode superclass, but VariableProxy needs to
  // know its end position too (for error messages). It cannot be inferred from
  // the variable name length because it can contain escapes.
  int end_position_;
};


// Left-hand side can only be a property, a global or a (parameter or local)
// slot.
enum LhsKind {
  VARIABLE,
  NAMED_PROPERTY,
  KEYED_PROPERTY,
  NAMED_SUPER_PROPERTY,
  KEYED_SUPER_PROPERTY
};


class Property final : public Expression {
 public:
  DECLARE_NODE_TYPE(Property)

  bool IsValidReferenceExpression() const override { return true; }

  Expression* obj() const { return obj_; }
  Expression* key() const { return key_; }

  static int num_ids() { return parent_num_ids() + 1; }
  BailoutId LoadId() const { return BailoutId(local_id(0)); }

  bool IsStringAccess() const {
    return IsStringAccessField::decode(bit_field_);
  }

  // Type feedback information.
  bool IsMonomorphic() override { return receiver_types_.length() == 1; }
  SmallMapList* GetReceiverTypes() override { return &receiver_types_; }
  KeyedAccessStoreMode GetStoreMode() const override { return STANDARD_STORE; }
  IcCheckType GetKeyType() const override {
    return KeyTypeField::decode(bit_field_);
  }
  bool IsUninitialized() const {
    return !is_for_call() && HasNoTypeInformation();
  }
  bool HasNoTypeInformation() const {
    return GetInlineCacheState() == UNINITIALIZED;
  }
  InlineCacheState GetInlineCacheState() const {
    return InlineCacheStateField::decode(bit_field_);
  }
  void set_is_string_access(bool b) {
    bit_field_ = IsStringAccessField::update(bit_field_, b);
  }
  void set_key_type(IcCheckType key_type) {
    bit_field_ = KeyTypeField::update(bit_field_, key_type);
  }
  void set_inline_cache_state(InlineCacheState state) {
    bit_field_ = InlineCacheStateField::update(bit_field_, state);
  }
  void mark_for_call() {
    bit_field_ = IsForCallField::update(bit_field_, true);
  }
  bool is_for_call() const { return IsForCallField::decode(bit_field_); }

  bool IsSuperAccess() { return obj()->IsSuperPropertyReference(); }

  virtual FeedbackVectorRequirements ComputeFeedbackRequirements(
      Isolate* isolate, const ICSlotCache* cache) override {
    return FeedbackVectorRequirements(0, 1);
  }
  void SetFirstFeedbackICSlot(FeedbackVectorICSlot slot,
                              ICSlotCache* cache) override {
    property_feedback_slot_ = slot;
  }
  Code::Kind FeedbackICSlotKind(int index) override {
    return key()->IsPropertyName() ? Code::LOAD_IC : Code::KEYED_LOAD_IC;
  }

  FeedbackVectorICSlot PropertyFeedbackSlot() const {
    return property_feedback_slot_;
  }

  static LhsKind GetAssignType(Property* property) {
    if (property == NULL) return VARIABLE;
    bool super_access = property->IsSuperAccess();
    return (property->key()->IsPropertyName())
               ? (super_access ? NAMED_SUPER_PROPERTY : NAMED_PROPERTY)
               : (super_access ? KEYED_SUPER_PROPERTY : KEYED_PROPERTY);
  }

 protected:
  Property(Zone* zone, Expression* obj, Expression* key, int pos)
      : Expression(zone, pos),
        bit_field_(IsForCallField::encode(false) |
                   IsStringAccessField::encode(false) |
                   InlineCacheStateField::encode(UNINITIALIZED)),
        property_feedback_slot_(FeedbackVectorICSlot::Invalid()),
        obj_(obj),
        key_(key) {}
  static int parent_num_ids() { return Expression::num_ids(); }

 private:
  int local_id(int n) const { return base_id() + parent_num_ids() + n; }

  class IsForCallField : public BitField8<bool, 0, 1> {};
  class IsStringAccessField : public BitField8<bool, 1, 1> {};
  class KeyTypeField : public BitField8<IcCheckType, 2, 1> {};
  class InlineCacheStateField : public BitField8<InlineCacheState, 3, 4> {};
  uint8_t bit_field_;
  FeedbackVectorICSlot property_feedback_slot_;
  Expression* obj_;
  Expression* key_;
  SmallMapList receiver_types_;
};


class Call final : public Expression {
 public:
  DECLARE_NODE_TYPE(Call)

  Expression* expression() const { return expression_; }
  ZoneList<Expression*>* arguments() const { return arguments_; }

  // Type feedback information.
  virtual FeedbackVectorRequirements ComputeFeedbackRequirements(
      Isolate* isolate, const ICSlotCache* cache) override;
  void SetFirstFeedbackICSlot(FeedbackVectorICSlot slot,
                              ICSlotCache* cache) override {
    ic_slot_ = slot;
  }
  void SetFirstFeedbackSlot(FeedbackVectorSlot slot) override { slot_ = slot; }
  Code::Kind FeedbackICSlotKind(int index) override { return Code::CALL_IC; }

  FeedbackVectorSlot CallFeedbackSlot() const { return slot_; }

  FeedbackVectorICSlot CallFeedbackICSlot() const { return ic_slot_; }

  SmallMapList* GetReceiverTypes() override {
    if (expression()->IsProperty()) {
      return expression()->AsProperty()->GetReceiverTypes();
    }
    return NULL;
  }

  bool IsMonomorphic() override {
    if (expression()->IsProperty()) {
      return expression()->AsProperty()->IsMonomorphic();
    }
    return !target_.is_null();
  }

  bool global_call() const {
    VariableProxy* proxy = expression_->AsVariableProxy();
    return proxy != NULL && proxy->var()->IsUnallocatedOrGlobalSlot();
  }

  bool known_global_function() const {
    return global_call() && !target_.is_null();
  }

  Handle<JSFunction> target() { return target_; }

  Handle<AllocationSite> allocation_site() { return allocation_site_; }

  void SetKnownGlobalTarget(Handle<JSFunction> target) {
    target_ = target;
    set_is_uninitialized(false);
  }
  void set_target(Handle<JSFunction> target) { target_ = target; }
  void set_allocation_site(Handle<AllocationSite> site) {
    allocation_site_ = site;
  }

  static int num_ids() { return parent_num_ids() + 3; }
  BailoutId ReturnId() const { return BailoutId(local_id(0)); }
  BailoutId EvalId() const { return BailoutId(local_id(1)); }
  BailoutId LookupId() const { return BailoutId(local_id(2)); }

  bool is_uninitialized() const {
    return IsUninitializedField::decode(bit_field_);
  }
  void set_is_uninitialized(bool b) {
    bit_field_ = IsUninitializedField::update(bit_field_, b);
  }

  enum CallType {
    POSSIBLY_EVAL_CALL,
    GLOBAL_CALL,
    LOOKUP_SLOT_CALL,
    PROPERTY_CALL,
    SUPER_CALL,
    OTHER_CALL
  };

  // Helpers to determine how to handle the call.
  CallType GetCallType(Isolate* isolate) const;
  bool IsUsingCallFeedbackSlot(Isolate* isolate) const;
  bool IsUsingCallFeedbackICSlot(Isolate* isolate) const;

#ifdef DEBUG
  // Used to assert that the FullCodeGenerator records the return site.
  bool return_is_recorded_;
#endif

 protected:
  Call(Zone* zone, Expression* expression, ZoneList<Expression*>* arguments,
       int pos)
      : Expression(zone, pos),
        ic_slot_(FeedbackVectorICSlot::Invalid()),
        slot_(FeedbackVectorSlot::Invalid()),
        expression_(expression),
        arguments_(arguments),
        bit_field_(IsUninitializedField::encode(false)) {
    if (expression->IsProperty()) {
      expression->AsProperty()->mark_for_call();
    }
  }
  static int parent_num_ids() { return Expression::num_ids(); }

 private:
  int local_id(int n) const { return base_id() + parent_num_ids() + n; }

  FeedbackVectorICSlot ic_slot_;
  FeedbackVectorSlot slot_;
  Expression* expression_;
  ZoneList<Expression*>* arguments_;
  Handle<JSFunction> target_;
  Handle<AllocationSite> allocation_site_;
  class IsUninitializedField : public BitField8<bool, 0, 1> {};
  uint8_t bit_field_;
};


class CallNew final : public Expression {
 public:
  DECLARE_NODE_TYPE(CallNew)

  Expression* expression() const { return expression_; }
  ZoneList<Expression*>* arguments() const { return arguments_; }

  // Type feedback information.
  virtual FeedbackVectorRequirements ComputeFeedbackRequirements(
      Isolate* isolate, const ICSlotCache* cache) override {
    return FeedbackVectorRequirements(1, 0);
  }
  void SetFirstFeedbackSlot(FeedbackVectorSlot slot) override {
    callnew_feedback_slot_ = slot;
  }

  FeedbackVectorSlot CallNewFeedbackSlot() {
    DCHECK(!callnew_feedback_slot_.IsInvalid());
    return callnew_feedback_slot_;
  }

  bool IsMonomorphic() override { return is_monomorphic_; }
  Handle<JSFunction> target() const { return target_; }
  Handle<AllocationSite> allocation_site() const {
    return allocation_site_;
  }

  static int num_ids() { return parent_num_ids() + 1; }
  static int feedback_slots() { return 1; }
  BailoutId ReturnId() const { return BailoutId(local_id(0)); }

  void set_allocation_site(Handle<AllocationSite> site) {
    allocation_site_ = site;
  }
  void set_is_monomorphic(bool monomorphic) { is_monomorphic_ = monomorphic; }
  void set_target(Handle<JSFunction> target) { target_ = target; }
  void SetKnownGlobalTarget(Handle<JSFunction> target) {
    target_ = target;
    is_monomorphic_ = true;
  }

 protected:
  CallNew(Zone* zone, Expression* expression, ZoneList<Expression*>* arguments,
          int pos)
      : Expression(zone, pos),
        expression_(expression),
        arguments_(arguments),
        is_monomorphic_(false),
        callnew_feedback_slot_(FeedbackVectorSlot::Invalid()) {}

  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_;
  ZoneList<Expression*>* arguments_;
  bool is_monomorphic_;
  Handle<JSFunction> target_;
  Handle<AllocationSite> allocation_site_;
  FeedbackVectorSlot callnew_feedback_slot_;
};


// The CallRuntime class does not represent any official JavaScript
// language construct. Instead it is used to call a C or JS function
// with a set of arguments. This is used from the builtins that are
// implemented in JavaScript (see "v8natives.js").
class CallRuntime final : public Expression {
 public:
  DECLARE_NODE_TYPE(CallRuntime)

  ZoneList<Expression*>* arguments() const { return arguments_; }
  bool is_jsruntime() const { return function_ == NULL; }

  int context_index() const {
    DCHECK(is_jsruntime());
    return context_index_;
  }
  const Runtime::Function* function() const {
    DCHECK(!is_jsruntime());
    return function_;
  }

  static int num_ids() { return parent_num_ids() + 1; }
  BailoutId CallId() { return BailoutId(local_id(0)); }

  const char* debug_name() {
    return is_jsruntime() ? "(context function)" : function_->name;
  }

 protected:
  CallRuntime(Zone* zone, const Runtime::Function* function,
              ZoneList<Expression*>* arguments, int pos)
      : Expression(zone, pos), function_(function), arguments_(arguments) {}

  CallRuntime(Zone* zone, int context_index, ZoneList<Expression*>* arguments,
              int pos)
      : Expression(zone, pos),
        function_(NULL),
        context_index_(context_index),
        arguments_(arguments) {}

  static int parent_num_ids() { return Expression::num_ids(); }

 private:
  int local_id(int n) const { return base_id() + parent_num_ids() + n; }

  const Runtime::Function* function_;
  int context_index_;
  ZoneList<Expression*>* arguments_;
};


class UnaryOperation final : public Expression {
 public:
  DECLARE_NODE_TYPE(UnaryOperation)

  Token::Value op() const { return op_; }
  Expression* expression() const { return expression_; }

  // For unary not (Token::NOT), the AST ids where true and false will
  // actually be materialized, respectively.
  static int num_ids() { return parent_num_ids() + 2; }
  BailoutId MaterializeTrueId() const { return BailoutId(local_id(0)); }
  BailoutId MaterializeFalseId() const { return BailoutId(local_id(1)); }

  virtual void RecordToBooleanTypeFeedback(TypeFeedbackOracle* oracle) override;

 protected:
  UnaryOperation(Zone* zone, Token::Value op, Expression* expression, int pos)
      : Expression(zone, pos), op_(op), expression_(expression) {
    DCHECK(Token::IsUnaryOp(op));
  }
  static int parent_num_ids() { return Expression::num_ids(); }

 private:
  int local_id(int n) const { return base_id() + parent_num_ids() + n; }

  Token::Value op_;
  Expression* expression_;
};


class BinaryOperation final : public Expression {
 public:
  DECLARE_NODE_TYPE(BinaryOperation)

  Token::Value op() const { return static_cast<Token::Value>(op_); }
  Expression* left() const { return left_; }
  Expression* right() const { return right_; }
  Handle<AllocationSite> allocation_site() const { return allocation_site_; }
  void set_allocation_site(Handle<AllocationSite> allocation_site) {
    allocation_site_ = allocation_site;
  }

  // The short-circuit logical operations need an AST ID for their
  // right-hand subexpression.
  static int num_ids() { return parent_num_ids() + 2; }
  BailoutId RightId() const { return BailoutId(local_id(0)); }

  TypeFeedbackId BinaryOperationFeedbackId() const {
    return TypeFeedbackId(local_id(1));
  }
  Maybe<int> fixed_right_arg() const {
    return has_fixed_right_arg_ ? Just(fixed_right_arg_value_) : Nothing<int>();
  }
  void set_fixed_right_arg(Maybe<int> arg) {
    has_fixed_right_arg_ = arg.IsJust();
    if (arg.IsJust()) fixed_right_arg_value_ = arg.FromJust();
  }

  virtual void RecordToBooleanTypeFeedback(TypeFeedbackOracle* oracle) override;

 protected:
  BinaryOperation(Zone* zone, Token::Value op, Expression* left,
                  Expression* right, int pos)
      : Expression(zone, pos),
        op_(static_cast<byte>(op)),
        has_fixed_right_arg_(false),
        fixed_right_arg_value_(0),
        left_(left),
        right_(right) {
    DCHECK(Token::IsBinaryOp(op));
  }
  static int parent_num_ids() { return Expression::num_ids(); }

 private:
  int local_id(int n) const { return base_id() + parent_num_ids() + n; }

  const byte op_;  // actually Token::Value
  // TODO(rossberg): the fixed arg should probably be represented as a Constant
  // type for the RHS. Currenty it's actually a Maybe<int>
  bool has_fixed_right_arg_;
  int fixed_right_arg_value_;
  Expression* left_;
  Expression* right_;
  Handle<AllocationSite> allocation_site_;
};


class CountOperation final : public Expression {
 public:
  DECLARE_NODE_TYPE(CountOperation)

  bool is_prefix() const { return IsPrefixField::decode(bit_field_); }
  bool is_postfix() const { return !is_prefix(); }

  Token::Value op() const { return TokenField::decode(bit_field_); }
  Token::Value binary_op() {
    return (op() == Token::INC) ? Token::ADD : Token::SUB;
  }

  Expression* expression() const { return expression_; }

  bool IsMonomorphic() override { return receiver_types_.length() == 1; }
  SmallMapList* GetReceiverTypes() override { return &receiver_types_; }
  IcCheckType GetKeyType() const override {
    return KeyTypeField::decode(bit_field_);
  }
  KeyedAccessStoreMode GetStoreMode() const override {
    return StoreModeField::decode(bit_field_);
  }
  Type* type() const { return type_; }
  void set_key_type(IcCheckType type) {
    bit_field_ = KeyTypeField::update(bit_field_, type);
  }
  void set_store_mode(KeyedAccessStoreMode mode) {
    bit_field_ = StoreModeField::update(bit_field_, mode);
  }
  void set_type(Type* type) { type_ = type; }

  static int num_ids() { return parent_num_ids() + 4; }
  BailoutId AssignmentId() const { return BailoutId(local_id(0)); }
  BailoutId ToNumberId() const { return BailoutId(local_id(1)); }
  TypeFeedbackId CountBinOpFeedbackId() const {
    return TypeFeedbackId(local_id(2));
  }
  TypeFeedbackId CountStoreFeedbackId() const {
    return TypeFeedbackId(local_id(3));
  }

  FeedbackVectorRequirements ComputeFeedbackRequirements(
      Isolate* isolate, const ICSlotCache* cache) override;
  void SetFirstFeedbackICSlot(FeedbackVectorICSlot slot,
                              ICSlotCache* cache) override {
    slot_ = slot;
  }
  Code::Kind FeedbackICSlotKind(int index) override;
  FeedbackVectorICSlot CountSlot() const { return slot_; }

 protected:
  CountOperation(Zone* zone, Token::Value op, bool is_prefix, Expression* expr,
                 int pos)
      : Expression(zone, pos),
        bit_field_(
            IsPrefixField::encode(is_prefix) | KeyTypeField::encode(ELEMENT) |
            StoreModeField::encode(STANDARD_STORE) | TokenField::encode(op)),
        type_(NULL),
        expression_(expr),
        slot_(FeedbackVectorICSlot::Invalid()) {}
  static int parent_num_ids() { return Expression::num_ids(); }

 private:
  int local_id(int n) const { return base_id() + parent_num_ids() + n; }

  class IsPrefixField : public BitField16<bool, 0, 1> {};
  class KeyTypeField : public BitField16<IcCheckType, 1, 1> {};
  class StoreModeField : public BitField16<KeyedAccessStoreMode, 2, 3> {};
  class TokenField : public BitField16<Token::Value, 5, 8> {};

  // Starts with 16-bit field, which should get packed together with
  // Expression's trailing 16-bit field.
  uint16_t bit_field_;
  Type* type_;
  Expression* expression_;
  SmallMapList receiver_types_;
  FeedbackVectorICSlot slot_;
};


class CompareOperation final : public Expression {
 public:
  DECLARE_NODE_TYPE(CompareOperation)

  Token::Value op() const { return op_; }
  Expression* left() const { return left_; }
  Expression* right() const { return right_; }

  // Type feedback information.
  static int num_ids() { return parent_num_ids() + 1; }
  TypeFeedbackId CompareOperationFeedbackId() const {
    return TypeFeedbackId(local_id(0));
  }
  Type* combined_type() const { return combined_type_; }
  void set_combined_type(Type* type) { combined_type_ = type; }

  // Match special cases.
  bool IsLiteralCompareTypeof(Expression** expr, Handle<String>* check);
  bool IsLiteralCompareUndefined(Expression** expr, Isolate* isolate);
  bool IsLiteralCompareNull(Expression** expr);

 protected:
  CompareOperation(Zone* zone, Token::Value op, Expression* left,
                   Expression* right, int pos)
      : Expression(zone, pos),
        op_(op),
        left_(left),
        right_(right),
        combined_type_(Type::None(zone)) {
    DCHECK(Token::IsCompareOp(op));
  }
  static int parent_num_ids() { return Expression::num_ids(); }

 private:
  int local_id(int n) const { return base_id() + parent_num_ids() + n; }

  Token::Value op_;
  Expression* left_;
  Expression* right_;

  Type* combined_type_;
};


class Spread final : public Expression {
 public:
  DECLARE_NODE_TYPE(Spread)

  Expression* expression() const { return expression_; }

  static int num_ids() { return parent_num_ids(); }

 protected:
  Spread(Zone* zone, Expression* expression, int pos)
      : Expression(zone, pos), expression_(expression) {}
  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_;
};


class Conditional final : public Expression {
 public:
  DECLARE_NODE_TYPE(Conditional)

  Expression* condition() const { return condition_; }
  Expression* then_expression() const { return then_expression_; }
  Expression* else_expression() const { return else_expression_; }

  static int num_ids() { return parent_num_ids() + 2; }
  BailoutId ThenId() const { return BailoutId(local_id(0)); }
  BailoutId ElseId() const { return BailoutId(local_id(1)); }

 protected:
  Conditional(Zone* zone, Expression* condition, Expression* then_expression,
              Expression* else_expression, int position)
      : Expression(zone, position),
        condition_(condition),
        then_expression_(then_expression),
        else_expression_(else_expression) {}
  static int parent_num_ids() { return Expression::num_ids(); }

 private:
  int local_id(int n) const { return base_id() + parent_num_ids() + n; }

  Expression* condition_;
  Expression* then_expression_;
  Expression* else_expression_;
};


class Assignment final : public Expression {
 public:
  DECLARE_NODE_TYPE(Assignment)

  Assignment* AsSimpleAssignment() { return !is_compound() ? this : NULL; }

  Token::Value binary_op() const;

  Token::Value op() const { return TokenField::decode(bit_field_); }
  Expression* target() const { return target_; }
  Expression* value() const { return value_; }
  BinaryOperation* binary_operation() const { return binary_operation_; }

  // This check relies on the definition order of token in token.h.
  bool is_compound() const { return op() > Token::ASSIGN; }

  static int num_ids() { return parent_num_ids() + 2; }
  BailoutId AssignmentId() const { return BailoutId(local_id(0)); }

  // Type feedback information.
  TypeFeedbackId AssignmentFeedbackId() { return TypeFeedbackId(local_id(1)); }
  bool IsMonomorphic() override { return receiver_types_.length() == 1; }
  bool IsUninitialized() const {
    return IsUninitializedField::decode(bit_field_);
  }
  bool HasNoTypeInformation() {
    return IsUninitializedField::decode(bit_field_);
  }
  SmallMapList* GetReceiverTypes() override { return &receiver_types_; }
  IcCheckType GetKeyType() const override {
    return KeyTypeField::decode(bit_field_);
  }
  KeyedAccessStoreMode GetStoreMode() const override {
    return StoreModeField::decode(bit_field_);
  }
  void set_is_uninitialized(bool b) {
    bit_field_ = IsUninitializedField::update(bit_field_, b);
  }
  void set_key_type(IcCheckType key_type) {
    bit_field_ = KeyTypeField::update(bit_field_, key_type);
  }
  void set_store_mode(KeyedAccessStoreMode mode) {
    bit_field_ = StoreModeField::update(bit_field_, mode);
  }

  FeedbackVectorRequirements ComputeFeedbackRequirements(
      Isolate* isolate, const ICSlotCache* cache) override;
  void SetFirstFeedbackICSlot(FeedbackVectorICSlot slot,
                              ICSlotCache* cache) override {
    slot_ = slot;
  }
  Code::Kind FeedbackICSlotKind(int index) override;
  FeedbackVectorICSlot AssignmentSlot() const { return slot_; }

 protected:
  Assignment(Zone* zone, Token::Value op, Expression* target, Expression* value,
             int pos);
  static int parent_num_ids() { return Expression::num_ids(); }

 private:
  int local_id(int n) const { return base_id() + parent_num_ids() + n; }

  class IsUninitializedField : public BitField16<bool, 0, 1> {};
  class KeyTypeField : public BitField16<IcCheckType, 1, 1> {};
  class StoreModeField : public BitField16<KeyedAccessStoreMode, 2, 3> {};
  class TokenField : public BitField16<Token::Value, 5, 8> {};

  // Starts with 16-bit field, which should get packed together with
  // Expression's trailing 16-bit field.
  uint16_t bit_field_;
  Expression* target_;
  Expression* value_;
  BinaryOperation* binary_operation_;
  SmallMapList receiver_types_;
  FeedbackVectorICSlot slot_;
};


class Yield final : public Expression {
 public:
  DECLARE_NODE_TYPE(Yield)

  enum Kind {
    kInitial,  // The initial yield that returns the unboxed generator object.
    kSuspend,  // A normal yield: { value: EXPRESSION, done: false }
    kDelegating,  // A yield*.
    kFinal        // A return: { value: EXPRESSION, done: true }
  };

  Expression* generator_object() const { return generator_object_; }
  Expression* expression() const { return expression_; }
  Kind yield_kind() const { return yield_kind_; }

  // Type feedback information.
  bool HasFeedbackSlots() const { return yield_kind() == kDelegating; }
  virtual FeedbackVectorRequirements ComputeFeedbackRequirements(
      Isolate* isolate, const ICSlotCache* cache) override {
    return FeedbackVectorRequirements(0, HasFeedbackSlots() ? 3 : 0);
  }
  void SetFirstFeedbackICSlot(FeedbackVectorICSlot slot,
                              ICSlotCache* cache) override {
    yield_first_feedback_slot_ = slot;
  }
  Code::Kind FeedbackICSlotKind(int index) override {
    return index == 0 ? Code::KEYED_LOAD_IC : Code::LOAD_IC;
  }

  FeedbackVectorICSlot KeyedLoadFeedbackSlot() {
    DCHECK(!HasFeedbackSlots() || !yield_first_feedback_slot_.IsInvalid());
    return yield_first_feedback_slot_;
  }

  FeedbackVectorICSlot DoneFeedbackSlot() {
    return KeyedLoadFeedbackSlot().next();
  }

  FeedbackVectorICSlot ValueFeedbackSlot() { return DoneFeedbackSlot().next(); }

 protected:
  Yield(Zone* zone, Expression* generator_object, Expression* expression,
        Kind yield_kind, int pos)
      : Expression(zone, pos),
        generator_object_(generator_object),
        expression_(expression),
        yield_kind_(yield_kind),
        yield_first_feedback_slot_(FeedbackVectorICSlot::Invalid()) {}

 private:
  Expression* generator_object_;
  Expression* expression_;
  Kind yield_kind_;
  FeedbackVectorICSlot yield_first_feedback_slot_;
};


class Throw final : public Expression {
 public:
  DECLARE_NODE_TYPE(Throw)

  Expression* exception() const { return exception_; }

 protected:
  Throw(Zone* zone, Expression* exception, int pos)
      : Expression(zone, pos), exception_(exception) {}

 private:
  Expression* exception_;
};


class FunctionLiteral final : public Expression {
 public:
  enum FunctionType {
    ANONYMOUS_EXPRESSION,
    NAMED_EXPRESSION,
    DECLARATION
  };

  enum ParameterFlag {
    kNoDuplicateParameters = 0,
    kHasDuplicateParameters = 1
  };

  enum IsFunctionFlag {
    kGlobalOrEval,
    kIsFunction
  };

  enum EagerCompileHint { kShouldEagerCompile, kShouldLazyCompile };

  enum ShouldBeUsedOnceHint { kShouldBeUsedOnce, kDontKnowIfShouldBeUsedOnce };

  enum ArityRestriction {
    NORMAL_ARITY,
    GETTER_ARITY,
    SETTER_ARITY
  };

  DECLARE_NODE_TYPE(FunctionLiteral)

  Handle<String> name() const { return raw_name_->string(); }
  const AstRawString* raw_name() const { return raw_name_; }
  Scope* scope() const { return scope_; }
  ZoneList<Statement*>* body() const { return body_; }
  void set_function_token_position(int pos) { function_token_position_ = pos; }
  int function_token_position() const { return function_token_position_; }
  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_); }
  LanguageMode language_mode() const;

  static bool NeedsHomeObject(Expression* expr);

  int materialized_literal_count() { return materialized_literal_count_; }
  int expected_property_count() { return expected_property_count_; }
  int parameter_count() { return parameter_count_; }

  bool AllowsLazyCompilation();
  bool AllowsLazyCompilationWithoutContext();

  Handle<String> debug_name() const {
    if (raw_name_ != NULL && !raw_name_->IsEmpty()) {
      return raw_name_->string();
    }
    return inferred_name();
  }

  Handle<String> inferred_name() const {
    if (!inferred_name_.is_null()) {
      DCHECK(raw_inferred_name_ == NULL);
      return inferred_name_;
    }
    if (raw_inferred_name_ != NULL) {
      return raw_inferred_name_->string();
    }
    UNREACHABLE();
    return Handle<String>();
  }

  // Only one of {set_inferred_name, set_raw_inferred_name} should be called.
  void set_inferred_name(Handle<String> inferred_name) {
    DCHECK(!inferred_name.is_null());
    inferred_name_ = inferred_name;
    DCHECK(raw_inferred_name_== NULL || raw_inferred_name_->IsEmpty());
    raw_inferred_name_ = NULL;
  }

  void set_raw_inferred_name(const AstString* raw_inferred_name) {
    DCHECK(raw_inferred_name != NULL);
    raw_inferred_name_ = raw_inferred_name;
    DCHECK(inferred_name_.is_null());
    inferred_name_ = Handle<String>();
  }

  bool pretenure() { return Pretenure::decode(bitfield_); }
  void set_pretenure() { bitfield_ |= Pretenure::encode(true); }

  bool has_duplicate_parameters() {
    return HasDuplicateParameters::decode(bitfield_);
  }

  bool is_function() { return IsFunction::decode(bitfield_) == kIsFunction; }

  // This is used as a heuristic on when to eagerly compile a function
  // literal. We consider the following constructs as hints that the
  // function will be called immediately:
  // - (function() { ... })();
  // - var x = function() { ... }();
  bool should_eager_compile() const {
    return EagerCompileHintBit::decode(bitfield_) == kShouldEagerCompile;
  }
  void set_should_eager_compile() {
    bitfield_ = EagerCompileHintBit::update(bitfield_, kShouldEagerCompile);
  }

  // A hint that we expect this function to be called (exactly) once,
  // i.e. we suspect it's an initialization function.
  bool should_be_used_once_hint() const {
    return ShouldBeUsedOnceHintBit::decode(bitfield_) == kShouldBeUsedOnce;
  }
  void set_should_be_used_once_hint() {
    bitfield_ = ShouldBeUsedOnceHintBit::update(bitfield_, kShouldBeUsedOnce);
  }

  FunctionKind kind() const { return FunctionKindBits::decode(bitfield_); }

  int ast_node_count() { return ast_properties_.node_count(); }
  AstProperties::Flags flags() const { return ast_properties_.flags(); }
  void set_ast_properties(AstProperties* ast_properties) {
    ast_properties_ = *ast_properties;
  }
  const ZoneFeedbackVectorSpec* feedback_vector_spec() const {
    return ast_properties_.get_spec();
  }
  bool dont_optimize() { return dont_optimize_reason_ != kNoReason; }
  BailoutReason dont_optimize_reason() { return dont_optimize_reason_; }
  void set_dont_optimize_reason(BailoutReason reason) {
    dont_optimize_reason_ = reason;
  }

 protected:
  FunctionLiteral(Zone* zone, const AstRawString* name,
                  AstValueFactory* ast_value_factory, Scope* scope,
                  ZoneList<Statement*>* body, int materialized_literal_count,
                  int expected_property_count, int parameter_count,
                  FunctionType function_type,
                  ParameterFlag has_duplicate_parameters,
                  IsFunctionFlag is_function,
                  EagerCompileHint eager_compile_hint, FunctionKind kind,
                  int position)
      : Expression(zone, position),
        raw_name_(name),
        scope_(scope),
        body_(body),
        raw_inferred_name_(ast_value_factory->empty_string()),
        ast_properties_(zone),
        dont_optimize_reason_(kNoReason),
        materialized_literal_count_(materialized_literal_count),
        expected_property_count_(expected_property_count),
        parameter_count_(parameter_count),
        function_token_position_(RelocInfo::kNoPosition) {
    bitfield_ = IsExpression::encode(function_type != DECLARATION) |
                IsAnonymous::encode(function_type == ANONYMOUS_EXPRESSION) |
                Pretenure::encode(false) |
                HasDuplicateParameters::encode(has_duplicate_parameters) |
                IsFunction::encode(is_function) |
                EagerCompileHintBit::encode(eager_compile_hint) |
                FunctionKindBits::encode(kind) |
                ShouldBeUsedOnceHintBit::encode(kDontKnowIfShouldBeUsedOnce);
    DCHECK(IsValidFunctionKind(kind));
  }

 private:
  const AstRawString* raw_name_;
  Handle<String> name_;
  Scope* scope_;
  ZoneList<Statement*>* body_;
  const AstString* raw_inferred_name_;
  Handle<String> inferred_name_;
  AstProperties ast_properties_;
  BailoutReason dont_optimize_reason_;

  int materialized_literal_count_;
  int expected_property_count_;
  int parameter_count_;
  int function_token_position_;

  unsigned bitfield_;
  class IsExpression : public BitField<bool, 0, 1> {};
  class IsAnonymous : public BitField<bool, 1, 1> {};
  class Pretenure : public BitField<bool, 2, 1> {};
  class HasDuplicateParameters : public BitField<ParameterFlag, 3, 1> {};
  class IsFunction : public BitField<IsFunctionFlag, 4, 1> {};
  class EagerCompileHintBit : public BitField<EagerCompileHint, 5, 1> {};
  class FunctionKindBits : public BitField<FunctionKind, 6, 8> {};
  class ShouldBeUsedOnceHintBit : public BitField<ShouldBeUsedOnceHint, 15, 1> {
  };
};


class ClassLiteral final : public Expression {
 public:
  typedef ObjectLiteralProperty Property;

  DECLARE_NODE_TYPE(ClassLiteral)

  Handle<String> name() const { return raw_name_->string(); }
  const AstRawString* raw_name() const { return raw_name_; }
  Scope* scope() const { return scope_; }
  VariableProxy* class_variable_proxy() const { return class_variable_proxy_; }
  Expression* extends() const { return extends_; }
  FunctionLiteral* constructor() const { return constructor_; }
  ZoneList<Property*>* properties() const { return properties_; }
  int start_position() const { return position(); }
  int end_position() const { return end_position_; }

  BailoutId EntryId() const { return BailoutId(local_id(0)); }
  BailoutId DeclsId() const { return BailoutId(local_id(1)); }
  BailoutId ExitId() { return BailoutId(local_id(2)); }
  BailoutId CreateLiteralId() const { return BailoutId(local_id(3)); }

  // Return an AST id for a property that is used in simulate instructions.
  BailoutId GetIdForProperty(int i) { return BailoutId(local_id(i + 4)); }

  // 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(); }

  // Object literals need one feedback slot for each non-trivial value, as well
  // as some slots for home objects.
  FeedbackVectorRequirements ComputeFeedbackRequirements(
      Isolate* isolate, const ICSlotCache* cache) override;
  void SetFirstFeedbackICSlot(FeedbackVectorICSlot slot,
                              ICSlotCache* cache) override {
    slot_ = slot;
  }
  Code::Kind FeedbackICSlotKind(int index) override { return Code::STORE_IC; }

  bool NeedsProxySlot() const {
    return FLAG_vector_stores && scope() != NULL &&
           class_variable_proxy()->var()->IsUnallocated();
  }

  FeedbackVectorICSlot ProxySlot() const { return slot_; }

  // After feedback slots were assigned, propagate information to the properties
  // which need it.
  void LayoutFeedbackSlots();

 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)
      : Expression(zone, start_position),
        raw_name_(name),
        scope_(scope),
        class_variable_proxy_(class_variable_proxy),
        extends_(extends),
        constructor_(constructor),
        properties_(properties),
        end_position_(end_position),
        slot_(FeedbackVectorICSlot::Invalid()) {
  }

  static int parent_num_ids() { return Expression::num_ids(); }

 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_;
  FeedbackVectorICSlot slot_;
};


class NativeFunctionLiteral final : public Expression {
 public:
  DECLARE_NODE_TYPE(NativeFunctionLiteral)

  Handle<String> name() const { return name_->string(); }
  v8::Extension* extension() const { return extension_; }

 protected:
  NativeFunctionLiteral(Zone* zone, const AstRawString* name,
                        v8::Extension* extension, int pos)
      : Expression(zone, pos), name_(name), extension_(extension) {}

 private:
  const AstRawString* name_;
  v8::Extension* extension_;
};


class ThisFunction final : public Expression {
 public:
  DECLARE_NODE_TYPE(ThisFunction)

 protected:
  ThisFunction(Zone* zone, int pos) : Expression(zone, pos) {}
};


class SuperPropertyReference final : public Expression {
 public:
  DECLARE_NODE_TYPE(SuperPropertyReference)

  VariableProxy* this_var() const { return this_var_; }
  Expression* home_object() const { return home_object_; }

 protected:
  SuperPropertyReference(Zone* zone, VariableProxy* this_var,
                         Expression* home_object, int pos)
      : Expression(zone, pos), this_var_(this_var), home_object_(home_object) {
    DCHECK(this_var->is_this());
    DCHECK(home_object->IsProperty());
  }

 private:
  VariableProxy* this_var_;
  Expression* home_object_;
};


class SuperCallReference final : public Expression {
 public:
  DECLARE_NODE_TYPE(SuperCallReference)

  VariableProxy* this_var() const { return this_var_; }
  VariableProxy* new_target_var() const { return new_target_var_; }
  VariableProxy* this_function_var() const { return this_function_var_; }

 protected:
  SuperCallReference(Zone* zone, VariableProxy* this_var,
                     VariableProxy* new_target_var,
                     VariableProxy* this_function_var, int pos)
      : Expression(zone, pos),
        this_var_(this_var),
        new_target_var_(new_target_var),
        this_function_var_(this_function_var) {
    DCHECK(this_var->is_this());
    DCHECK(new_target_var->raw_name()->IsOneByteEqualTo(".new.target"));
    DCHECK(this_function_var->raw_name()->IsOneByteEqualTo(".this_function"));
  }

 private:
  VariableProxy* this_var_;
  VariableProxy* new_target_var_;
  VariableProxy* this_function_var_;
};


// This class is produced when parsing the () in arrow functions without any
// arguments and is not actually a valid expression.
class EmptyParentheses final : public Expression {
 public:
  DECLARE_NODE_TYPE(EmptyParentheses)

 private:
  EmptyParentheses(Zone* zone, int pos) : Expression(zone, pos) {}
};


#undef DECLARE_NODE_TYPE


// ----------------------------------------------------------------------------
// Regular expressions


class RegExpVisitor BASE_EMBEDDED {
 public:
  virtual ~RegExpVisitor() { }
#define MAKE_CASE(Name)                                              \
  virtual void* Visit##Name(RegExp##Name*, void* data) = 0;
  FOR_EACH_REG_EXP_TREE_TYPE(MAKE_CASE)
#undef MAKE_CASE
};


class RegExpTree : public ZoneObject {
 public:
  static const int kInfinity = kMaxInt;
  virtual ~RegExpTree() {}
  virtual void* Accept(RegExpVisitor* visitor, void* data) = 0;
  virtual RegExpNode* ToNode(RegExpCompiler* compiler,
                             RegExpNode* on_success) = 0;
  virtual bool IsTextElement() { return false; }
  virtual bool IsAnchoredAtStart() { return false; }
  virtual bool IsAnchoredAtEnd() { return false; }
  virtual int min_match() = 0;
  virtual int max_match() = 0;
  // Returns the interval of registers used for captures within this
  // expression.
  virtual Interval CaptureRegisters() { return Interval::Empty(); }
  virtual void AppendToText(RegExpText* text, Zone* zone);
  std::ostream& Print(std::ostream& os, Zone* zone);  // NOLINT
#define MAKE_ASTYPE(Name)                                                  \
  virtual RegExp##Name* As##Name();                                        \
  virtual bool Is##Name();
  FOR_EACH_REG_EXP_TREE_TYPE(MAKE_ASTYPE)
#undef MAKE_ASTYPE
};


class RegExpDisjunction final : public RegExpTree {
 public:
  explicit RegExpDisjunction(ZoneList<RegExpTree*>* alternatives);
  void* Accept(RegExpVisitor* visitor, void* data) override;
  virtual RegExpNode* ToNode(RegExpCompiler* compiler,
                             RegExpNode* on_success) override;
  RegExpDisjunction* AsDisjunction() override;
  Interval CaptureRegisters() override;
  bool IsDisjunction() override;
  bool IsAnchoredAtStart() override;
  bool IsAnchoredAtEnd() override;
  int min_match() override { return min_match_; }
  int max_match() override { return max_match_; }
  ZoneList<RegExpTree*>* alternatives() { return alternatives_; }
 private:
  bool SortConsecutiveAtoms(RegExpCompiler* compiler);
  void RationalizeConsecutiveAtoms(RegExpCompiler* compiler);
  void FixSingleCharacterDisjunctions(RegExpCompiler* compiler);
  ZoneList<RegExpTree*>* alternatives_;
  int min_match_;
  int max_match_;
};


class RegExpAlternative final : public RegExpTree {
 public:
  explicit RegExpAlternative(ZoneList<RegExpTree*>* nodes);
  void* Accept(RegExpVisitor* visitor, void* data) override;
  virtual RegExpNode* ToNode(RegExpCompiler* compiler,
                             RegExpNode* on_success) override;
  RegExpAlternative* AsAlternative() override;
  Interval CaptureRegisters() override;
  bool IsAlternative() override;
  bool IsAnchoredAtStart() override;
  bool IsAnchoredAtEnd() override;
  int min_match() override { return min_match_; }
  int max_match() override { return max_match_; }
  ZoneList<RegExpTree*>* nodes() { return nodes_; }
 private:
  ZoneList<RegExpTree*>* nodes_;
  int min_match_;
  int max_match_;
};


class RegExpAssertion final : public RegExpTree {
 public:
  enum AssertionType {
    START_OF_LINE,
    START_OF_INPUT,
    END_OF_LINE,
    END_OF_INPUT,
    BOUNDARY,
    NON_BOUNDARY
  };
  explicit RegExpAssertion(AssertionType type) : assertion_type_(type) { }
  void* Accept(RegExpVisitor* visitor, void* data) override;
  virtual RegExpNode* ToNode(RegExpCompiler* compiler,
                             RegExpNode* on_success) override;
  RegExpAssertion* AsAssertion() override;
  bool IsAssertion() override;
  bool IsAnchoredAtStart() override;
  bool IsAnchoredAtEnd() override;
  int min_match() override { return 0; }
  int max_match() override { return 0; }
  AssertionType assertion_type() { return assertion_type_; }
 private:
  AssertionType assertion_type_;
};


class CharacterSet final BASE_EMBEDDED {
 public:
  explicit CharacterSet(uc16 standard_set_type)
      : ranges_(NULL),
        standard_set_type_(standard_set_type) {}
  explicit CharacterSet(ZoneList<CharacterRange>* ranges)
      : ranges_(ranges),
        standard_set_type_(0) {}
  ZoneList<CharacterRange>* ranges(Zone* zone);
  uc16 standard_set_type() { return standard_set_type_; }
  void set_standard_set_type(uc16 special_set_type) {
    standard_set_type_ = special_set_type;
  }
  bool is_standard() { return standard_set_type_ != 0; }
  void Canonicalize();
 private:
  ZoneList<CharacterRange>* ranges_;
  // If non-zero, the value represents a standard set (e.g., all whitespace
  // characters) without having to expand the ranges.
  uc16 standard_set_type_;
};


class RegExpCharacterClass final : public RegExpTree {
 public:
  RegExpCharacterClass(ZoneList<CharacterRange>* ranges, bool is_negated)
      : set_(ranges),
        is_negated_(is_negated) { }
  explicit RegExpCharacterClass(uc16 type)
      : set_(type),
        is_negated_(false) { }
  void* Accept(RegExpVisitor* visitor, void* data) override;
  virtual RegExpNode* ToNode(RegExpCompiler* compiler,
                             RegExpNode* on_success) override;
  RegExpCharacterClass* AsCharacterClass() override;
  bool IsCharacterClass() override;
  bool IsTextElement() override { return true; }
  int min_match() override { return 1; }
  int max_match() override { return 1; }
  void AppendToText(RegExpText* text, Zone* zone) override;
  CharacterSet character_set() { return set_; }
  // TODO(lrn): Remove need for complex version if is_standard that
  // recognizes a mangled standard set and just do { return set_.is_special(); }
  bool is_standard(Zone* zone);
  // Returns a value representing the standard character set if is_standard()
  // returns true.
  // Currently used values are:
  // s : unicode whitespace
  // S : unicode non-whitespace
  // w : ASCII word character (digit, letter, underscore)
  // W : non-ASCII word character
  // d : ASCII digit
  // D : non-ASCII digit
  // . : non-unicode non-newline
  // * : All characters
  uc16 standard_type() { return set_.standard_set_type(); }
  ZoneList<CharacterRange>* ranges(Zone* zone) { return set_.ranges(zone); }
  bool is_negated() { return is_negated_; }

 private:
  CharacterSet set_;
  bool is_negated_;
};


class RegExpAtom final : public RegExpTree {
 public:
  explicit RegExpAtom(Vector<const uc16> data) : data_(data) { }
  void* Accept(RegExpVisitor* visitor, void* data) override;
  virtual RegExpNode* ToNode(RegExpCompiler* compiler,
                             RegExpNode* on_success) override;
  RegExpAtom* AsAtom() override;
  bool IsAtom() override;
  bool IsTextElement() override { return true; }
  int min_match() override { return data_.length(); }
  int max_match() override { return data_.length(); }
  void AppendToText(RegExpText* text, Zone* zone) override;
  Vector<const uc16> data() { return data_; }
  int length() { return data_.length(); }
 private:
  Vector<const uc16> data_;
};


class RegExpText final : public RegExpTree {
 public:
  explicit RegExpText(Zone* zone) : elements_(2, zone), length_(0) {}
  void* Accept(RegExpVisitor* visitor, void* data) override;
  virtual RegExpNode* ToNode(RegExpCompiler* compiler,
                             RegExpNode* on_success) override;
  RegExpText* AsText() override;
  bool IsText() override;
  bool IsTextElement() override { return true; }
  int min_match() override { return length_; }
  int max_match() override { return length_; }
  void AppendToText(RegExpText* text, Zone* zone) override;
  void AddElement(TextElement elm, Zone* zone)  {
    elements_.Add(elm, zone);
    length_ += elm.length();
  }
  ZoneList<TextElement>* elements() { return &elements_; }
 private:
  ZoneList<TextElement> elements_;
  int length_;
};


class RegExpQuantifier final : public RegExpTree {
 public:
  enum QuantifierType { GREEDY, NON_GREEDY, POSSESSIVE };
  RegExpQuantifier(int min, int max, QuantifierType type, RegExpTree* body)
      : body_(body),
        min_(min),
        max_(max),
        min_match_(min * body->min_match()),
        quantifier_type_(type) {
    if (max > 0 && body->max_match() > kInfinity / max) {
      max_match_ = kInfinity;
    } else {
      max_match_ = max * body->max_match();
    }
  }
  void* Accept(RegExpVisitor* visitor, void* data) override;
  virtual RegExpNode* ToNode(RegExpCompiler* compiler,
                             RegExpNode* on_success) override;
  static RegExpNode* ToNode(int min,
                            int max,
                            bool is_greedy,
                            RegExpTree* body,
                            RegExpCompiler* compiler,
                            RegExpNode* on_success,
                            bool not_at_start = false);
  RegExpQuantifier* AsQuantifier() override;
  Interval CaptureRegisters() override;
  bool IsQuantifier() override;
  int min_match() override { return min_match_; }
  int max_match() override { return max_match_; }
  int min() { return min_; }
  int max() { return max_; }
  bool is_possessive() { return quantifier_type_ == POSSESSIVE; }
  bool is_non_greedy() { return quantifier_type_ == NON_GREEDY; }
  bool is_greedy() { return quantifier_type_ == GREEDY; }
  RegExpTree* body() { return body_; }

 private:
  RegExpTree* body_;
  int min_;
  int max_;
  int min_match_;
  int max_match_;
  QuantifierType quantifier_type_;
};


class RegExpCapture final : public RegExpTree {
 public:
  explicit RegExpCapture(RegExpTree* body, int index)
      : body_(body), index_(index) { }
  void* Accept(RegExpVisitor* visitor, void* data) override;
  virtual RegExpNode* ToNode(RegExpCompiler* compiler,
                             RegExpNode* on_success) override;
  static RegExpNode* ToNode(RegExpTree* body,
                            int index,
                            RegExpCompiler* compiler,
                            RegExpNode* on_success);
  RegExpCapture* AsCapture() override;
  bool IsAnchoredAtStart() override;
  bool IsAnchoredAtEnd() override;
  Interval CaptureRegisters() override;
  bool IsCapture() override;
  int min_match() override { return body_->min_match(); }
  int max_match() override { return body_->max_match(); }
  RegExpTree* body() { return body_; }
  int index() { return index_; }
  static int StartRegister(int index) { return index * 2; }
  static int EndRegister(int index) { return index * 2 + 1; }

 private:
  RegExpTree* body_;
  int index_;
};


class RegExpLookahead final : public RegExpTree {
 public:
  RegExpLookahead(RegExpTree* body,
                  bool is_positive,
                  int capture_count,
                  int capture_from)
      : body_(body),
        is_positive_(is_positive),
        capture_count_(capture_count),
        capture_from_(capture_from) { }

  void* Accept(RegExpVisitor* visitor, void* data) override;
  virtual RegExpNode* ToNode(RegExpCompiler* compiler,
                             RegExpNode* on_success) override;
  RegExpLookahead* AsLookahead() override;
  Interval CaptureRegisters() override;
  bool IsLookahead() override;
  bool IsAnchoredAtStart() override;
  int min_match() override { return 0; }
  int max_match() override { return 0; }
  RegExpTree* body() { return body_; }
  bool is_positive() { return is_positive_; }
  int capture_count() { return capture_count_; }
  int capture_from() { return capture_from_; }

 private:
  RegExpTree* body_;
  bool is_positive_;
  int capture_count_;
  int capture_from_;
};


class RegExpBackReference final : public RegExpTree {
 public:
  explicit RegExpBackReference(RegExpCapture* capture)
      : capture_(capture) { }
  void* Accept(RegExpVisitor* visitor, void* data) override;
  virtual RegExpNode* ToNode(RegExpCompiler* compiler,
                             RegExpNode* on_success) override;
  RegExpBackReference* AsBackReference() override;
  bool IsBackReference() override;
  int min_match() override { return 0; }
  int max_match() override { return capture_->max_match(); }
  int index() { return capture_->index(); }
  RegExpCapture* capture() { return capture_; }
 private:
  RegExpCapture* capture_;
};


class RegExpEmpty final : public RegExpTree {
 public:
  RegExpEmpty() { }
  void* Accept(RegExpVisitor* visitor, void* data) override;
  virtual RegExpNode* ToNode(RegExpCompiler* compiler,
                             RegExpNode* on_success) override;
  RegExpEmpty* AsEmpty() override;
  bool IsEmpty() override;
  int min_match() override { return 0; }
  int max_match() override { return 0; }
};


// ----------------------------------------------------------------------------
// Basic visitor
// - leaf node visitors are abstract.

class AstVisitor BASE_EMBEDDED {
 public:
  AstVisitor() {}
  virtual ~AstVisitor() {}

  // Stack overflow check and dynamic dispatch.
  virtual void Visit(AstNode* node) = 0;

  // Iteration left-to-right.
  virtual void VisitDeclarations(ZoneList<Declaration*>* declarations);
  virtual void VisitStatements(ZoneList<Statement*>* statements);
  virtual void VisitExpressions(ZoneList<Expression*>* expressions);

  // Individual AST nodes.
#define DEF_VISIT(type)                         \
  virtual void Visit##type(type* node) = 0;
  AST_NODE_LIST(DEF_VISIT)
#undef DEF_VISIT
};


#define DEFINE_AST_VISITOR_SUBCLASS_MEMBERS()               \
 public:                                                    \
  void Visit(AstNode* node) final {                         \
    if (!CheckStackOverflow()) node->Accept(this);          \
  }                                                         \
                                                            \
  void SetStackOverflow() { stack_overflow_ = true; }       \
  void ClearStackOverflow() { stack_overflow_ = false; }    \
  bool HasStackOverflow() const { return stack_overflow_; } \
                                                            \
  bool CheckStackOverflow() {                               \
    if (stack_overflow_) return true;                       \
    StackLimitCheck check(isolate_);                        \
    if (!check.HasOverflowed()) return false;               \
    stack_overflow_ = true;                                 \
    return true;                                            \
  }                                                         \
                                                            \
 private:                                                   \
  void InitializeAstVisitor(Isolate* isolate, Zone* zone) { \
    isolate_ = isolate;                                     \
    zone_ = zone;                                           \
    stack_overflow_ = false;                                \
  }                                                         \
  Zone* zone() { return zone_; }                            \
  Isolate* isolate() { return isolate_; }                   \
                                                            \
  Isolate* isolate_;                                        \
  Zone* zone_;                                              \
  bool stack_overflow_


// ----------------------------------------------------------------------------
// AstNode factory

class AstNodeFactory final BASE_EMBEDDED {
 public:
  explicit AstNodeFactory(AstValueFactory* ast_value_factory)
      : local_zone_(ast_value_factory->zone()),
        parser_zone_(ast_value_factory->zone()),
        ast_value_factory_(ast_value_factory) {}

  VariableDeclaration* NewVariableDeclaration(
      VariableProxy* proxy, VariableMode mode, Scope* scope, int pos,
      bool is_class_declaration = false, int declaration_group_start = -1) {
    return new (parser_zone_)
        VariableDeclaration(parser_zone_, proxy, mode, scope, pos,
                            is_class_declaration, declaration_group_start);
  }

  FunctionDeclaration* NewFunctionDeclaration(VariableProxy* proxy,
                                              VariableMode mode,
                                              FunctionLiteral* fun,
                                              Scope* scope,
                                              int pos) {
    return new (parser_zone_)
        FunctionDeclaration(parser_zone_, proxy, mode, fun, scope, pos);
  }

  ImportDeclaration* NewImportDeclaration(VariableProxy* proxy,
                                          const AstRawString* import_name,
                                          const AstRawString* module_specifier,
                                          Scope* scope, int pos) {
    return new (parser_zone_) ImportDeclaration(
        parser_zone_, proxy, import_name, module_specifier, scope, pos);
  }

  ExportDeclaration* NewExportDeclaration(VariableProxy* proxy,
                                          Scope* scope,
                                          int pos) {
    return new (parser_zone_)
        ExportDeclaration(parser_zone_, proxy, scope, pos);
  }

  Block* NewBlock(ZoneList<const AstRawString*>* labels, int capacity,
                  bool ignore_completion_value, int pos) {
    return new (local_zone_)
        Block(local_zone_, labels, capacity, ignore_completion_value, pos);
  }

#define STATEMENT_WITH_LABELS(NodeType)                                     \
  NodeType* New##NodeType(ZoneList<const AstRawString*>* labels, int pos) { \
    return new (local_zone_) NodeType(local_zone_, labels, pos);            \
  }
  STATEMENT_WITH_LABELS(DoWhileStatement)
  STATEMENT_WITH_LABELS(WhileStatement)
  STATEMENT_WITH_LABELS(ForStatement)
  STATEMENT_WITH_LABELS(SwitchStatement)
#undef STATEMENT_WITH_LABELS

  ForEachStatement* NewForEachStatement(ForEachStatement::VisitMode visit_mode,
                                        ZoneList<const AstRawString*>* labels,
                                        int pos) {
    switch (visit_mode) {
      case ForEachStatement::ENUMERATE: {
        return new (local_zone_) ForInStatement(local_zone_, labels, pos);
      }
      case ForEachStatement::ITERATE: {
        return new (local_zone_) ForOfStatement(local_zone_, labels, pos);
      }
    }
    UNREACHABLE();
    return NULL;
  }

  ExpressionStatement* NewExpressionStatement(Expression* expression, int pos) {
    return new (local_zone_) ExpressionStatement(local_zone_, expression, pos);
  }

  ContinueStatement* NewContinueStatement(IterationStatement* target, int pos) {
    return new (local_zone_) ContinueStatement(local_zone_, target, pos);
  }

  BreakStatement* NewBreakStatement(BreakableStatement* target, int pos) {
    return new (local_zone_) BreakStatement(local_zone_, target, pos);
  }

  ReturnStatement* NewReturnStatement(Expression* expression, int pos) {
    return new (local_zone_) ReturnStatement(local_zone_, expression, pos);
  }

  WithStatement* NewWithStatement(Scope* scope,
                                  Expression* expression,
                                  Statement* statement,
                                  int pos) {
    return new (local_zone_)
        WithStatement(local_zone_, scope, expression, statement, pos);
  }

  IfStatement* NewIfStatement(Expression* condition,
                              Statement* then_statement,
                              Statement* else_statement,
                              int pos) {
    return new (local_zone_) IfStatement(local_zone_, condition, then_statement,
                                         else_statement, pos);
  }

  TryCatchStatement* NewTryCatchStatement(Block* try_block, Scope* scope,
                                          Variable* variable,
                                          Block* catch_block, int pos) {
    return new (local_zone_) TryCatchStatement(local_zone_, try_block, scope,
                                               variable, catch_block, pos);
  }

  TryFinallyStatement* NewTryFinallyStatement(Block* try_block,
                                              Block* finally_block, int pos) {
    return new (local_zone_)
        TryFinallyStatement(local_zone_, try_block, finally_block, pos);
  }

  DebuggerStatement* NewDebuggerStatement(int pos) {
    return new (local_zone_) DebuggerStatement(local_zone_, pos);
  }

  EmptyStatement* NewEmptyStatement(int pos) {
    return new (local_zone_) EmptyStatement(local_zone_, pos);
  }

  CaseClause* NewCaseClause(
      Expression* label, ZoneList<Statement*>* statements, int pos) {
    return new (local_zone_) CaseClause(local_zone_, label, statements, pos);
  }

  Literal* NewStringLiteral(const AstRawString* string, int pos) {
    return new (local_zone_)
        Literal(local_zone_, ast_value_factory_->NewString(string), pos);
  }

  // A JavaScript symbol (ECMA-262 edition 6).
  Literal* NewSymbolLiteral(const char* name, int pos) {
    return new (local_zone_)
        Literal(local_zone_, ast_value_factory_->NewSymbol(name), pos);
  }

  Literal* NewNumberLiteral(double number, int pos, bool with_dot = false) {
    return new (local_zone_) Literal(
        local_zone_, ast_value_factory_->NewNumber(number, with_dot), pos);
  }

  Literal* NewSmiLiteral(int number, int pos) {
    return new (local_zone_)
        Literal(local_zone_, ast_value_factory_->NewSmi(number), pos);
  }

  Literal* NewBooleanLiteral(bool b, int pos) {
    return new (local_zone_)
        Literal(local_zone_, ast_value_factory_->NewBoolean(b), pos);
  }

  Literal* NewNullLiteral(int pos) {
    return new (local_zone_)
        Literal(local_zone_, ast_value_factory_->NewNull(), pos);
  }

  Literal* NewUndefinedLiteral(int pos) {
    return new (local_zone_)
        Literal(local_zone_, ast_value_factory_->NewUndefined(), pos);
  }

  Literal* NewTheHoleLiteral(int pos) {
    return new (local_zone_)
        Literal(local_zone_, ast_value_factory_->NewTheHole(), pos);
  }

  ObjectLiteral* NewObjectLiteral(
      ZoneList<ObjectLiteral::Property*>* properties,
      int literal_index,
      int boilerplate_properties,
      bool has_function,
      bool is_strong,
      int pos) {
    return new (local_zone_)
        ObjectLiteral(local_zone_, properties, literal_index,
                      boilerplate_properties, has_function, is_strong, pos);
  }

  ObjectLiteral::Property* NewObjectLiteralProperty(
      Expression* key, Expression* value, ObjectLiteralProperty::Kind kind,
      bool is_static, bool is_computed_name) {
    return new (local_zone_)
        ObjectLiteral::Property(key, value, kind, is_static, is_computed_name);
  }

  ObjectLiteral::Property* NewObjectLiteralProperty(Expression* key,
                                                    Expression* value,
                                                    bool is_static,
                                                    bool is_computed_name) {
    return new (local_zone_) ObjectLiteral::Property(
        ast_value_factory_, key, value, is_static, is_computed_name);
  }

  RegExpLiteral* NewRegExpLiteral(const AstRawString* pattern,
                                  const AstRawString* flags,
                                  int literal_index,
                                  bool is_strong,
                                  int pos) {
    return new (local_zone_) RegExpLiteral(local_zone_, pattern, flags,
                                           literal_index, is_strong, pos);
  }

  ArrayLiteral* NewArrayLiteral(ZoneList<Expression*>* values,
                                int literal_index,
                                bool is_strong,
                                int pos) {
    return new (local_zone_)
        ArrayLiteral(local_zone_, values, -1, literal_index, is_strong, pos);
  }

  ArrayLiteral* NewArrayLiteral(ZoneList<Expression*>* values,
                                int first_spread_index, int literal_index,
                                bool is_strong, int pos) {
    return new (local_zone_) ArrayLiteral(
        local_zone_, values, first_spread_index, literal_index, is_strong, pos);
  }

  VariableProxy* NewVariableProxy(Variable* var,
                                  int start_position = RelocInfo::kNoPosition,
                                  int end_position = RelocInfo::kNoPosition) {
    return new (parser_zone_)
        VariableProxy(parser_zone_, var, start_position, end_position);
  }

  VariableProxy* NewVariableProxy(const AstRawString* name,
                                  Variable::Kind variable_kind,
                                  int start_position = RelocInfo::kNoPosition,
                                  int end_position = RelocInfo::kNoPosition) {
    DCHECK_NOT_NULL(name);
    return new (parser_zone_) VariableProxy(parser_zone_, name, variable_kind,
                                            start_position, end_position);
  }

  Property* NewProperty(Expression* obj, Expression* key, int pos) {
    return new (local_zone_) Property(local_zone_, obj, key, pos);
  }

  Call* NewCall(Expression* expression,
                ZoneList<Expression*>* arguments,
                int pos) {
    return new (local_zone_) Call(local_zone_, expression, arguments, pos);
  }

  CallNew* NewCallNew(Expression* expression,
                      ZoneList<Expression*>* arguments,
                      int pos) {
    return new (local_zone_) CallNew(local_zone_, expression, arguments, pos);
  }

  CallRuntime* NewCallRuntime(Runtime::FunctionId id,
                              ZoneList<Expression*>* arguments, int pos) {
    return new (local_zone_)
        CallRuntime(local_zone_, Runtime::FunctionForId(id), arguments, pos);
  }

  CallRuntime* NewCallRuntime(const Runtime::Function* function,
                              ZoneList<Expression*>* arguments, int pos) {
    return new (local_zone_) CallRuntime(local_zone_, function, arguments, pos);
  }

  CallRuntime* NewCallRuntime(int context_index,
                              ZoneList<Expression*>* arguments, int pos) {
    return new (local_zone_)
        CallRuntime(local_zone_, context_index, arguments, pos);
  }

  UnaryOperation* NewUnaryOperation(Token::Value op,
                                    Expression* expression,
                                    int pos) {
    return new (local_zone_) UnaryOperation(local_zone_, op, expression, pos);
  }

  BinaryOperation* NewBinaryOperation(Token::Value op,
                                      Expression* left,
                                      Expression* right,
                                      int pos) {
    return new (local_zone_) BinaryOperation(local_zone_, op, left, right, pos);
  }

  CountOperation* NewCountOperation(Token::Value op,
                                    bool is_prefix,
                                    Expression* expr,
                                    int pos) {
    return new (local_zone_)
        CountOperation(local_zone_, op, is_prefix, expr, pos);
  }

  CompareOperation* NewCompareOperation(Token::Value op,
                                        Expression* left,
                                        Expression* right,
                                        int pos) {
    return new (local_zone_)
        CompareOperation(local_zone_, op, left, right, pos);
  }

  Spread* NewSpread(Expression* expression, int pos) {
    return new (local_zone_) Spread(local_zone_, expression, pos);
  }

  Conditional* NewConditional(Expression* condition,
                              Expression* then_expression,
                              Expression* else_expression,
                              int position) {
    return new (local_zone_) Conditional(
        local_zone_, condition, then_expression, else_expression, position);
  }

  Assignment* NewAssignment(Token::Value op,
                            Expression* target,
                            Expression* value,
                            int pos) {
    DCHECK(Token::IsAssignmentOp(op));
    Assignment* assign =
        new (local_zone_) Assignment(local_zone_, op, target, value, pos);
    if (assign->is_compound()) {
      DCHECK(Token::IsAssignmentOp(op));
      assign->binary_operation_ =
          NewBinaryOperation(assign->binary_op(), target, value, pos + 1);
    }
    return assign;
  }

  Yield* NewYield(Expression *generator_object,
                  Expression* expression,
                  Yield::Kind yield_kind,
                  int pos) {
    if (!expression) expression = NewUndefinedLiteral(pos);
    return new (local_zone_)
        Yield(local_zone_, generator_object, expression, yield_kind, pos);
  }

  Throw* NewThrow(Expression* exception, int pos) {
    return new (local_zone_) Throw(local_zone_, exception, pos);
  }

  FunctionLiteral* NewFunctionLiteral(
      const AstRawString* name, AstValueFactory* ast_value_factory,
      Scope* scope, ZoneList<Statement*>* body, int materialized_literal_count,
      int expected_property_count, int parameter_count,
      FunctionLiteral::ParameterFlag has_duplicate_parameters,
      FunctionLiteral::FunctionType function_type,
      FunctionLiteral::IsFunctionFlag is_function,
      FunctionLiteral::EagerCompileHint eager_compile_hint, FunctionKind kind,
      int position) {
    return new (parser_zone_) FunctionLiteral(
        parser_zone_, name, ast_value_factory, scope, body,
        materialized_literal_count, expected_property_count, parameter_count,
        function_type, has_duplicate_parameters, is_function,
        eager_compile_hint, kind, position);
  }

  ClassLiteral* NewClassLiteral(const AstRawString* name, 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,
                     properties, start_position, end_position);
  }

  NativeFunctionLiteral* NewNativeFunctionLiteral(const AstRawString* name,
                                                  v8::Extension* extension,
                                                  int pos) {
    return new (parser_zone_)
        NativeFunctionLiteral(parser_zone_, name, extension, pos);
  }

  ThisFunction* NewThisFunction(int pos) {
    return new (local_zone_) ThisFunction(local_zone_, pos);
  }

  SuperPropertyReference* NewSuperPropertyReference(VariableProxy* this_var,
                                                    Expression* home_object,
                                                    int pos) {
    return new (parser_zone_)
        SuperPropertyReference(parser_zone_, this_var, home_object, pos);
  }

  SuperCallReference* NewSuperCallReference(VariableProxy* this_var,
                                            VariableProxy* new_target_var,
                                            VariableProxy* this_function_var,
                                            int pos) {
    return new (parser_zone_) SuperCallReference(
        parser_zone_, this_var, new_target_var, this_function_var, pos);
  }

  EmptyParentheses* NewEmptyParentheses(int pos) {
    return new (local_zone_) EmptyParentheses(local_zone_, pos);
  }

  Zone* zone() const { return local_zone_; }

  // Handles use of temporary zones when parsing inner function bodies.
  class BodyScope {
   public:
    BodyScope(AstNodeFactory* factory, Zone* temp_zone, bool use_temp_zone)
        : factory_(factory), prev_zone_(factory->local_zone_) {
      if (use_temp_zone) {
        factory->local_zone_ = temp_zone;
      }
    }

    ~BodyScope() { factory_->local_zone_ = prev_zone_; }

   private:
    AstNodeFactory* factory_;
    Zone* prev_zone_;
  };

 private:
  // This zone may be deallocated upon returning from parsing a function body
  // which we can guarantee is not going to be compiled or have its AST
  // inspected.
  // See ParseFunctionLiteral in parser.cc for preconditions.
  Zone* local_zone_;
  // ZoneObjects which need to persist until scope analysis must be allocated in
  // the parser-level zone.
  Zone* parser_zone_;
  AstValueFactory* ast_value_factory_;
};


} }  // namespace v8::internal

#endif  // V8_AST_H_
