// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#ifndef RUNTIME_VM_REGEXP_H_
#define RUNTIME_VM_REGEXP_H_

#include "platform/unicode.h"

#include "vm/compiler/assembler/assembler.h"
#include "vm/compiler/backend/flow_graph_compiler.h"
#include "vm/compiler/backend/il.h"
#include "vm/object.h"
#include "vm/regexp_assembler.h"
#include "vm/splay-tree.h"

namespace dart {

class NodeVisitor;
class RegExpCompiler;
class RegExpMacroAssembler;
class RegExpNode;
class RegExpTree;
class BoyerMooreLookahead;

// Represents code units in the range from from_ to to_, both ends are
// inclusive.
class CharacterRange {
 public:
  CharacterRange() : from_(0), to_(0) {}
  CharacterRange(int32_t from, int32_t to) : from_(from), to_(to) {}

  static void AddClassEscape(uint16_t type,
                             ZoneGrowableArray<CharacterRange>* ranges);
  // Add class escapes with case equivalent closure for \w and \W if necessary.
  static void AddClassEscape(uint16_t type,
                             ZoneGrowableArray<CharacterRange>* ranges,
                             bool add_unicode_case_equivalents);
  static GrowableArray<const intptr_t> GetWordBounds();
  static inline CharacterRange Singleton(int32_t value) {
    return CharacterRange(value, value);
  }
  static inline CharacterRange Range(int32_t from, int32_t to) {
    ASSERT(from <= to);
    return CharacterRange(from, to);
  }
  static inline CharacterRange Everything() {
    return CharacterRange(0, Utf::kMaxCodePoint);
  }
  static inline ZoneGrowableArray<CharacterRange>* List(Zone* zone,
                                                        CharacterRange range) {
    auto list = new (zone) ZoneGrowableArray<CharacterRange>(1);
    list->Add(range);
    return list;
  }
  bool Contains(int32_t i) const { return from_ <= i && i <= to_; }
  int32_t from() const { return from_; }
  void set_from(int32_t value) { from_ = value; }
  int32_t to() const { return to_; }
  void set_to(int32_t value) { to_ = value; }
  bool is_valid() const { return from_ <= to_; }
  bool IsEverything(int32_t max) const { return from_ == 0 && to_ >= max; }
  bool IsSingleton() const { return (from_ == to_); }
  static void AddCaseEquivalents(ZoneGrowableArray<CharacterRange>* ranges,
                                 bool is_one_byte,
                                 Zone* zone);
  static void Split(ZoneGrowableArray<CharacterRange>* base,
                    GrowableArray<const intptr_t> overlay,
                    ZoneGrowableArray<CharacterRange>** included,
                    ZoneGrowableArray<CharacterRange>** excluded,
                    Zone* zone);
  // Whether a range list is in canonical form: Ranges ordered by from value,
  // and ranges non-overlapping and non-adjacent.
  static bool IsCanonical(ZoneGrowableArray<CharacterRange>* ranges);
  // Convert range list to canonical form. The characters covered by the ranges
  // will still be the same, but no character is in more than one range, and
  // adjacent ranges are merged. The resulting list may be shorter than the
  // original, but cannot be longer.
  static void Canonicalize(ZoneGrowableArray<CharacterRange>* ranges);
  // Negate the contents of a character range in canonical form.
  static void Negate(ZoneGrowableArray<CharacterRange>* src,
                     ZoneGrowableArray<CharacterRange>* dst);
  static const intptr_t kStartMarker = (1 << 24);
  static const intptr_t kPayloadMask = (1 << 24) - 1;

 private:
  int32_t from_;
  int32_t to_;

  DISALLOW_ALLOCATION();
};

// A set of unsigned integers that behaves especially well on small
// integers (< 32).  May do zone-allocation.
class OutSet : public ZoneAllocated {
 public:
  OutSet() : first_(0), remaining_(NULL), successors_(NULL) {}
  OutSet* Extend(unsigned value, Zone* zone);
  bool Get(unsigned value) const;
  static const unsigned kFirstLimit = 32;

 private:
  // Destructively set a value in this set.  In most cases you want
  // to use Extend instead to ensure that only one instance exists
  // that contains the same values.
  void Set(unsigned value, Zone* zone);

  // The successors are a list of sets that contain the same values
  // as this set and the one more value that is not present in this
  // set.
  ZoneGrowableArray<OutSet*>* successors() { return successors_; }

  OutSet(uint32_t first, ZoneGrowableArray<unsigned>* remaining)
      : first_(first), remaining_(remaining), successors_(NULL) {}
  uint32_t first_;
  ZoneGrowableArray<unsigned>* remaining_;
  ZoneGrowableArray<OutSet*>* successors_;
  friend class Trace;
};

// A mapping from integers, specified as ranges, to a set of integers.
// Used for mapping character ranges to choices.
class DispatchTable : public ValueObject {
 public:
  explicit DispatchTable(Zone* zone) : tree_(zone) {}

  class Entry {
   public:
    Entry() : from_(0), to_(0), out_set_(nullptr) {}
    Entry(int32_t from, int32_t to, OutSet* out_set)
        : from_(from), to_(to), out_set_(out_set) {
      ASSERT(from <= to);
    }
    int32_t from() { return from_; }
    int32_t to() { return to_; }
    void set_to(int32_t value) { to_ = value; }
    void AddValue(int value, Zone* zone) {
      out_set_ = out_set_->Extend(value, zone);
    }
    OutSet* out_set() { return out_set_; }

   private:
    int32_t from_;
    int32_t to_;
    OutSet* out_set_;
  };

  class Config {
   public:
    typedef int32_t Key;
    typedef Entry Value;
    static const int32_t kNoKey;
    static const Entry NoValue() { return Value(); }
    static inline int Compare(int32_t a, int32_t b) {
      if (a == b)
        return 0;
      else if (a < b)
        return -1;
      else
        return 1;
    }
  };

  void AddRange(CharacterRange range, int32_t value, Zone* zone);
  OutSet* Get(int32_t value);
  void Dump();

  template <typename Callback>
  void ForEach(Callback* callback) {
    return tree()->ForEach(callback);
  }

 private:
  // There can't be a static empty set since it allocates its
  // successors in a zone and caches them.
  OutSet* empty() { return &empty_; }
  OutSet empty_;
  ZoneSplayTree<Config>* tree() { return &tree_; }
  ZoneSplayTree<Config> tree_;
};

// Categorizes character ranges into BMP, non-BMP, lead, and trail surrogates.
class UnicodeRangeSplitter : public ValueObject {
 public:
  UnicodeRangeSplitter(Zone* zone, ZoneGrowableArray<CharacterRange>* base);
  void Call(uint32_t from, DispatchTable::Entry entry);

  ZoneGrowableArray<CharacterRange>* bmp() { return bmp_; }
  ZoneGrowableArray<CharacterRange>* lead_surrogates() {
    return lead_surrogates_;
  }
  ZoneGrowableArray<CharacterRange>* trail_surrogates() {
    return trail_surrogates_;
  }
  ZoneGrowableArray<CharacterRange>* non_bmp() const { return non_bmp_; }

 private:
  static const int kBase = 0;
  // Separate ranges into
  static const int kBmpCodePoints = 1;
  static const int kLeadSurrogates = 2;
  static const int kTrailSurrogates = 3;
  static const int kNonBmpCodePoints = 4;

  Zone* zone_;
  DispatchTable table_;
  ZoneGrowableArray<CharacterRange>* bmp_;
  ZoneGrowableArray<CharacterRange>* lead_surrogates_;
  ZoneGrowableArray<CharacterRange>* trail_surrogates_;
  ZoneGrowableArray<CharacterRange>* non_bmp_;
};

#define FOR_EACH_NODE_TYPE(VISIT)                                              \
  VISIT(End)                                                                   \
  VISIT(Action)                                                                \
  VISIT(Choice)                                                                \
  VISIT(BackReference)                                                         \
  VISIT(Assertion)                                                             \
  VISIT(Text)

#define FOR_EACH_REG_EXP_TREE_TYPE(VISIT)                                      \
  VISIT(Disjunction)                                                           \
  VISIT(Alternative)                                                           \
  VISIT(Assertion)                                                             \
  VISIT(CharacterClass)                                                        \
  VISIT(Atom)                                                                  \
  VISIT(Quantifier)                                                            \
  VISIT(Capture)                                                               \
  VISIT(Lookaround)                                                            \
  VISIT(BackReference)                                                         \
  VISIT(Empty)                                                                 \
  VISIT(Text)

#define FORWARD_DECLARE(Name) class RegExp##Name;
FOR_EACH_REG_EXP_TREE_TYPE(FORWARD_DECLARE)
#undef FORWARD_DECLARE

class TextElement {
 public:
  enum TextType { ATOM, CHAR_CLASS };

  static TextElement Atom(RegExpAtom* atom);
  static TextElement CharClass(RegExpCharacterClass* char_class);

  intptr_t cp_offset() const { return cp_offset_; }
  void set_cp_offset(intptr_t cp_offset) { cp_offset_ = cp_offset; }
  intptr_t length() const;

  TextType text_type() const { return text_type_; }

  RegExpTree* tree() const { return tree_; }

  RegExpAtom* atom() const {
    ASSERT(text_type() == ATOM);
    return reinterpret_cast<RegExpAtom*>(tree());
  }

  RegExpCharacterClass* char_class() const {
    ASSERT(text_type() == CHAR_CLASS);
    return reinterpret_cast<RegExpCharacterClass*>(tree());
  }

 private:
  TextElement(TextType text_type, RegExpTree* tree)
      : cp_offset_(-1), text_type_(text_type), tree_(tree) {}

  intptr_t cp_offset_;
  TextType text_type_;
  RegExpTree* tree_;

  DISALLOW_ALLOCATION();
};

class Trace;
struct PreloadState;
class GreedyLoopState;
class AlternativeGenerationList;

struct NodeInfo {
  NodeInfo()
      : being_analyzed(false),
        been_analyzed(false),
        follows_word_interest(false),
        follows_newline_interest(false),
        follows_start_interest(false),
        at_end(false),
        visited(false),
        replacement_calculated(false) {}

  // Returns true if the interests and assumptions of this node
  // matches the given one.
  bool Matches(NodeInfo* that) {
    return (at_end == that->at_end) &&
           (follows_word_interest == that->follows_word_interest) &&
           (follows_newline_interest == that->follows_newline_interest) &&
           (follows_start_interest == that->follows_start_interest);
  }

  // Updates the interests of this node given the interests of the
  // node preceding it.
  void AddFromPreceding(NodeInfo* that) {
    at_end |= that->at_end;
    follows_word_interest |= that->follows_word_interest;
    follows_newline_interest |= that->follows_newline_interest;
    follows_start_interest |= that->follows_start_interest;
  }

  bool HasLookbehind() {
    return follows_word_interest || follows_newline_interest ||
           follows_start_interest;
  }

  // Sets the interests of this node to include the interests of the
  // following node.
  void AddFromFollowing(NodeInfo* that) {
    follows_word_interest |= that->follows_word_interest;
    follows_newline_interest |= that->follows_newline_interest;
    follows_start_interest |= that->follows_start_interest;
  }

  void ResetCompilationState() {
    being_analyzed = false;
    been_analyzed = false;
  }

  bool being_analyzed : 1;
  bool been_analyzed : 1;

  // These bits are set of this node has to know what the preceding
  // character was.
  bool follows_word_interest : 1;
  bool follows_newline_interest : 1;
  bool follows_start_interest : 1;

  bool at_end : 1;
  bool visited : 1;
  bool replacement_calculated : 1;
};

// Details of a quick mask-compare check that can look ahead in the
// input stream.
class QuickCheckDetails {
 public:
  QuickCheckDetails()
      : characters_(0), mask_(0), value_(0), cannot_match_(false) {}
  explicit QuickCheckDetails(intptr_t characters)
      : characters_(characters), mask_(0), value_(0), cannot_match_(false) {}
  bool Rationalize(bool one_byte);
  // Merge in the information from another branch of an alternation.
  void Merge(QuickCheckDetails* other, intptr_t from_index);
  // Advance the current position by some amount.
  void Advance(intptr_t by, bool one_byte);
  void Clear();
  bool cannot_match() { return cannot_match_; }
  void set_cannot_match() { cannot_match_ = true; }
  struct Position {
    Position() : mask(0), value(0), determines_perfectly(false) {}
    uint16_t mask;
    uint16_t value;
    bool determines_perfectly;
  };
  intptr_t characters() { return characters_; }
  void set_characters(intptr_t characters) { characters_ = characters; }
  Position* positions(intptr_t index) {
    ASSERT(index >= 0);
    ASSERT(index < characters_);
    return positions_ + index;
  }
  uint32_t mask() { return mask_; }
  uint32_t value() { return value_; }

 private:
  // How many characters do we have quick check information from.  This is
  // the same for all branches of a choice node.
  intptr_t characters_;
  Position positions_[4];
  // These values are the condensate of the above array after Rationalize().
  uint32_t mask_;
  uint32_t value_;
  // If set to true, there is no way this quick check can match at all.
  // E.g., if it requires to be at the start of the input, and isn't.
  bool cannot_match_;

  DISALLOW_ALLOCATION();
};

class RegExpNode : public ZoneAllocated {
 public:
  explicit RegExpNode(Zone* zone)
      : replacement_(NULL), trace_count_(0), zone_(zone) {
    bm_info_[0] = bm_info_[1] = NULL;
  }
  virtual ~RegExpNode();
  virtual void Accept(NodeVisitor* visitor) = 0;
  // Generates a goto to this node or actually generates the code at this point.
  virtual void Emit(RegExpCompiler* compiler, Trace* trace) = 0;
  // How many characters must this node consume at a minimum in order to
  // succeed.  If we have found at least 'still_to_find' characters that
  // must be consumed there is no need to ask any following nodes whether
  // they are sure to eat any more characters.  The not_at_start argument is
  // used to indicate that we know we are not at the start of the input.  In
  // this case anchored branches will always fail and can be ignored when
  // determining how many characters are consumed on success.
  virtual intptr_t EatsAtLeast(intptr_t still_to_find,
                               intptr_t budget,
                               bool not_at_start) = 0;
  // Emits some quick code that checks whether the preloaded characters match.
  // Falls through on certain failure, jumps to the label on possible success.
  // If the node cannot make a quick check it does nothing and returns false.
  bool EmitQuickCheck(RegExpCompiler* compiler,
                      Trace* bounds_check_trace,
                      Trace* trace,
                      bool preload_has_checked_bounds,
                      BlockLabel* on_possible_success,
                      QuickCheckDetails* details_return,
                      bool fall_through_on_failure);
  // For a given number of characters this returns a mask and a value.  The
  // next n characters are anded with the mask and compared with the value.
  // A comparison failure indicates the node cannot match the next n characters.
  // A comparison success indicates the node may match.
  virtual void GetQuickCheckDetails(QuickCheckDetails* details,
                                    RegExpCompiler* compiler,
                                    intptr_t characters_filled_in,
                                    bool not_at_start) = 0;
  static const intptr_t kNodeIsTooComplexForGreedyLoops = -1;
  virtual intptr_t GreedyLoopTextLength() {
    return kNodeIsTooComplexForGreedyLoops;
  }
  // Only returns the successor for a text node of length 1 that matches any
  // character and that has no guards on it.
  virtual RegExpNode* GetSuccessorOfOmnivorousTextNode(
      RegExpCompiler* compiler) {
    return NULL;
  }

  // Collects information on the possible code units (mod 128) that can match if
  // we look forward.  This is used for a Boyer-Moore-like string searching
  // implementation.  TODO(erikcorry):  This should share more code with
  // EatsAtLeast, GetQuickCheckDetails.  The budget argument is used to limit
  // the number of nodes we are willing to look at in order to create this data.
  static const intptr_t kRecursionBudget = 200;
  virtual void FillInBMInfo(intptr_t offset,
                            intptr_t budget,
                            BoyerMooreLookahead* bm,
                            bool not_at_start) {
    UNREACHABLE();
  }

  // If we know that the input is one-byte then there are some nodes that can
  // never match.  This method returns a node that can be substituted for
  // itself, or NULL if the node can never match.
  virtual RegExpNode* FilterOneByte(intptr_t depth) { return this; }
  // Helper for FilterOneByte.
  RegExpNode* replacement() {
    ASSERT(info()->replacement_calculated);
    return replacement_;
  }
  RegExpNode* set_replacement(RegExpNode* replacement) {
    info()->replacement_calculated = true;
    replacement_ = replacement;
    return replacement;  // For convenience.
  }

  // We want to avoid recalculating the lookahead info, so we store it on the
  // node.  Only info that is for this node is stored.  We can tell that the
  // info is for this node when offset == 0, so the information is calculated
  // relative to this node.
  void SaveBMInfo(BoyerMooreLookahead* bm, bool not_at_start, intptr_t offset) {
    if (offset == 0) set_bm_info(not_at_start, bm);
  }

  BlockLabel* label() { return &label_; }
  // If non-generic code is generated for a node (i.e. the node is not at the
  // start of the trace) then it cannot be reused.  This variable sets a limit
  // on how often we allow that to happen before we insist on starting a new
  // trace and generating generic code for a node that can be reused by flushing
  // the deferred actions in the current trace and generating a goto.
  static const intptr_t kMaxCopiesCodeGenerated = 10;

  NodeInfo* info() { return &info_; }

  BoyerMooreLookahead* bm_info(bool not_at_start) {
    return bm_info_[not_at_start ? 1 : 0];
  }

  Zone* zone() const { return zone_; }

 protected:
  enum LimitResult { DONE, CONTINUE };
  RegExpNode* replacement_;

  LimitResult LimitVersions(RegExpCompiler* compiler, Trace* trace);

  void set_bm_info(bool not_at_start, BoyerMooreLookahead* bm) {
    bm_info_[not_at_start ? 1 : 0] = bm;
  }

 private:
  static const intptr_t kFirstCharBudget = 10;
  BlockLabel label_;
  NodeInfo info_;
  // This variable keeps track of how many times code has been generated for
  // this node (in different traces).  We don't keep track of where the
  // generated code is located unless the code is generated at the start of
  // a trace, in which case it is generic and can be reused by flushing the
  // deferred operations in the current trace and generating a goto.
  intptr_t trace_count_;
  BoyerMooreLookahead* bm_info_[2];
  Zone* zone_;
};

// A simple closed interval.
class Interval {
 public:
  Interval() : from_(kNone), to_(kNone) {}
  Interval(intptr_t from, intptr_t to) : from_(from), to_(to) {}

  Interval Union(Interval that) {
    if (that.from_ == kNone)
      return *this;
    else if (from_ == kNone)
      return that;
    else
      return Interval(Utils::Minimum(from_, that.from_),
                      Utils::Maximum(to_, that.to_));
  }
  bool Contains(intptr_t value) const {
    return (from_ <= value) && (value <= to_);
  }
  bool is_empty() const { return from_ == kNone; }
  intptr_t from() const { return from_; }
  intptr_t to() const { return to_; }
  static Interval Empty() { return Interval(); }
  static const intptr_t kNone = -1;

 private:
  intptr_t from_;
  intptr_t to_;

  DISALLOW_ALLOCATION();
};

class SeqRegExpNode : public RegExpNode {
 public:
  explicit SeqRegExpNode(RegExpNode* on_success)
      : RegExpNode(on_success->zone()), on_success_(on_success) {}
  RegExpNode* on_success() { return on_success_; }
  void set_on_success(RegExpNode* node) { on_success_ = node; }
  virtual RegExpNode* FilterOneByte(intptr_t depth);
  virtual void FillInBMInfo(intptr_t offset,
                            intptr_t budget,
                            BoyerMooreLookahead* bm,
                            bool not_at_start) {
    on_success_->FillInBMInfo(offset, budget - 1, bm, not_at_start);
    if (offset == 0) set_bm_info(not_at_start, bm);
  }

 protected:
  RegExpNode* FilterSuccessor(intptr_t depth);

 private:
  RegExpNode* on_success_;
};

class ActionNode : public SeqRegExpNode {
 public:
  enum ActionType {
    SET_REGISTER,
    INCREMENT_REGISTER,
    STORE_POSITION,
    BEGIN_SUBMATCH,
    POSITIVE_SUBMATCH_SUCCESS,
    EMPTY_MATCH_CHECK,
    CLEAR_CAPTURES
  };
  static ActionNode* SetRegister(intptr_t reg,
                                 intptr_t val,
                                 RegExpNode* on_success);
  static ActionNode* IncrementRegister(intptr_t reg, RegExpNode* on_success);
  static ActionNode* StorePosition(intptr_t reg,
                                   bool is_capture,
                                   RegExpNode* on_success);
  static ActionNode* ClearCaptures(Interval range, RegExpNode* on_success);
  static ActionNode* BeginSubmatch(intptr_t stack_pointer_reg,
                                   intptr_t position_reg,
                                   RegExpNode* on_success);
  static ActionNode* PositiveSubmatchSuccess(intptr_t stack_pointer_reg,
                                             intptr_t restore_reg,
                                             intptr_t clear_capture_count,
                                             intptr_t clear_capture_from,
                                             RegExpNode* on_success);
  static ActionNode* EmptyMatchCheck(intptr_t start_register,
                                     intptr_t repetition_register,
                                     intptr_t repetition_limit,
                                     RegExpNode* on_success);
  virtual void Accept(NodeVisitor* visitor);
  virtual void Emit(RegExpCompiler* compiler, Trace* trace);
  virtual intptr_t EatsAtLeast(intptr_t still_to_find,
                               intptr_t budget,
                               bool not_at_start);
  virtual void GetQuickCheckDetails(QuickCheckDetails* details,
                                    RegExpCompiler* compiler,
                                    intptr_t filled_in,
                                    bool not_at_start) {
    return on_success()->GetQuickCheckDetails(details, compiler, filled_in,
                                              not_at_start);
  }
  virtual void FillInBMInfo(intptr_t offset,
                            intptr_t budget,
                            BoyerMooreLookahead* bm,
                            bool not_at_start);
  ActionType action_type() { return action_type_; }
  // TODO(erikcorry): We should allow some action nodes in greedy loops.
  virtual intptr_t GreedyLoopTextLength() {
    return kNodeIsTooComplexForGreedyLoops;
  }

 private:
  union {
    struct {
      intptr_t reg;
      intptr_t value;
    } u_store_register;
    struct {
      intptr_t reg;
    } u_increment_register;
    struct {
      intptr_t reg;
      bool is_capture;
    } u_position_register;
    struct {
      intptr_t stack_pointer_register;
      intptr_t current_position_register;
      intptr_t clear_register_count;
      intptr_t clear_register_from;
    } u_submatch;
    struct {
      intptr_t start_register;
      intptr_t repetition_register;
      intptr_t repetition_limit;
    } u_empty_match_check;
    struct {
      intptr_t range_from;
      intptr_t range_to;
    } u_clear_captures;
  } data_;
  ActionNode(ActionType action_type, RegExpNode* on_success)
      : SeqRegExpNode(on_success), action_type_(action_type) {}
  ActionType action_type_;
  friend class DotPrinter;
};

class TextNode : public SeqRegExpNode {
 public:
  TextNode(ZoneGrowableArray<TextElement>* elms,
           bool read_backward,
           RegExpNode* on_success)
      : SeqRegExpNode(on_success), elms_(elms), read_backward_(read_backward) {}
  TextNode(RegExpCharacterClass* that,
           bool read_backward,
           RegExpNode* on_success)
      : SeqRegExpNode(on_success),
        elms_(new (zone()) ZoneGrowableArray<TextElement>(1)),
        read_backward_(read_backward) {
    elms_->Add(TextElement::CharClass(that));
  }
  // Create TextNode for a single character class for the given ranges.
  static TextNode* CreateForCharacterRanges(
      ZoneGrowableArray<CharacterRange>* ranges,
      bool read_backward,
      RegExpNode* on_success,
      RegExpFlags flags);
  // Create TextNode for a surrogate pair with a range given for the
  // lead and the trail surrogate each.
  static TextNode* CreateForSurrogatePair(CharacterRange lead,
                                          CharacterRange trail,
                                          bool read_backward,
                                          RegExpNode* on_success,
                                          RegExpFlags flags);
  virtual void Accept(NodeVisitor* visitor);
  virtual void Emit(RegExpCompiler* compiler, Trace* trace);
  virtual intptr_t EatsAtLeast(intptr_t still_to_find,
                               intptr_t budget,
                               bool not_at_start);
  virtual void GetQuickCheckDetails(QuickCheckDetails* details,
                                    RegExpCompiler* compiler,
                                    intptr_t characters_filled_in,
                                    bool not_at_start);
  ZoneGrowableArray<TextElement>* elements() { return elms_; }
  bool read_backward() { return read_backward_; }
  void MakeCaseIndependent(bool is_one_byte);
  virtual intptr_t GreedyLoopTextLength();
  virtual RegExpNode* GetSuccessorOfOmnivorousTextNode(
      RegExpCompiler* compiler);
  virtual void FillInBMInfo(intptr_t offset,
                            intptr_t budget,
                            BoyerMooreLookahead* bm,
                            bool not_at_start);
  void CalculateOffsets();
  virtual RegExpNode* FilterOneByte(intptr_t depth);

 private:
  enum TextEmitPassType {
    NON_LATIN1_MATCH,            // Check for characters that can't match.
    SIMPLE_CHARACTER_MATCH,      // Case-dependent single character check.
    NON_LETTER_CHARACTER_MATCH,  // Check characters that have no case equivs.
    CASE_CHARACTER_MATCH,        // Case-independent single character check.
    CHARACTER_CLASS_MATCH        // Character class.
  };
  static bool SkipPass(intptr_t pass, bool ignore_case);
  static const intptr_t kFirstRealPass = SIMPLE_CHARACTER_MATCH;
  static const intptr_t kLastPass = CHARACTER_CLASS_MATCH;
  void TextEmitPass(RegExpCompiler* compiler,
                    TextEmitPassType pass,
                    bool preloaded,
                    Trace* trace,
                    bool first_element_checked,
                    intptr_t* checked_up_to);
  intptr_t Length();
  ZoneGrowableArray<TextElement>* elms_;
  bool read_backward_;
};

class AssertionNode : public SeqRegExpNode {
 public:
  enum AssertionType {
    AT_END,
    AT_START,
    AT_BOUNDARY,
    AT_NON_BOUNDARY,
    AFTER_NEWLINE
  };
  static AssertionNode* AtEnd(RegExpNode* on_success) {
    return new (on_success->zone()) AssertionNode(AT_END, on_success);
  }
  static AssertionNode* AtStart(RegExpNode* on_success) {
    return new (on_success->zone()) AssertionNode(AT_START, on_success);
  }
  static AssertionNode* AtBoundary(RegExpNode* on_success) {
    return new (on_success->zone()) AssertionNode(AT_BOUNDARY, on_success);
  }
  static AssertionNode* AtNonBoundary(RegExpNode* on_success) {
    return new (on_success->zone()) AssertionNode(AT_NON_BOUNDARY, on_success);
  }
  static AssertionNode* AfterNewline(RegExpNode* on_success) {
    return new (on_success->zone()) AssertionNode(AFTER_NEWLINE, on_success);
  }
  virtual void Accept(NodeVisitor* visitor);
  virtual void Emit(RegExpCompiler* compiler, Trace* trace);
  virtual intptr_t EatsAtLeast(intptr_t still_to_find,
                               intptr_t budget,
                               bool not_at_start);
  virtual void GetQuickCheckDetails(QuickCheckDetails* details,
                                    RegExpCompiler* compiler,
                                    intptr_t filled_in,
                                    bool not_at_start);
  virtual void FillInBMInfo(intptr_t offset,
                            intptr_t budget,
                            BoyerMooreLookahead* bm,
                            bool not_at_start);
  AssertionType assertion_type() { return assertion_type_; }

 private:
  void EmitBoundaryCheck(RegExpCompiler* compiler, Trace* trace);
  enum IfPrevious { kIsNonWord, kIsWord };
  void BacktrackIfPrevious(RegExpCompiler* compiler,
                           Trace* trace,
                           IfPrevious backtrack_if_previous);
  AssertionNode(AssertionType t, RegExpNode* on_success)
      : SeqRegExpNode(on_success), assertion_type_(t) {}
  AssertionType assertion_type_;
};

class BackReferenceNode : public SeqRegExpNode {
 public:
  BackReferenceNode(intptr_t start_reg,
                    intptr_t end_reg,
                    RegExpFlags flags,
                    bool read_backward,
                    RegExpNode* on_success)
      : SeqRegExpNode(on_success),
        start_reg_(start_reg),
        end_reg_(end_reg),
        flags_(flags),
        read_backward_(read_backward) {}
  virtual void Accept(NodeVisitor* visitor);
  intptr_t start_register() { return start_reg_; }
  intptr_t end_register() { return end_reg_; }
  bool read_backward() { return read_backward_; }
  virtual void Emit(RegExpCompiler* compiler, Trace* trace);
  virtual intptr_t EatsAtLeast(intptr_t still_to_find,
                               intptr_t recursion_depth,
                               bool not_at_start);
  virtual void GetQuickCheckDetails(QuickCheckDetails* details,
                                    RegExpCompiler* compiler,
                                    intptr_t characters_filled_in,
                                    bool not_at_start) {
    return;
  }
  virtual void FillInBMInfo(intptr_t offset,
                            intptr_t budget,
                            BoyerMooreLookahead* bm,
                            bool not_at_start);

 private:
  intptr_t start_reg_;
  intptr_t end_reg_;
  RegExpFlags flags_;
  bool read_backward_;
};

class EndNode : public RegExpNode {
 public:
  enum Action { ACCEPT, BACKTRACK, NEGATIVE_SUBMATCH_SUCCESS };
  explicit EndNode(Action action, Zone* zone)
      : RegExpNode(zone), action_(action) {}
  virtual void Accept(NodeVisitor* visitor);
  virtual void Emit(RegExpCompiler* compiler, Trace* trace);
  virtual intptr_t EatsAtLeast(intptr_t still_to_find,
                               intptr_t recursion_depth,
                               bool not_at_start) {
    return 0;
  }
  virtual void GetQuickCheckDetails(QuickCheckDetails* details,
                                    RegExpCompiler* compiler,
                                    intptr_t characters_filled_in,
                                    bool not_at_start) {
    // Returning 0 from EatsAtLeast should ensure we never get here.
    UNREACHABLE();
  }
  virtual void FillInBMInfo(intptr_t offset,
                            intptr_t budget,
                            BoyerMooreLookahead* bm,
                            bool not_at_start) {
    // Returning 0 from EatsAtLeast should ensure we never get here.
    UNREACHABLE();
  }

 private:
  Action action_;
};

class NegativeSubmatchSuccess : public EndNode {
 public:
  NegativeSubmatchSuccess(intptr_t stack_pointer_reg,
                          intptr_t position_reg,
                          intptr_t clear_capture_count,
                          intptr_t clear_capture_start,
                          Zone* zone)
      : EndNode(NEGATIVE_SUBMATCH_SUCCESS, zone),
        stack_pointer_register_(stack_pointer_reg),
        current_position_register_(position_reg),
        clear_capture_count_(clear_capture_count),
        clear_capture_start_(clear_capture_start) {}
  virtual void Emit(RegExpCompiler* compiler, Trace* trace);

 private:
  intptr_t stack_pointer_register_;
  intptr_t current_position_register_;
  intptr_t clear_capture_count_;
  intptr_t clear_capture_start_;
};

class Guard : public ZoneAllocated {
 public:
  enum Relation { LT, GEQ };
  Guard(intptr_t reg, Relation op, intptr_t value)
      : reg_(reg), op_(op), value_(value) {}
  intptr_t reg() { return reg_; }
  Relation op() { return op_; }
  intptr_t value() { return value_; }

 private:
  intptr_t reg_;
  Relation op_;
  intptr_t value_;
};

class GuardedAlternative {
 public:
  explicit GuardedAlternative(RegExpNode* node) : node_(node), guards_(NULL) {}
  void AddGuard(Guard* guard, Zone* zone);
  RegExpNode* node() const { return node_; }
  void set_node(RegExpNode* node) { node_ = node; }
  ZoneGrowableArray<Guard*>* guards() const { return guards_; }

 private:
  RegExpNode* node_;
  ZoneGrowableArray<Guard*>* guards_;

  DISALLOW_ALLOCATION();
};

struct AlternativeGeneration;

class ChoiceNode : public RegExpNode {
 public:
  explicit ChoiceNode(intptr_t expected_size, Zone* zone)
      : RegExpNode(zone),
        alternatives_(new (zone)
                          ZoneGrowableArray<GuardedAlternative>(expected_size)),
        not_at_start_(false),
        being_calculated_(false) {}
  virtual void Accept(NodeVisitor* visitor);
  void AddAlternative(GuardedAlternative node) { alternatives()->Add(node); }
  ZoneGrowableArray<GuardedAlternative>* alternatives() {
    return alternatives_;
  }
  virtual void Emit(RegExpCompiler* compiler, Trace* trace);
  virtual intptr_t EatsAtLeast(intptr_t still_to_find,
                               intptr_t budget,
                               bool not_at_start);
  intptr_t EatsAtLeastHelper(intptr_t still_to_find,
                             intptr_t budget,
                             RegExpNode* ignore_this_node,
                             bool not_at_start);
  virtual void GetQuickCheckDetails(QuickCheckDetails* details,
                                    RegExpCompiler* compiler,
                                    intptr_t characters_filled_in,
                                    bool not_at_start);
  virtual void FillInBMInfo(intptr_t offset,
                            intptr_t budget,
                            BoyerMooreLookahead* bm,
                            bool not_at_start);

  bool being_calculated() { return being_calculated_; }
  bool not_at_start() { return not_at_start_; }
  void set_not_at_start() { not_at_start_ = true; }
  void set_being_calculated(bool b) { being_calculated_ = b; }
  virtual bool try_to_emit_quick_check_for_alternative(bool is_first) {
    return true;
  }
  virtual RegExpNode* FilterOneByte(intptr_t depth);
  virtual bool read_backward() { return false; }

 protected:
  intptr_t GreedyLoopTextLengthForAlternative(
      const GuardedAlternative* alternative);
  ZoneGrowableArray<GuardedAlternative>* alternatives_;

 private:
  friend class Analysis;
  void GenerateGuard(RegExpMacroAssembler* macro_assembler,
                     Guard* guard,
                     Trace* trace);
  intptr_t CalculatePreloadCharacters(RegExpCompiler* compiler,
                                      intptr_t eats_at_least);
  void EmitOutOfLineContinuation(RegExpCompiler* compiler,
                                 Trace* trace,
                                 GuardedAlternative alternative,
                                 AlternativeGeneration* alt_gen,
                                 intptr_t preload_characters,
                                 bool next_expects_preload);
  void SetUpPreLoad(RegExpCompiler* compiler,
                    Trace* current_trace,
                    PreloadState* preloads);
  void AssertGuardsMentionRegisters(Trace* trace);
  intptr_t EmitOptimizedUnanchoredSearch(RegExpCompiler* compiler,
                                         Trace* trace);
  Trace* EmitGreedyLoop(RegExpCompiler* compiler,
                        Trace* trace,
                        AlternativeGenerationList* alt_gens,
                        PreloadState* preloads,
                        GreedyLoopState* greedy_loop_state,
                        intptr_t text_length);
  void EmitChoices(RegExpCompiler* compiler,
                   AlternativeGenerationList* alt_gens,
                   intptr_t first_choice,
                   Trace* trace,
                   PreloadState* preloads);
  // If true, this node is never checked at the start of the input.
  // Allows a new trace to start with at_start() set to false.
  bool not_at_start_;
  bool being_calculated_;
};

class NegativeLookaroundChoiceNode : public ChoiceNode {
 public:
  explicit NegativeLookaroundChoiceNode(GuardedAlternative this_must_fail,
                                        GuardedAlternative then_do_this,
                                        Zone* zone)
      : ChoiceNode(2, zone) {
    AddAlternative(this_must_fail);
    AddAlternative(then_do_this);
  }
  virtual intptr_t EatsAtLeast(intptr_t still_to_find,
                               intptr_t budget,
                               bool not_at_start);
  virtual void GetQuickCheckDetails(QuickCheckDetails* details,
                                    RegExpCompiler* compiler,
                                    intptr_t characters_filled_in,
                                    bool not_at_start);
  virtual void FillInBMInfo(intptr_t offset,
                            intptr_t budget,
                            BoyerMooreLookahead* bm,
                            bool not_at_start) {
    (*alternatives_)[1].node()->FillInBMInfo(offset, budget - 1, bm,
                                             not_at_start);
    if (offset == 0) set_bm_info(not_at_start, bm);
  }
  // For a negative lookahead we don't emit the quick check for the
  // alternative that is expected to fail.  This is because quick check code
  // starts by loading enough characters for the alternative that takes fewest
  // characters, but on a negative lookahead the negative branch did not take
  // part in that calculation (EatsAtLeast) so the assumptions don't hold.
  virtual bool try_to_emit_quick_check_for_alternative(bool is_first) {
    return !is_first;
  }
  virtual RegExpNode* FilterOneByte(intptr_t depth);
};

class LoopChoiceNode : public ChoiceNode {
 public:
  explicit LoopChoiceNode(bool body_can_be_zero_length,
                          bool read_backward,
                          Zone* zone)
      : ChoiceNode(2, zone),
        loop_node_(NULL),
        continue_node_(NULL),
        body_can_be_zero_length_(body_can_be_zero_length),
        read_backward_(read_backward) {}
  void AddLoopAlternative(GuardedAlternative alt);
  void AddContinueAlternative(GuardedAlternative alt);
  virtual void Emit(RegExpCompiler* compiler, Trace* trace);
  virtual intptr_t EatsAtLeast(intptr_t still_to_find,
                               intptr_t budget,
                               bool not_at_start);
  virtual void GetQuickCheckDetails(QuickCheckDetails* details,
                                    RegExpCompiler* compiler,
                                    intptr_t characters_filled_in,
                                    bool not_at_start);
  virtual void FillInBMInfo(intptr_t offset,
                            intptr_t budget,
                            BoyerMooreLookahead* bm,
                            bool not_at_start);
  RegExpNode* loop_node() { return loop_node_; }
  RegExpNode* continue_node() { return continue_node_; }
  bool body_can_be_zero_length() { return body_can_be_zero_length_; }
  virtual bool read_backward() { return read_backward_; }
  virtual void Accept(NodeVisitor* visitor);
  virtual RegExpNode* FilterOneByte(intptr_t depth);

 private:
  // AddAlternative is made private for loop nodes because alternatives
  // should not be added freely, we need to keep track of which node
  // goes back to the node itself.
  void AddAlternative(GuardedAlternative node) {
    ChoiceNode::AddAlternative(node);
  }

  RegExpNode* loop_node_;
  RegExpNode* continue_node_;
  bool body_can_be_zero_length_;
  bool read_backward_;
};

// Improve the speed that we scan for an initial point where a non-anchored
// regexp can match by using a Boyer-Moore-like table. This is done by
// identifying non-greedy non-capturing loops in the nodes that eat any
// character one at a time.  For example in the middle of the regexp
// /foo[\s\S]*?bar/ we find such a loop.  There is also such a loop implicitly
// inserted at the start of any non-anchored regexp.
//
// When we have found such a loop we look ahead in the nodes to find the set of
// characters that can come at given distances. For example for the regexp
// /.?foo/ we know that there are at least 3 characters ahead of us, and the
// sets of characters that can occur are [any, [f, o], [o]]. We find a range in
// the lookahead info where the set of characters is reasonably constrained. In
// our example this is from index 1 to 2 (0 is not constrained). We can now
// look 3 characters ahead and if we don't find one of [f, o] (the union of
// [f, o] and [o]) then we can skip forwards by the range size (in this case 2).
//
// For Unicode input strings we do the same, but modulo 128.
//
// We also look at the first string fed to the regexp and use that to get a hint
// of the character frequencies in the inputs. This affects the assessment of
// whether the set of characters is 'reasonably constrained'.
//
// We also have another lookahead mechanism (called quick check in the code),
// which uses a wide load of multiple characters followed by a mask and compare
// to determine whether a match is possible at this point.
enum ContainedInLattice {
  kNotYet = 0,
  kLatticeIn = 1,
  kLatticeOut = 2,
  kLatticeUnknown = 3  // Can also mean both in and out.
};

inline ContainedInLattice Combine(ContainedInLattice a, ContainedInLattice b) {
  return static_cast<ContainedInLattice>(a | b);
}

ContainedInLattice AddRange(ContainedInLattice a,
                            const intptr_t* ranges,
                            intptr_t ranges_size,
                            Interval new_range);

class BoyerMoorePositionInfo : public ZoneAllocated {
 public:
  explicit BoyerMoorePositionInfo(Zone* zone)
      : map_(new (zone) ZoneGrowableArray<bool>(kMapSize)),
        map_count_(0),
        w_(kNotYet),
        s_(kNotYet),
        d_(kNotYet),
        surrogate_(kNotYet) {
    for (intptr_t i = 0; i < kMapSize; i++) {
      map_->Add(false);
    }
  }

  bool& at(intptr_t i) { return (*map_)[i]; }

  static const intptr_t kMapSize = 128;
  static const intptr_t kMask = kMapSize - 1;

  intptr_t map_count() const { return map_count_; }

  void Set(intptr_t character);
  void SetInterval(const Interval& interval);
  void SetAll();
  bool is_non_word() { return w_ == kLatticeOut; }
  bool is_word() { return w_ == kLatticeIn; }

 private:
  ZoneGrowableArray<bool>* map_;
  intptr_t map_count_;            // Number of set bits in the map.
  ContainedInLattice w_;          // The \w character class.
  ContainedInLattice s_;          // The \s character class.
  ContainedInLattice d_;          // The \d character class.
  ContainedInLattice surrogate_;  // Surrogate UTF-16 code units.
};

class BoyerMooreLookahead : public ZoneAllocated {
 public:
  BoyerMooreLookahead(intptr_t length, RegExpCompiler* compiler, Zone* Zone);

  intptr_t length() { return length_; }
  intptr_t max_char() { return max_char_; }
  RegExpCompiler* compiler() { return compiler_; }

  intptr_t Count(intptr_t map_number) {
    return bitmaps_->At(map_number)->map_count();
  }

  BoyerMoorePositionInfo* at(intptr_t i) { return bitmaps_->At(i); }

  void Set(intptr_t map_number, intptr_t character) {
    if (character > max_char_) return;
    BoyerMoorePositionInfo* info = bitmaps_->At(map_number);
    info->Set(character);
  }

  void SetInterval(intptr_t map_number, const Interval& interval) {
    if (interval.from() > max_char_) return;
    BoyerMoorePositionInfo* info = bitmaps_->At(map_number);
    if (interval.to() > max_char_) {
      info->SetInterval(Interval(interval.from(), max_char_));
    } else {
      info->SetInterval(interval);
    }
  }

  void SetAll(intptr_t map_number) { bitmaps_->At(map_number)->SetAll(); }

  void SetRest(intptr_t from_map) {
    for (intptr_t i = from_map; i < length_; i++)
      SetAll(i);
  }
  void EmitSkipInstructions(RegExpMacroAssembler* masm);

 private:
  // This is the value obtained by EatsAtLeast.  If we do not have at least this
  // many characters left in the sample string then the match is bound to fail.
  // Therefore it is OK to read a character this far ahead of the current match
  // point.
  intptr_t length_;
  RegExpCompiler* compiler_;
  // 0xff for Latin1, 0xffff for UTF-16.
  intptr_t max_char_;
  ZoneGrowableArray<BoyerMoorePositionInfo*>* bitmaps_;

  intptr_t GetSkipTable(intptr_t min_lookahead,
                        intptr_t max_lookahead,
                        const TypedData& boolean_skip_table);
  bool FindWorthwhileInterval(intptr_t* from, intptr_t* to);
  intptr_t FindBestInterval(intptr_t max_number_of_chars,
                            intptr_t old_biggest_points,
                            intptr_t* from,
                            intptr_t* to);
};

// There are many ways to generate code for a node.  This class encapsulates
// the current way we should be generating.  In other words it encapsulates
// the current state of the code generator.  The effect of this is that we
// generate code for paths that the matcher can take through the regular
// expression.  A given node in the regexp can be code-generated several times
// as it can be part of several traces.  For example for the regexp:
// /foo(bar|ip)baz/ the code to match baz will be generated twice, once as part
// of the foo-bar-baz trace and once as part of the foo-ip-baz trace.  The code
// to match foo is generated only once (the traces have a common prefix).  The
// code to store the capture is deferred and generated (twice) after the places
// where baz has been matched.
class Trace {
 public:
  // A value for a property that is either known to be true, know to be false,
  // or not known.
  enum TriBool { UNKNOWN = -1, FALSE_VALUE = 0, TRUE_VALUE = 1 };

  class DeferredAction {
   public:
    DeferredAction(ActionNode::ActionType action_type, intptr_t reg)
        : action_type_(action_type), reg_(reg), next_(NULL) {}
    DeferredAction* next() { return next_; }
    bool Mentions(intptr_t reg);
    intptr_t reg() { return reg_; }
    ActionNode::ActionType action_type() { return action_type_; }

   private:
    ActionNode::ActionType action_type_;
    intptr_t reg_;
    DeferredAction* next_;
    friend class Trace;

    DISALLOW_ALLOCATION();
  };

  class DeferredCapture : public DeferredAction {
   public:
    DeferredCapture(intptr_t reg, bool is_capture, Trace* trace)
        : DeferredAction(ActionNode::STORE_POSITION, reg),
          cp_offset_(trace->cp_offset()),
          is_capture_(is_capture) {}
    intptr_t cp_offset() { return cp_offset_; }
    bool is_capture() { return is_capture_; }

   private:
    intptr_t cp_offset_;
    bool is_capture_;
    void set_cp_offset(intptr_t cp_offset) { cp_offset_ = cp_offset; }
  };

  class DeferredSetRegister : public DeferredAction {
   public:
    DeferredSetRegister(intptr_t reg, intptr_t value)
        : DeferredAction(ActionNode::SET_REGISTER, reg), value_(value) {}
    intptr_t value() { return value_; }

   private:
    intptr_t value_;
  };

  class DeferredClearCaptures : public DeferredAction {
   public:
    explicit DeferredClearCaptures(Interval range)
        : DeferredAction(ActionNode::CLEAR_CAPTURES, -1), range_(range) {}
    Interval range() { return range_; }

   private:
    Interval range_;
  };

  class DeferredIncrementRegister : public DeferredAction {
   public:
    explicit DeferredIncrementRegister(intptr_t reg)
        : DeferredAction(ActionNode::INCREMENT_REGISTER, reg) {}
  };

  Trace()
      : cp_offset_(0),
        actions_(NULL),
        backtrack_(NULL),
        stop_node_(NULL),
        loop_label_(NULL),
        characters_preloaded_(0),
        bound_checked_up_to_(0),
        flush_budget_(100),
        at_start_(UNKNOWN) {}

  // End the trace.  This involves flushing the deferred actions in the trace
  // and pushing a backtrack location onto the backtrack stack.  Once this is
  // done we can start a new trace or go to one that has already been
  // generated.
  void Flush(RegExpCompiler* compiler, RegExpNode* successor);
  intptr_t cp_offset() { return cp_offset_; }
  DeferredAction* actions() { return actions_; }
  // A trivial trace is one that has no deferred actions or other state that
  // affects the assumptions used when generating code.  There is no recorded
  // backtrack location in a trivial trace, so with a trivial trace we will
  // generate code that, on a failure to match, gets the backtrack location
  // from the backtrack stack rather than using a direct jump instruction.  We
  // always start code generation with a trivial trace and non-trivial traces
  // are created as we emit code for nodes or add to the list of deferred
  // actions in the trace.  The location of the code generated for a node using
  // a trivial trace is recorded in a label in the node so that gotos can be
  // generated to that code.
  bool is_trivial() {
    return backtrack_ == NULL && actions_ == NULL && cp_offset_ == 0 &&
           characters_preloaded_ == 0 && bound_checked_up_to_ == 0 &&
           quick_check_performed_.characters() == 0 && at_start_ == UNKNOWN;
  }
  TriBool at_start() { return at_start_; }
  void set_at_start(TriBool at_start) { at_start_ = at_start; }
  BlockLabel* backtrack() { return backtrack_; }
  BlockLabel* loop_label() { return loop_label_; }
  RegExpNode* stop_node() { return stop_node_; }
  intptr_t characters_preloaded() { return characters_preloaded_; }
  intptr_t bound_checked_up_to() { return bound_checked_up_to_; }
  intptr_t flush_budget() { return flush_budget_; }
  QuickCheckDetails* quick_check_performed() { return &quick_check_performed_; }
  bool mentions_reg(intptr_t reg);
  // Returns true if a deferred position store exists to the specified
  // register and stores the offset in the out-parameter.  Otherwise
  // returns false.
  bool GetStoredPosition(intptr_t reg, intptr_t* cp_offset);
  // These set methods and AdvanceCurrentPositionInTrace should be used only on
  // new traces - the intention is that traces are immutable after creation.
  void add_action(DeferredAction* new_action) {
    ASSERT(new_action->next_ == NULL);
    new_action->next_ = actions_;
    actions_ = new_action;
  }
  void set_backtrack(BlockLabel* backtrack) { backtrack_ = backtrack; }
  void set_stop_node(RegExpNode* node) { stop_node_ = node; }
  void set_loop_label(BlockLabel* label) { loop_label_ = label; }
  void set_characters_preloaded(intptr_t count) {
    characters_preloaded_ = count;
  }
  void set_bound_checked_up_to(intptr_t to) { bound_checked_up_to_ = to; }
  void set_flush_budget(intptr_t to) { flush_budget_ = to; }
  void set_quick_check_performed(QuickCheckDetails* d) {
    quick_check_performed_ = *d;
  }
  void InvalidateCurrentCharacter();
  void AdvanceCurrentPositionInTrace(intptr_t by, RegExpCompiler* compiler);

 private:
  intptr_t FindAffectedRegisters(OutSet* affected_registers, Zone* zone);
  void PerformDeferredActions(RegExpMacroAssembler* macro,
                              intptr_t max_register,
                              const OutSet& affected_registers,
                              OutSet* registers_to_pop,
                              OutSet* registers_to_clear,
                              Zone* zone);
  void RestoreAffectedRegisters(RegExpMacroAssembler* macro,
                                intptr_t max_register,
                                const OutSet& registers_to_pop,
                                const OutSet& registers_to_clear);
  intptr_t cp_offset_;
  DeferredAction* actions_;
  BlockLabel* backtrack_;
  RegExpNode* stop_node_;
  BlockLabel* loop_label_;
  intptr_t characters_preloaded_;
  intptr_t bound_checked_up_to_;
  QuickCheckDetails quick_check_performed_;
  intptr_t flush_budget_;
  TriBool at_start_;

  DISALLOW_ALLOCATION();
};

class GreedyLoopState {
 public:
  explicit GreedyLoopState(bool not_at_start);

  BlockLabel* label() { return &label_; }
  Trace* counter_backtrack_trace() { return &counter_backtrack_trace_; }

 private:
  BlockLabel label_;
  Trace counter_backtrack_trace_;
};

struct PreloadState {
  static const intptr_t kEatsAtLeastNotYetInitialized = -1;
  bool preload_is_current_;
  bool preload_has_checked_bounds_;
  intptr_t preload_characters_;
  intptr_t eats_at_least_;
  void init() { eats_at_least_ = kEatsAtLeastNotYetInitialized; }

  DISALLOW_ALLOCATION();
};

class NodeVisitor : public ValueObject {
 public:
  virtual ~NodeVisitor() {}
#define DECLARE_VISIT(Type) virtual void Visit##Type(Type##Node* that) = 0;
  FOR_EACH_NODE_TYPE(DECLARE_VISIT)
#undef DECLARE_VISIT
  virtual void VisitLoopChoice(LoopChoiceNode* that) { VisitChoice(that); }
};

// Assertion propagation moves information about assertions such as
// \b to the affected nodes.  For instance, in /.\b./ information must
// be propagated to the first '.' that whatever follows needs to know
// if it matched a word or a non-word, and to the second '.' that it
// has to check if it succeeds a word or non-word.  In this case the
// result will be something like:
//
//   +-------+        +------------+
//   |   .   |        |      .     |
//   +-------+  --->  +------------+
//   | word? |        | check word |
//   +-------+        +------------+
class Analysis : public NodeVisitor {
 public:
  explicit Analysis(bool is_one_byte)
      : is_one_byte_(is_one_byte), error_message_(NULL) {}
  void EnsureAnalyzed(RegExpNode* node);

#define DECLARE_VISIT(Type) virtual void Visit##Type(Type##Node* that);
  FOR_EACH_NODE_TYPE(DECLARE_VISIT)
#undef DECLARE_VISIT
  virtual void VisitLoopChoice(LoopChoiceNode* that);

  bool has_failed() { return error_message_ != NULL; }
  const char* error_message() {
    ASSERT(error_message_ != NULL);
    return error_message_;
  }
  void fail(const char* error_message) { error_message_ = error_message; }

 private:
  bool is_one_byte_;
  const char* error_message_;

  DISALLOW_IMPLICIT_CONSTRUCTORS(Analysis);
};

struct RegExpCompileData : public ZoneAllocated {
  RegExpCompileData()
      : tree(NULL),
        node(NULL),
        simple(true),
        contains_anchor(false),
        capture_name_map(Array::Handle(Array::null())),
        error(String::Handle(String::null())),
        capture_count(0) {}
  RegExpTree* tree;
  RegExpNode* node;
  bool simple;
  bool contains_anchor;
  Array& capture_name_map;
  String& error;
  intptr_t capture_count;
};

class RegExpEngine : public AllStatic {
 public:
  struct CompilationResult {
    explicit CompilationResult(const char* error_message)
        : error_message(error_message),
#if !defined(DART_PRECOMPILED_RUNTIME)
          backtrack_goto(NULL),
          graph_entry(NULL),
          num_blocks(-1),
          num_stack_locals(-1),
#endif
          bytecode(NULL),
          num_registers(-1) {
    }

    CompilationResult(TypedData* bytecode, intptr_t num_registers)
        : error_message(NULL),
#if !defined(DART_PRECOMPILED_RUNTIME)
          backtrack_goto(NULL),
          graph_entry(NULL),
          num_blocks(-1),
          num_stack_locals(-1),
#endif
          bytecode(bytecode),
          num_registers(num_registers) {
    }

#if !defined(DART_PRECOMPILED_RUNTIME)
    CompilationResult(IndirectGotoInstr* backtrack_goto,
                      GraphEntryInstr* graph_entry,
                      intptr_t num_blocks,
                      intptr_t num_stack_locals,
                      intptr_t num_registers)
        : error_message(NULL),
          backtrack_goto(backtrack_goto),
          graph_entry(graph_entry),
          num_blocks(num_blocks),
          num_stack_locals(num_stack_locals),
          bytecode(NULL) {}
#endif

    const char* error_message;

    NOT_IN_PRECOMPILED(IndirectGotoInstr* backtrack_goto);
    NOT_IN_PRECOMPILED(GraphEntryInstr* graph_entry);
    NOT_IN_PRECOMPILED(const intptr_t num_blocks);
    NOT_IN_PRECOMPILED(const intptr_t num_stack_locals);

    TypedData* bytecode;
    intptr_t num_registers;
  };

#if !defined(DART_PRECOMPILED_RUNTIME)
  static CompilationResult CompileIR(
      RegExpCompileData* input,
      const ParsedFunction* parsed_function,
      const ZoneGrowableArray<const ICData*>& ic_data_array,
      intptr_t osr_id);
#endif

  static CompilationResult CompileBytecode(RegExpCompileData* data,
                                           const RegExp& regexp,
                                           bool is_one_byte,
                                           bool sticky,
                                           Zone* zone);

  static RawRegExp* CreateRegExp(Thread* thread,
                                 const String& pattern,
                                 RegExpFlags flags);

  static void DotPrint(const char* label, RegExpNode* node, bool ignore_case);
};

}  // namespace dart

#endif  // RUNTIME_VM_REGEXP_H_
