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

#include "vm/regexp.h"

#include <memory>

#include "platform/splay-tree-inl.h"
#include "platform/unicode.h"

#include "unicode/uniset.h"

#include "vm/dart_entry.h"
#include "vm/regexp_assembler.h"
#include "vm/regexp_assembler_bytecode.h"
#include "vm/regexp_assembler_ir.h"
#include "vm/regexp_ast.h"
#include "vm/symbols.h"
#include "vm/thread.h"
#include "vm/unibrow-inl.h"

#define Z (zone())

namespace dart {

// Default to generating optimized regexp code.
static const bool kRegexpOptimization = true;

// More makes code generation slower, less makes V8 benchmark score lower.
static const intptr_t kMaxLookaheadForBoyerMoore = 8;

ContainedInLattice AddRange(ContainedInLattice containment,
                            const int32_t* ranges,
                            intptr_t ranges_length,
                            Interval new_range) {
  ASSERT((ranges_length & 1) == 1);
  ASSERT(ranges[ranges_length - 1] == Utf::kMaxCodePoint + 1);
  if (containment == kLatticeUnknown) return containment;
  bool inside = false;
  int32_t last = 0;
  for (intptr_t i = 0; i < ranges_length;
       inside = !inside, last = ranges[i], i++) {
    // Consider the range from last to ranges[i].
    // We haven't got to the new range yet.
    if (ranges[i] <= new_range.from()) continue;
    // New range is wholly inside last-ranges[i].  Note that new_range.to() is
    // inclusive, but the values in ranges are not.
    if (last <= new_range.from() && new_range.to() < ranges[i]) {
      return Combine(containment, inside ? kLatticeIn : kLatticeOut);
    }
    return kLatticeUnknown;
  }
  return containment;
}

// -------------------------------------------------------------------
// Implementation of the Irregexp regular expression engine.
//
// The Irregexp regular expression engine is intended to be a complete
// implementation of ECMAScript regular expressions.  It generates
// IR code that is subsequently compiled to native code.

//   The Irregexp regexp engine is structured in three steps.
//   1) The parser generates an abstract syntax tree.  See regexp_ast.cc.
//   2) From the AST a node network is created.  The nodes are all
//      subclasses of RegExpNode.  The nodes represent states when
//      executing a regular expression.  Several optimizations are
//      performed on the node network.
//   3) From the nodes we generate IR instructions that can actually
//      execute the regular expression (perform the search).  The
//      code generation step is described in more detail below.

// Code generation.
//
//   The nodes are divided into four main categories.
//   * Choice nodes
//        These represent places where the regular expression can
//        match in more than one way.  For example on entry to an
//        alternation (foo|bar) or a repetition (*, +, ? or {}).
//   * Action nodes
//        These represent places where some action should be
//        performed.  Examples include recording the current position
//        in the input string to a register (in order to implement
//        captures) or other actions on register for example in order
//        to implement the counters needed for {} repetitions.
//   * Matching nodes
//        These attempt to match some element part of the input string.
//        Examples of elements include character classes, plain strings
//        or back references.
//   * End nodes
//        These are used to implement the actions required on finding
//        a successful match or failing to find a match.
//
//   The code generated maintains some state as it runs.  This consists of the
//   following elements:
//
//   * The capture registers.  Used for string captures.
//   * Other registers.  Used for counters etc.
//   * The current position.
//   * The stack of backtracking information.  Used when a matching node
//     fails to find a match and needs to try an alternative.
//
// Conceptual regular expression execution model:
//
//   There is a simple conceptual model of regular expression execution
//   which will be presented first.  The actual code generated is a more
//   efficient simulation of the simple conceptual model:
//
//   * Choice nodes are implemented as follows:
//     For each choice except the last {
//       push current position
//       push backtrack code location
//       <generate code to test for choice>
//       backtrack code location:
//       pop current position
//     }
//     <generate code to test for last choice>
//
//   * Actions nodes are generated as follows
//     <push affected registers on backtrack stack>
//     <generate code to perform action>
//     push backtrack code location
//     <generate code to test for following nodes>
//     backtrack code location:
//     <pop affected registers to restore their state>
//     <pop backtrack location from stack and go to it>
//
//   * Matching nodes are generated as follows:
//     if input string matches at current position
//       update current position
//       <generate code to test for following nodes>
//     else
//       <pop backtrack location from stack and go to it>
//
//   Thus it can be seen that the current position is saved and restored
//   by the choice nodes, whereas the registers are saved and restored by
//   by the action nodes that manipulate them.
//
//   The other interesting aspect of this model is that nodes are generated
//   at the point where they are needed by a recursive call to Emit().  If
//   the node has already been code generated then the Emit() call will
//   generate a jump to the previously generated code instead.  In order to
//   limit recursion it is possible for the Emit() function to put the node
//   on a work list for later generation and instead generate a jump.  The
//   destination of the jump is resolved later when the code is generated.
//
// Actual regular expression code generation.
//
//   Code generation is actually more complicated than the above.  In order
//   to improve the efficiency of the generated code some optimizations are
//   performed
//
//   * Choice nodes have 1-character lookahead.
//     A choice node looks at the following character and eliminates some of
//     the choices immediately based on that character.  This is not yet
//     implemented.
//   * Simple greedy loops store reduced backtracking information.
//     A quantifier like /.*foo/m will greedily match the whole input.  It will
//     then need to backtrack to a point where it can match "foo".  The naive
//     implementation of this would push each character position onto the
//     backtracking stack, then pop them off one by one.  This would use space
//     proportional to the length of the input string.  However since the "."
//     can only match in one way and always has a constant length (in this case
//     of 1) it suffices to store the current position on the top of the stack
//     once.  Matching now becomes merely incrementing the current position and
//     backtracking becomes decrementing the current position and checking the
//     result against the stored current position.  This is faster and saves
//     space.
//   * The current state is virtualized.
//     This is used to defer expensive operations until it is clear that they
//     are needed and to generate code for a node more than once, allowing
//     specialized an efficient versions of the code to be created. This is
//     explained in the section below.
//
// Execution state virtualization.
//
//   Instead of emitting code, nodes that manipulate the state can record their
//   manipulation in an object called the Trace.  The Trace object can record a
//   current position offset, an optional backtrack code location on the top of
//   the virtualized backtrack stack and some register changes.  When a node is
//   to be emitted it can flush the Trace or update it.  Flushing the Trace
//   will emit code to bring the actual state into line with the virtual state.
//   Avoiding flushing the state can postpone some work (e.g. updates of capture
//   registers).  Postponing work can save time when executing the regular
//   expression since it may be found that the work never has to be done as a
//   failure to match can occur.  In addition it is much faster to jump to a
//   known backtrack code location than it is to pop an unknown backtrack
//   location from the stack and jump there.
//
//   The virtual state found in the Trace affects code generation.  For example
//   the virtual state contains the difference between the actual current
//   position and the virtual current position, and matching code needs to use
//   this offset to attempt a match in the correct location of the input
//   string.  Therefore code generated for a non-trivial trace is specialized
//   to that trace.  The code generator therefore has the ability to generate
//   code for each node several times.  In order to limit the size of the
//   generated code there is an arbitrary limit on how many specialized sets of
//   code may be generated for a given node.  If the limit is reached, the
//   trace is flushed and a generic version of the code for a node is emitted.
//   This is subsequently used for that node.  The code emitted for non-generic
//   trace is not recorded in the node and so it cannot currently be reused in
//   the event that code generation is requested for an identical trace.

void RegExpTree::AppendToText(RegExpText* text) {
  UNREACHABLE();
}

void RegExpAtom::AppendToText(RegExpText* text) {
  text->AddElement(TextElement::Atom(this));
}

void RegExpCharacterClass::AppendToText(RegExpText* text) {
  text->AddElement(TextElement::CharClass(this));
}

void RegExpText::AppendToText(RegExpText* text) {
  for (intptr_t i = 0; i < elements()->length(); i++)
    text->AddElement((*elements())[i]);
}

TextElement TextElement::Atom(RegExpAtom* atom) {
  return TextElement(ATOM, atom);
}

TextElement TextElement::CharClass(RegExpCharacterClass* char_class) {
  return TextElement(CHAR_CLASS, char_class);
}

intptr_t TextElement::length() const {
  switch (text_type()) {
    case ATOM:
      return atom()->length();

    case CHAR_CLASS:
      return 1;
  }
  UNREACHABLE();
  return 0;
}

class FrequencyCollator : public ValueObject {
 public:
  FrequencyCollator() : total_samples_(0) {
    for (intptr_t i = 0; i < RegExpMacroAssembler::kTableSize; i++) {
      frequencies_[i] = CharacterFrequency(i);
    }
  }

  void CountCharacter(intptr_t character) {
    intptr_t index = (character & RegExpMacroAssembler::kTableMask);
    frequencies_[index].Increment();
    total_samples_++;
  }

  // Does not measure in percent, but rather per-128 (the table size from the
  // regexp macro assembler).
  intptr_t Frequency(intptr_t in_character) {
    ASSERT((in_character & RegExpMacroAssembler::kTableMask) == in_character);
    if (total_samples_ < 1) return 1;  // Division by zero.
    intptr_t freq_in_per128 =
        (frequencies_[in_character].counter() * 128) / total_samples_;
    return freq_in_per128;
  }

 private:
  class CharacterFrequency {
   public:
    CharacterFrequency() : counter_(0), character_(-1) {}
    explicit CharacterFrequency(intptr_t character)
        : counter_(0), character_(character) {}

    void Increment() { counter_++; }
    intptr_t counter() { return counter_; }
    intptr_t character() { return character_; }

   private:
    intptr_t counter_;
    intptr_t character_;

    DISALLOW_ALLOCATION();
  };

 private:
  CharacterFrequency frequencies_[RegExpMacroAssembler::kTableSize];
  intptr_t total_samples_;
};

class RegExpCompiler : public ValueObject {
 public:
  RegExpCompiler(intptr_t capture_count, bool is_one_byte);

  intptr_t AllocateRegister() { return next_register_++; }

  // Lookarounds to match lone surrogates for unicode character class matches
  // are never nested. We can therefore reuse registers.
  intptr_t UnicodeLookaroundStackRegister() {
    if (unicode_lookaround_stack_register_ == kNoRegister) {
      unicode_lookaround_stack_register_ = AllocateRegister();
    }
    return unicode_lookaround_stack_register_;
  }

  intptr_t UnicodeLookaroundPositionRegister() {
    if (unicode_lookaround_position_register_ == kNoRegister) {
      unicode_lookaround_position_register_ = AllocateRegister();
    }
    return unicode_lookaround_position_register_;
  }

#if !defined(DART_PRECOMPILED_RUNTIME)
  RegExpEngine::CompilationResult Assemble(IRRegExpMacroAssembler* assembler,
                                           RegExpNode* start,
                                           intptr_t capture_count,
                                           const String& pattern);
#endif

  RegExpEngine::CompilationResult Assemble(
      BytecodeRegExpMacroAssembler* assembler,
      RegExpNode* start,
      intptr_t capture_count,
      const String& pattern);

  inline void AddWork(RegExpNode* node) { work_list_->Add(node); }

  static const intptr_t kImplementationOffset = 0;
  static const intptr_t kNumberOfRegistersOffset = 0;
  static const intptr_t kCodeOffset = 1;

  RegExpMacroAssembler* macro_assembler() { return macro_assembler_; }
  EndNode* accept() { return accept_; }

  static const intptr_t kMaxRecursion = 100;
  inline intptr_t recursion_depth() { return recursion_depth_; }
  inline void IncrementRecursionDepth() { recursion_depth_++; }
  inline void DecrementRecursionDepth() { recursion_depth_--; }

  void SetRegExpTooBig() { reg_exp_too_big_ = true; }

  inline bool one_byte() const { return is_one_byte_; }
  bool read_backward() { return read_backward_; }
  void set_read_backward(bool value) { read_backward_ = value; }
  FrequencyCollator* frequency_collator() { return &frequency_collator_; }

  intptr_t current_expansion_factor() { return current_expansion_factor_; }
  void set_current_expansion_factor(intptr_t value) {
    current_expansion_factor_ = value;
  }

  Zone* zone() const { return zone_; }

  static const intptr_t kNoRegister = -1;

 private:
  EndNode* accept_;
  intptr_t next_register_;
  intptr_t unicode_lookaround_stack_register_;
  intptr_t unicode_lookaround_position_register_;
  ZoneGrowableArray<RegExpNode*>* work_list_;
  intptr_t recursion_depth_;
  RegExpMacroAssembler* macro_assembler_;
  bool is_one_byte_;
  bool reg_exp_too_big_;
  bool read_backward_;
  intptr_t current_expansion_factor_;
  FrequencyCollator frequency_collator_;
  Zone* zone_;
};

class RecursionCheck : public ValueObject {
 public:
  explicit RecursionCheck(RegExpCompiler* compiler) : compiler_(compiler) {
    compiler->IncrementRecursionDepth();
  }
  ~RecursionCheck() { compiler_->DecrementRecursionDepth(); }

 private:
  RegExpCompiler* compiler_;
};

static RegExpEngine::CompilationResult IrregexpRegExpTooBig() {
  return RegExpEngine::CompilationResult("RegExp too big");
}

// Attempts to compile the regexp using an Irregexp code generator.  Returns
// a fixed array or a null handle depending on whether it succeeded.
RegExpCompiler::RegExpCompiler(intptr_t capture_count, bool is_one_byte)
    : next_register_(2 * (capture_count + 1)),
      unicode_lookaround_stack_register_(kNoRegister),
      unicode_lookaround_position_register_(kNoRegister),
      work_list_(NULL),
      recursion_depth_(0),
      is_one_byte_(is_one_byte),
      reg_exp_too_big_(false),
      read_backward_(false),
      current_expansion_factor_(1),
      zone_(Thread::Current()->zone()) {
  accept_ = new (Z) EndNode(EndNode::ACCEPT, Z);
}

#if !defined(DART_PRECOMPILED_RUNTIME)
RegExpEngine::CompilationResult RegExpCompiler::Assemble(
    IRRegExpMacroAssembler* macro_assembler,
    RegExpNode* start,
    intptr_t capture_count,
    const String& pattern) {
  macro_assembler->set_slow_safe(false /* use_slow_safe_regexp_compiler */);
  macro_assembler_ = macro_assembler;

  ZoneGrowableArray<RegExpNode*> work_list(0);
  work_list_ = &work_list;
  BlockLabel fail;
  macro_assembler_->PushBacktrack(&fail);
  Trace new_trace;
  start->Emit(this, &new_trace);
  macro_assembler_->BindBlock(&fail);
  macro_assembler_->Fail();
  while (!work_list.is_empty()) {
    work_list.RemoveLast()->Emit(this, &new_trace);
  }
  if (reg_exp_too_big_) return IrregexpRegExpTooBig();

  macro_assembler->GenerateBacktrackBlock();
  macro_assembler->FinalizeRegistersArray();

  return RegExpEngine::CompilationResult(
      macro_assembler->backtrack_goto(), macro_assembler->graph_entry(),
      macro_assembler->num_blocks(), macro_assembler->num_stack_locals(),
      next_register_);
}
#endif

RegExpEngine::CompilationResult RegExpCompiler::Assemble(
    BytecodeRegExpMacroAssembler* macro_assembler,
    RegExpNode* start,
    intptr_t capture_count,
    const String& pattern) {
  macro_assembler->set_slow_safe(false /* use_slow_safe_regexp_compiler */);
  macro_assembler_ = macro_assembler;

  ZoneGrowableArray<RegExpNode*> work_list(0);
  work_list_ = &work_list;
  BlockLabel fail;
  macro_assembler_->PushBacktrack(&fail);
  Trace new_trace;
  start->Emit(this, &new_trace);
  macro_assembler_->BindBlock(&fail);
  macro_assembler_->Fail();
  while (!work_list.is_empty()) {
    work_list.RemoveLast()->Emit(this, &new_trace);
  }
  if (reg_exp_too_big_) return IrregexpRegExpTooBig();

  TypedData& bytecode = TypedData::ZoneHandle(macro_assembler->GetBytecode());
  return RegExpEngine::CompilationResult(&bytecode, next_register_);
}

bool Trace::DeferredAction::Mentions(intptr_t that) {
  if (action_type() == ActionNode::CLEAR_CAPTURES) {
    Interval range = static_cast<DeferredClearCaptures*>(this)->range();
    return range.Contains(that);
  } else {
    return reg() == that;
  }
}

bool Trace::mentions_reg(intptr_t reg) {
  for (DeferredAction* action = actions_; action != NULL;
       action = action->next()) {
    if (action->Mentions(reg)) return true;
  }
  return false;
}

bool Trace::GetStoredPosition(intptr_t reg, intptr_t* cp_offset) {
  ASSERT(*cp_offset == 0);
  for (DeferredAction* action = actions_; action != NULL;
       action = action->next()) {
    if (action->Mentions(reg)) {
      if (action->action_type() == ActionNode::STORE_POSITION) {
        *cp_offset = static_cast<DeferredCapture*>(action)->cp_offset();
        return true;
      } else {
        return false;
      }
    }
  }
  return false;
}

// This is called as we come into a loop choice node and some other tricky
// nodes.  It normalizes the state of the code generator to ensure we can
// generate generic code.
intptr_t Trace::FindAffectedRegisters(OutSet* affected_registers, Zone* zone) {
  intptr_t max_register = RegExpCompiler::kNoRegister;
  for (DeferredAction* action = actions_; action != NULL;
       action = action->next()) {
    if (action->action_type() == ActionNode::CLEAR_CAPTURES) {
      Interval range = static_cast<DeferredClearCaptures*>(action)->range();
      for (intptr_t i = range.from(); i <= range.to(); i++)
        affected_registers->Set(i, zone);
      if (range.to() > max_register) max_register = range.to();
    } else {
      affected_registers->Set(action->reg(), zone);
      if (action->reg() > max_register) max_register = action->reg();
    }
  }
  return max_register;
}

void Trace::RestoreAffectedRegisters(RegExpMacroAssembler* assembler,
                                     intptr_t max_register,
                                     const OutSet& registers_to_pop,
                                     const OutSet& registers_to_clear) {
  for (intptr_t reg = max_register; reg >= 0; reg--) {
    if (registers_to_pop.Get(reg)) {
      assembler->PopRegister(reg);
    } else if (registers_to_clear.Get(reg)) {
      intptr_t clear_to = reg;
      while (reg > 0 && registers_to_clear.Get(reg - 1)) {
        reg--;
      }
      assembler->ClearRegisters(reg, clear_to);
    }
  }
}

void Trace::PerformDeferredActions(RegExpMacroAssembler* assembler,
                                   intptr_t max_register,
                                   const OutSet& affected_registers,
                                   OutSet* registers_to_pop,
                                   OutSet* registers_to_clear,
                                   Zone* zone) {
  for (intptr_t reg = 0; reg <= max_register; reg++) {
    if (!affected_registers.Get(reg)) {
      continue;
    }

    // The chronologically first deferred action in the trace
    // is used to infer the action needed to restore a register
    // to its previous state (or not, if it's safe to ignore it).
    enum DeferredActionUndoType { ACTION_IGNORE, ACTION_RESTORE, ACTION_CLEAR };
    DeferredActionUndoType undo_action = ACTION_IGNORE;

    intptr_t value = 0;
    bool absolute = false;
    bool clear = false;
    static const intptr_t kNoStore = kMinInt32;
    intptr_t store_position = kNoStore;
    // This is a little tricky because we are scanning the actions in reverse
    // historical order (newest first).
    for (DeferredAction* action = actions_; action != NULL;
         action = action->next()) {
      if (action->Mentions(reg)) {
        switch (action->action_type()) {
          case ActionNode::SET_REGISTER: {
            Trace::DeferredSetRegister* psr =
                static_cast<Trace::DeferredSetRegister*>(action);
            if (!absolute) {
              value += psr->value();
              absolute = true;
            }
            // SET_REGISTER is currently only used for newly introduced loop
            // counters. They can have a significant previous value if they
            // occour in a loop. TODO(lrn): Propagate this information, so we
            // can set undo_action to ACTION_IGNORE if we know there is no
            // value to restore.
            undo_action = ACTION_RESTORE;
            ASSERT(store_position == kNoStore);
            ASSERT(!clear);
            break;
          }
          case ActionNode::INCREMENT_REGISTER:
            if (!absolute) {
              value++;
            }
            ASSERT(store_position == kNoStore);
            ASSERT(!clear);
            undo_action = ACTION_RESTORE;
            break;
          case ActionNode::STORE_POSITION: {
            Trace::DeferredCapture* pc =
                static_cast<Trace::DeferredCapture*>(action);
            if (!clear && store_position == kNoStore) {
              store_position = pc->cp_offset();
            }

            // For captures we know that stores and clears alternate.
            // Other register, are never cleared, and if the occur
            // inside a loop, they might be assigned more than once.
            if (reg <= 1) {
              // Registers zero and one, aka "capture zero", is
              // always set correctly if we succeed. There is no
              // need to undo a setting on backtrack, because we
              // will set it again or fail.
              undo_action = ACTION_IGNORE;
            } else {
              undo_action = pc->is_capture() ? ACTION_CLEAR : ACTION_RESTORE;
            }
            ASSERT(!absolute);
            ASSERT(value == 0);
            break;
          }
          case ActionNode::CLEAR_CAPTURES: {
            // Since we're scanning in reverse order, if we've already
            // set the position we have to ignore historically earlier
            // clearing operations.
            if (store_position == kNoStore) {
              clear = true;
            }
            undo_action = ACTION_RESTORE;
            ASSERT(!absolute);
            ASSERT(value == 0);
            break;
          }
          default:
            UNREACHABLE();
            break;
        }
      }
    }
    // Prepare for the undo-action (e.g., push if it's going to be popped).
    if (undo_action == ACTION_RESTORE) {
      assembler->PushRegister(reg);
      registers_to_pop->Set(reg, zone);
    } else if (undo_action == ACTION_CLEAR) {
      registers_to_clear->Set(reg, zone);
    }
    // Perform the chronologically last action (or accumulated increment)
    // for the register.
    if (store_position != kNoStore) {
      assembler->WriteCurrentPositionToRegister(reg, store_position);
    } else if (clear) {
      assembler->ClearRegisters(reg, reg);
    } else if (absolute) {
      assembler->SetRegister(reg, value);
    } else if (value != 0) {
      assembler->AdvanceRegister(reg, value);
    }
  }
}

// This is called as we come into a loop choice node and some other tricky
// nodes.  It normalizes the state of the code generator to ensure we can
// generate generic code.
void Trace::Flush(RegExpCompiler* compiler, RegExpNode* successor) {
  RegExpMacroAssembler* assembler = compiler->macro_assembler();

  ASSERT(!is_trivial());

  if (actions_ == NULL && backtrack() == NULL) {
    // Here we just have some deferred cp advances to fix and we are back to
    // a normal situation.  We may also have to forget some information gained
    // through a quick check that was already performed.
    if (cp_offset_ != 0) assembler->AdvanceCurrentPosition(cp_offset_);
    // Create a new trivial state and generate the node with that.
    Trace new_state;
    successor->Emit(compiler, &new_state);
    return;
  }

  // Generate deferred actions here along with code to undo them again.
  OutSet affected_registers;

  if (backtrack() != NULL) {
    // Here we have a concrete backtrack location.  These are set up by choice
    // nodes and so they indicate that we have a deferred save of the current
    // position which we may need to emit here.
    assembler->PushCurrentPosition();
  }
  Zone* zone = successor->zone();
  intptr_t max_register = FindAffectedRegisters(&affected_registers, zone);
  OutSet registers_to_pop;
  OutSet registers_to_clear;
  PerformDeferredActions(assembler, max_register, affected_registers,
                         &registers_to_pop, &registers_to_clear, zone);
  if (cp_offset_ != 0) {
    assembler->AdvanceCurrentPosition(cp_offset_);
  }

  // Create a new trivial state and generate the node with that.
  BlockLabel undo;
  assembler->PushBacktrack(&undo);
  Trace new_state;
  successor->Emit(compiler, &new_state);

  // On backtrack we need to restore state.
  assembler->BindBlock(&undo);
  RestoreAffectedRegisters(assembler, max_register, registers_to_pop,
                           registers_to_clear);
  if (backtrack() == NULL) {
    assembler->Backtrack();
  } else {
    assembler->PopCurrentPosition();
    assembler->GoTo(backtrack());
  }
}

void NegativeSubmatchSuccess::Emit(RegExpCompiler* compiler, Trace* trace) {
  RegExpMacroAssembler* assembler = compiler->macro_assembler();

  // Omit flushing the trace. We discard the entire stack frame anyway.

  if (!label()->IsBound()) {
    // We are completely independent of the trace, since we ignore it,
    // so this code can be used as the generic version.
    assembler->BindBlock(label());
  }

  // Throw away everything on the backtrack stack since the start
  // of the negative submatch and restore the character position.
  assembler->ReadCurrentPositionFromRegister(current_position_register_);
  assembler->ReadStackPointerFromRegister(stack_pointer_register_);
  if (clear_capture_count_ > 0) {
    // Clear any captures that might have been performed during the success
    // of the body of the negative look-ahead.
    int clear_capture_end = clear_capture_start_ + clear_capture_count_ - 1;
    assembler->ClearRegisters(clear_capture_start_, clear_capture_end);
  }
  // Now that we have unwound the stack we find at the top of the stack the
  // backtrack that the BeginSubmatch node got.
  assembler->Backtrack();
}

void EndNode::Emit(RegExpCompiler* compiler, Trace* trace) {
  if (!trace->is_trivial()) {
    trace->Flush(compiler, this);
    return;
  }
  RegExpMacroAssembler* assembler = compiler->macro_assembler();
  if (!label()->IsBound()) {
    assembler->BindBlock(label());
  }
  switch (action_) {
    case ACCEPT:
      assembler->Succeed();
      return;
    case BACKTRACK:
      assembler->GoTo(trace->backtrack());
      return;
    case NEGATIVE_SUBMATCH_SUCCESS:
      // This case is handled in a different virtual method.
      UNREACHABLE();
  }
  UNIMPLEMENTED();
}

void GuardedAlternative::AddGuard(Guard* guard, Zone* zone) {
  if (guards_ == NULL) guards_ = new (zone) ZoneGrowableArray<Guard*>(1);
  guards_->Add(guard);
}

ActionNode* ActionNode::SetRegister(intptr_t reg,
                                    intptr_t val,
                                    RegExpNode* on_success) {
  ActionNode* result =
      new (on_success->zone()) ActionNode(SET_REGISTER, on_success);
  result->data_.u_store_register.reg = reg;
  result->data_.u_store_register.value = val;
  return result;
}

ActionNode* ActionNode::IncrementRegister(intptr_t reg,
                                          RegExpNode* on_success) {
  ActionNode* result =
      new (on_success->zone()) ActionNode(INCREMENT_REGISTER, on_success);
  result->data_.u_increment_register.reg = reg;
  return result;
}

ActionNode* ActionNode::StorePosition(intptr_t reg,
                                      bool is_capture,
                                      RegExpNode* on_success) {
  ActionNode* result =
      new (on_success->zone()) ActionNode(STORE_POSITION, on_success);
  result->data_.u_position_register.reg = reg;
  result->data_.u_position_register.is_capture = is_capture;
  return result;
}

ActionNode* ActionNode::ClearCaptures(Interval range, RegExpNode* on_success) {
  ActionNode* result =
      new (on_success->zone()) ActionNode(CLEAR_CAPTURES, on_success);
  result->data_.u_clear_captures.range_from = range.from();
  result->data_.u_clear_captures.range_to = range.to();
  return result;
}

ActionNode* ActionNode::BeginSubmatch(intptr_t stack_reg,
                                      intptr_t position_reg,
                                      RegExpNode* on_success) {
  ActionNode* result =
      new (on_success->zone()) ActionNode(BEGIN_SUBMATCH, on_success);
  result->data_.u_submatch.stack_pointer_register = stack_reg;
  result->data_.u_submatch.current_position_register = position_reg;
  return result;
}

ActionNode* ActionNode::PositiveSubmatchSuccess(intptr_t stack_reg,
                                                intptr_t position_reg,
                                                intptr_t clear_register_count,
                                                intptr_t clear_register_from,
                                                RegExpNode* on_success) {
  ActionNode* result = new (on_success->zone())
      ActionNode(POSITIVE_SUBMATCH_SUCCESS, on_success);
  result->data_.u_submatch.stack_pointer_register = stack_reg;
  result->data_.u_submatch.current_position_register = position_reg;
  result->data_.u_submatch.clear_register_count = clear_register_count;
  result->data_.u_submatch.clear_register_from = clear_register_from;
  return result;
}

ActionNode* ActionNode::EmptyMatchCheck(intptr_t start_register,
                                        intptr_t repetition_register,
                                        intptr_t repetition_limit,
                                        RegExpNode* on_success) {
  ActionNode* result =
      new (on_success->zone()) ActionNode(EMPTY_MATCH_CHECK, on_success);
  result->data_.u_empty_match_check.start_register = start_register;
  result->data_.u_empty_match_check.repetition_register = repetition_register;
  result->data_.u_empty_match_check.repetition_limit = repetition_limit;
  return result;
}

#define DEFINE_ACCEPT(Type)                                                    \
  void Type##Node::Accept(NodeVisitor* visitor) { visitor->Visit##Type(this); }
FOR_EACH_NODE_TYPE(DEFINE_ACCEPT)
#undef DEFINE_ACCEPT

void LoopChoiceNode::Accept(NodeVisitor* visitor) {
  visitor->VisitLoopChoice(this);
}

// -------------------------------------------------------------------
// Emit code.

void ChoiceNode::GenerateGuard(RegExpMacroAssembler* macro_assembler,
                               Guard* guard,
                               Trace* trace) {
  switch (guard->op()) {
    case Guard::LT:
      ASSERT(!trace->mentions_reg(guard->reg()));
      macro_assembler->IfRegisterGE(guard->reg(), guard->value(),
                                    trace->backtrack());
      break;
    case Guard::GEQ:
      ASSERT(!trace->mentions_reg(guard->reg()));
      macro_assembler->IfRegisterLT(guard->reg(), guard->value(),
                                    trace->backtrack());
      break;
  }
}

// Returns the number of characters in the equivalence class, omitting those
// that cannot occur in the source string because it is ASCII.
static intptr_t GetCaseIndependentLetters(uint16_t character,
                                          bool one_byte_subject,
                                          int32_t* letters) {
  unibrow::Mapping<unibrow::Ecma262UnCanonicalize> jsregexp_uncanonicalize;
  intptr_t length = jsregexp_uncanonicalize.get(character, '\0', letters);
  // Unibrow returns 0 or 1 for characters where case independence is
  // trivial.
  if (length == 0) {
    letters[0] = character;
    length = 1;
  }
  if (!one_byte_subject || character <= Symbols::kMaxOneCharCodeSymbol) {
    return length;
  }

  // The standard requires that non-ASCII characters cannot have ASCII
  // character codes in their equivalence class.
  // TODO(dcarney): issue 3550 this is not actually true for Latin1 anymore,
  // is it?  For example, \u00C5 is equivalent to \u212B.
  return 0;
}

static inline bool EmitSimpleCharacter(Zone* zone,
                                       RegExpCompiler* compiler,
                                       uint16_t c,
                                       BlockLabel* on_failure,
                                       intptr_t cp_offset,
                                       bool check,
                                       bool preloaded) {
  RegExpMacroAssembler* assembler = compiler->macro_assembler();
  bool bound_checked = false;
  if (!preloaded) {
    assembler->LoadCurrentCharacter(cp_offset, on_failure, check);
    bound_checked = true;
  }
  assembler->CheckNotCharacter(c, on_failure);
  return bound_checked;
}

// Only emits non-letters (things that don't have case).  Only used for case
// independent matches.
static inline bool EmitAtomNonLetter(Zone* zone,
                                     RegExpCompiler* compiler,
                                     uint16_t c,
                                     BlockLabel* on_failure,
                                     intptr_t cp_offset,
                                     bool check,
                                     bool preloaded) {
  RegExpMacroAssembler* macro_assembler = compiler->macro_assembler();
  bool one_byte = compiler->one_byte();
  int32_t chars[unibrow::Ecma262UnCanonicalize::kMaxWidth];
  intptr_t length = GetCaseIndependentLetters(c, one_byte, chars);
  if (length < 1) {
    // This can't match.  Must be an one-byte subject and a non-one-byte
    // character.  We do not need to do anything since the one-byte pass
    // already handled this.
    return false;  // Bounds not checked.
  }
  bool checked = false;
  // We handle the length > 1 case in a later pass.
  if (length == 1) {
    if (one_byte && c > Symbols::kMaxOneCharCodeSymbol) {
      // Can't match - see above.
      return false;  // Bounds not checked.
    }
    if (!preloaded) {
      macro_assembler->LoadCurrentCharacter(cp_offset, on_failure, check);
      checked = check;
    }
    macro_assembler->CheckNotCharacter(c, on_failure);
  }
  return checked;
}

static bool ShortCutEmitCharacterPair(RegExpMacroAssembler* macro_assembler,
                                      bool one_byte,
                                      uint16_t c1,
                                      uint16_t c2,
                                      BlockLabel* on_failure) {
  uint16_t char_mask;
  if (one_byte) {
    char_mask = Symbols::kMaxOneCharCodeSymbol;
  } else {
    char_mask = Utf16::kMaxCodeUnit;
  }
  uint16_t exor = c1 ^ c2;
  // Check whether exor has only one bit set.
  if (((exor - 1) & exor) == 0) {
    // If c1 and c2 differ only by one bit.
    // Ecma262UnCanonicalize always gives the highest number last.
    ASSERT(c2 > c1);
    uint16_t mask = char_mask ^ exor;
    macro_assembler->CheckNotCharacterAfterAnd(c1, mask, on_failure);
    return true;
  }
  ASSERT(c2 > c1);
  uint16_t diff = c2 - c1;
  if (((diff - 1) & diff) == 0 && c1 >= diff) {
    // If the characters differ by 2^n but don't differ by one bit then
    // subtract the difference from the found character, then do the or
    // trick.  We avoid the theoretical case where negative numbers are
    // involved in order to simplify code generation.
    uint16_t mask = char_mask ^ diff;
    macro_assembler->CheckNotCharacterAfterMinusAnd(c1 - diff, diff, mask,
                                                    on_failure);
    return true;
  }
  return false;
}

typedef bool EmitCharacterFunction(Zone* zone,
                                   RegExpCompiler* compiler,
                                   uint16_t c,
                                   BlockLabel* on_failure,
                                   intptr_t cp_offset,
                                   bool check,
                                   bool preloaded);

// Only emits letters (things that have case).  Only used for case independent
// matches.
static inline bool EmitAtomLetter(Zone* zone,
                                  RegExpCompiler* compiler,
                                  uint16_t c,
                                  BlockLabel* on_failure,
                                  intptr_t cp_offset,
                                  bool check,
                                  bool preloaded) {
  RegExpMacroAssembler* macro_assembler = compiler->macro_assembler();
  bool one_byte = compiler->one_byte();
  int32_t chars[unibrow::Ecma262UnCanonicalize::kMaxWidth];
  intptr_t length = GetCaseIndependentLetters(c, one_byte, chars);
  if (length <= 1) return false;
  // We may not need to check against the end of the input string
  // if this character lies before a character that matched.
  if (!preloaded) {
    macro_assembler->LoadCurrentCharacter(cp_offset, on_failure, check);
  }
  BlockLabel ok;
  ASSERT(unibrow::Ecma262UnCanonicalize::kMaxWidth == 4);
  switch (length) {
    case 2: {
      if (ShortCutEmitCharacterPair(macro_assembler, one_byte, chars[0],
                                    chars[1], on_failure)) {
      } else {
        macro_assembler->CheckCharacter(chars[0], &ok);
        macro_assembler->CheckNotCharacter(chars[1], on_failure);
        macro_assembler->BindBlock(&ok);
      }
      break;
    }
    case 4:
      macro_assembler->CheckCharacter(chars[3], &ok);
      FALL_THROUGH;
    case 3:
      macro_assembler->CheckCharacter(chars[0], &ok);
      macro_assembler->CheckCharacter(chars[1], &ok);
      macro_assembler->CheckNotCharacter(chars[2], on_failure);
      macro_assembler->BindBlock(&ok);
      break;
    default:
      UNREACHABLE();
      break;
  }
  return true;
}

static void EmitBoundaryTest(RegExpMacroAssembler* masm,
                             uint16_t border,
                             BlockLabel* fall_through,
                             BlockLabel* above_or_equal,
                             BlockLabel* below) {
  if (below != fall_through) {
    masm->CheckCharacterLT(border, below);
    if (above_or_equal != fall_through) masm->GoTo(above_or_equal);
  } else {
    masm->CheckCharacterGT(border - 1, above_or_equal);
  }
}

static void EmitDoubleBoundaryTest(RegExpMacroAssembler* masm,
                                   uint16_t first,
                                   uint16_t last,
                                   BlockLabel* fall_through,
                                   BlockLabel* in_range,
                                   BlockLabel* out_of_range) {
  if (in_range == fall_through) {
    if (first == last) {
      masm->CheckNotCharacter(first, out_of_range);
    } else {
      masm->CheckCharacterNotInRange(first, last, out_of_range);
    }
  } else {
    if (first == last) {
      masm->CheckCharacter(first, in_range);
    } else {
      masm->CheckCharacterInRange(first, last, in_range);
    }
    if (out_of_range != fall_through) masm->GoTo(out_of_range);
  }
}

// even_label is for ranges[i] to ranges[i + 1] where i - start_index is even.
// odd_label is for ranges[i] to ranges[i + 1] where i - start_index is odd.
static void EmitUseLookupTable(RegExpMacroAssembler* masm,
                               ZoneGrowableArray<uint16_t>* ranges,
                               intptr_t start_index,
                               intptr_t end_index,
                               uint16_t min_char,
                               BlockLabel* fall_through,
                               BlockLabel* even_label,
                               BlockLabel* odd_label) {
  static const intptr_t kSize = RegExpMacroAssembler::kTableSize;
  static const intptr_t kMask = RegExpMacroAssembler::kTableMask;

  intptr_t base = (min_char & ~kMask);

  // Assert that everything is on one kTableSize page.
  for (intptr_t i = start_index; i <= end_index; i++) {
    ASSERT((ranges->At(i) & ~kMask) == base);
  }
  ASSERT(start_index == 0 || (ranges->At(start_index - 1) & ~kMask) <= base);

  char templ[kSize];
  BlockLabel* on_bit_set;
  BlockLabel* on_bit_clear;
  intptr_t bit;
  if (even_label == fall_through) {
    on_bit_set = odd_label;
    on_bit_clear = even_label;
    bit = 1;
  } else {
    on_bit_set = even_label;
    on_bit_clear = odd_label;
    bit = 0;
  }
  for (intptr_t i = 0; i < (ranges->At(start_index) & kMask) && i < kSize;
       i++) {
    templ[i] = bit;
  }
  intptr_t j = 0;
  bit ^= 1;
  for (intptr_t i = start_index; i < end_index; i++) {
    for (j = (ranges->At(i) & kMask); j < (ranges->At(i + 1) & kMask); j++) {
      templ[j] = bit;
    }
    bit ^= 1;
  }
  for (intptr_t i = j; i < kSize; i++) {
    templ[i] = bit;
  }
  // TODO(erikcorry): Cache these.
  const TypedData& ba = TypedData::ZoneHandle(
      masm->zone(), TypedData::New(kTypedDataUint8ArrayCid, kSize, Heap::kOld));
  for (intptr_t i = 0; i < kSize; i++) {
    ba.SetUint8(i, templ[i]);
  }
  masm->CheckBitInTable(ba, on_bit_set);
  if (on_bit_clear != fall_through) masm->GoTo(on_bit_clear);
}

static void CutOutRange(RegExpMacroAssembler* masm,
                        ZoneGrowableArray<uint16_t>* ranges,
                        intptr_t start_index,
                        intptr_t end_index,
                        intptr_t cut_index,
                        BlockLabel* even_label,
                        BlockLabel* odd_label) {
  bool odd = (((cut_index - start_index) & 1) == 1);
  BlockLabel* in_range_label = odd ? odd_label : even_label;
  BlockLabel dummy;
  EmitDoubleBoundaryTest(masm, ranges->At(cut_index),
                         ranges->At(cut_index + 1) - 1, &dummy, in_range_label,
                         &dummy);
  ASSERT(!dummy.IsLinked());
  // Cut out the single range by rewriting the array.  This creates a new
  // range that is a merger of the two ranges on either side of the one we
  // are cutting out.  The oddity of the labels is preserved.
  for (intptr_t j = cut_index; j > start_index; j--) {
    (*ranges)[j] = ranges->At(j - 1);
  }
  for (intptr_t j = cut_index + 1; j < end_index; j++) {
    (*ranges)[j] = ranges->At(j + 1);
  }
}

// Unicode case.  Split the search space into kSize spaces that are handled
// with recursion.
static void SplitSearchSpace(ZoneGrowableArray<uint16_t>* ranges,
                             intptr_t start_index,
                             intptr_t end_index,
                             intptr_t* new_start_index,
                             intptr_t* new_end_index,
                             uint16_t* border) {
  static const intptr_t kSize = RegExpMacroAssembler::kTableSize;
  static const intptr_t kMask = RegExpMacroAssembler::kTableMask;

  uint16_t first = ranges->At(start_index);
  uint16_t last = ranges->At(end_index) - 1;

  *new_start_index = start_index;
  *border = (ranges->At(start_index) & ~kMask) + kSize;
  while (*new_start_index < end_index) {
    if (ranges->At(*new_start_index) > *border) break;
    (*new_start_index)++;
  }
  // new_start_index is the index of the first edge that is beyond the
  // current kSize space.

  // For very large search spaces we do a binary chop search of the non-Latin1
  // space instead of just going to the end of the current kSize space.  The
  // heuristics are complicated a little by the fact that any 128-character
  // encoding space can be quickly tested with a table lookup, so we don't
  // wish to do binary chop search at a smaller granularity than that.  A
  // 128-character space can take up a lot of space in the ranges array if,
  // for example, we only want to match every second character (eg. the lower
  // case characters on some Unicode pages).
  intptr_t binary_chop_index = (end_index + start_index) / 2;
  // The first test ensures that we get to the code that handles the Latin1
  // range with a single not-taken branch, speeding up this important
  // character range (even non-Latin1 charset-based text has spaces and
  // punctuation).
  if (*border - 1 > Symbols::kMaxOneCharCodeSymbol &&  // Latin1 case.
      end_index - start_index > (*new_start_index - start_index) * 2 &&
      last - first > kSize * 2 && binary_chop_index > *new_start_index &&
      ranges->At(binary_chop_index) >= first + 2 * kSize) {
    intptr_t scan_forward_for_section_border = binary_chop_index;
    intptr_t new_border = (ranges->At(binary_chop_index) | kMask) + 1;

    while (scan_forward_for_section_border < end_index) {
      if (ranges->At(scan_forward_for_section_border) > new_border) {
        *new_start_index = scan_forward_for_section_border;
        *border = new_border;
        break;
      }
      scan_forward_for_section_border++;
    }
  }

  ASSERT(*new_start_index > start_index);
  *new_end_index = *new_start_index - 1;
  if (ranges->At(*new_end_index) == *border) {
    (*new_end_index)--;
  }
  if (*border >= ranges->At(end_index)) {
    *border = ranges->At(end_index);
    *new_start_index = end_index;  // Won't be used.
    *new_end_index = end_index - 1;
  }
}

// Gets a series of segment boundaries representing a character class.  If the
// character is in the range between an even and an odd boundary (counting from
// start_index) then go to even_label, otherwise go to odd_label.  We already
// know that the character is in the range of min_char to max_char inclusive.
// Either label can be NULL indicating backtracking.  Either label can also be
// equal to the fall_through label.
static void GenerateBranches(RegExpMacroAssembler* masm,
                             ZoneGrowableArray<uint16_t>* ranges,
                             intptr_t start_index,
                             intptr_t end_index,
                             uint16_t min_char,
                             uint16_t max_char,
                             BlockLabel* fall_through,
                             BlockLabel* even_label,
                             BlockLabel* odd_label) {
  uint16_t first = ranges->At(start_index);
  uint16_t last = ranges->At(end_index) - 1;

  ASSERT(min_char < first);

  // Just need to test if the character is before or on-or-after
  // a particular character.
  if (start_index == end_index) {
    EmitBoundaryTest(masm, first, fall_through, even_label, odd_label);
    return;
  }

  // Another almost trivial case:  There is one interval in the middle that is
  // different from the end intervals.
  if (start_index + 1 == end_index) {
    EmitDoubleBoundaryTest(masm, first, last, fall_through, even_label,
                           odd_label);
    return;
  }

  // It's not worth using table lookup if there are very few intervals in the
  // character class.
  if (end_index - start_index <= 6) {
    // It is faster to test for individual characters, so we look for those
    // first, then try arbitrary ranges in the second round.
    static intptr_t kNoCutIndex = -1;
    intptr_t cut = kNoCutIndex;
    for (intptr_t i = start_index; i < end_index; i++) {
      if (ranges->At(i) == ranges->At(i + 1) - 1) {
        cut = i;
        break;
      }
    }
    if (cut == kNoCutIndex) cut = start_index;
    CutOutRange(masm, ranges, start_index, end_index, cut, even_label,
                odd_label);
    ASSERT(end_index - start_index >= 2);
    GenerateBranches(masm, ranges, start_index + 1, end_index - 1, min_char,
                     max_char, fall_through, even_label, odd_label);
    return;
  }

  // If there are a lot of intervals in the regexp, then we will use tables to
  // determine whether the character is inside or outside the character class.
  static const intptr_t kBits = RegExpMacroAssembler::kTableSizeBits;

  if ((max_char >> kBits) == (min_char >> kBits)) {
    EmitUseLookupTable(masm, ranges, start_index, end_index, min_char,
                       fall_through, even_label, odd_label);
    return;
  }

  if ((min_char >> kBits) != (first >> kBits)) {
    masm->CheckCharacterLT(first, odd_label);
    GenerateBranches(masm, ranges, start_index + 1, end_index, first, max_char,
                     fall_through, odd_label, even_label);
    return;
  }

  intptr_t new_start_index = 0;
  intptr_t new_end_index = 0;
  uint16_t border = 0;

  SplitSearchSpace(ranges, start_index, end_index, &new_start_index,
                   &new_end_index, &border);

  BlockLabel handle_rest;
  BlockLabel* above = &handle_rest;
  if (border == last + 1) {
    // We didn't find any section that started after the limit, so everything
    // above the border is one of the terminal labels.
    above = (end_index & 1) != (start_index & 1) ? odd_label : even_label;
    ASSERT(new_end_index == end_index - 1);
  }

  ASSERT(start_index <= new_end_index);
  ASSERT(new_start_index <= end_index);
  ASSERT(start_index < new_start_index);
  ASSERT(new_end_index < end_index);
  ASSERT(new_end_index + 1 == new_start_index ||
         (new_end_index + 2 == new_start_index &&
          border == ranges->At(new_end_index + 1)));
  ASSERT(min_char < border - 1);
  ASSERT(border < max_char);
  ASSERT(ranges->At(new_end_index) < border);
  ASSERT(border < ranges->At(new_start_index) ||
         (border == ranges->At(new_start_index) &&
          new_start_index == end_index && new_end_index == end_index - 1 &&
          border == last + 1));
  ASSERT(new_start_index == 0 || border >= ranges->At(new_start_index - 1));

  masm->CheckCharacterGT(border - 1, above);
  BlockLabel dummy;
  GenerateBranches(masm, ranges, start_index, new_end_index, min_char,
                   border - 1, &dummy, even_label, odd_label);

  if (handle_rest.IsLinked()) {
    masm->BindBlock(&handle_rest);
    bool flip = (new_start_index & 1) != (start_index & 1);
    GenerateBranches(masm, ranges, new_start_index, end_index, border, max_char,
                     &dummy, flip ? odd_label : even_label,
                     flip ? even_label : odd_label);
  }
}

static void EmitCharClass(RegExpMacroAssembler* macro_assembler,
                          RegExpCharacterClass* cc,
                          bool one_byte,
                          BlockLabel* on_failure,
                          intptr_t cp_offset,
                          bool check_offset,
                          bool preloaded,
                          Zone* zone) {
  ZoneGrowableArray<CharacterRange>* ranges = cc->ranges();
  if (!CharacterRange::IsCanonical(ranges)) {
    CharacterRange::Canonicalize(ranges);
  }

  uint16_t max_char;
  if (one_byte) {
    max_char = Symbols::kMaxOneCharCodeSymbol;
  } else {
    max_char = Utf16::kMaxCodeUnit;
  }

  intptr_t range_count = ranges->length();

  intptr_t last_valid_range = range_count - 1;
  while (last_valid_range >= 0) {
    const CharacterRange& range = ranges->At(last_valid_range);
    if (range.from() <= max_char) {
      break;
    }
    last_valid_range--;
  }

  if (last_valid_range < 0) {
    if (!cc->is_negated()) {
      macro_assembler->GoTo(on_failure);
    }
    if (check_offset) {
      macro_assembler->CheckPosition(cp_offset, on_failure);
    }
    return;
  }

  if (last_valid_range == 0 && ranges->At(0).IsEverything(max_char)) {
    if (cc->is_negated()) {
      macro_assembler->GoTo(on_failure);
    } else {
      // This is a common case hit by non-anchored expressions.
      if (check_offset) {
        macro_assembler->CheckPosition(cp_offset, on_failure);
      }
    }
    return;
  }

  if (!preloaded) {
    macro_assembler->LoadCurrentCharacter(cp_offset, on_failure, check_offset);
  }

  if (cc->is_standard() && macro_assembler->CheckSpecialCharacterClass(
                               cc->standard_type(), on_failure)) {
    return;
  }

  // A new list with ascending entries.  Each entry is a code unit
  // where there is a boundary between code units that are part of
  // the class and code units that are not.  Normally we insert an
  // entry at zero which goes to the failure label, but if there
  // was already one there we fall through for success on that entry.
  // Subsequent entries have alternating meaning (success/failure).
  ZoneGrowableArray<uint16_t>* range_boundaries =
      new (zone) ZoneGrowableArray<uint16_t>(last_valid_range);

  bool zeroth_entry_is_failure = !cc->is_negated();

  for (intptr_t i = 0; i <= last_valid_range; i++) {
    const CharacterRange& range = ranges->At(i);
    if (range.from() == 0) {
      ASSERT(i == 0);
      zeroth_entry_is_failure = !zeroth_entry_is_failure;
    } else {
      range_boundaries->Add(range.from());
    }
    if (range.to() + 1 <= max_char) {
      range_boundaries->Add(range.to() + 1);
    }
  }
  intptr_t end_index = range_boundaries->length() - 1;

  BlockLabel fall_through;
  GenerateBranches(macro_assembler, range_boundaries,
                   0,  // start_index.
                   end_index,
                   0,  // min_char.
                   max_char, &fall_through,
                   zeroth_entry_is_failure ? &fall_through : on_failure,
                   zeroth_entry_is_failure ? on_failure : &fall_through);
  macro_assembler->BindBlock(&fall_through);
}

RegExpNode::~RegExpNode() {}

RegExpNode::LimitResult RegExpNode::LimitVersions(RegExpCompiler* compiler,
                                                  Trace* trace) {
  // If we are generating a greedy loop then don't stop and don't reuse code.
  if (trace->stop_node() != NULL) {
    return CONTINUE;
  }

  RegExpMacroAssembler* macro_assembler = compiler->macro_assembler();
  if (trace->is_trivial()) {
    if (label_.IsBound()) {
      // We are being asked to generate a generic version, but that's already
      // been done so just go to it.
      macro_assembler->GoTo(&label_);
      return DONE;
    }
    if (compiler->recursion_depth() >= RegExpCompiler::kMaxRecursion) {
      // To avoid too deep recursion we push the node to the work queue and just
      // generate a goto here.
      compiler->AddWork(this);
      macro_assembler->GoTo(&label_);
      return DONE;
    }
    // Generate generic version of the node and bind the label for later use.
    macro_assembler->BindBlock(&label_);
    return CONTINUE;
  }

  // We are being asked to make a non-generic version.  Keep track of how many
  // non-generic versions we generate so as not to overdo it.
  trace_count_++;
  if (kRegexpOptimization && trace_count_ < kMaxCopiesCodeGenerated &&
      compiler->recursion_depth() <= RegExpCompiler::kMaxRecursion) {
    return CONTINUE;
  }

  // If we get here code has been generated for this node too many times or
  // recursion is too deep.  Time to switch to a generic version.  The code for
  // generic versions above can handle deep recursion properly.
  trace->Flush(compiler, this);
  return DONE;
}

intptr_t ActionNode::EatsAtLeast(intptr_t still_to_find,
                                 intptr_t budget,
                                 bool not_at_start) {
  if (budget <= 0) return 0;
  if (action_type_ == POSITIVE_SUBMATCH_SUCCESS) return 0;  // Rewinds input!
  return on_success()->EatsAtLeast(still_to_find, budget - 1, not_at_start);
}

void ActionNode::FillInBMInfo(intptr_t offset,
                              intptr_t budget,
                              BoyerMooreLookahead* bm,
                              bool not_at_start) {
  if (action_type_ == BEGIN_SUBMATCH) {
    bm->SetRest(offset);
  } else if (action_type_ != POSITIVE_SUBMATCH_SUCCESS) {
    on_success()->FillInBMInfo(offset, budget - 1, bm, not_at_start);
  }
  SaveBMInfo(bm, not_at_start, offset);
}

intptr_t AssertionNode::EatsAtLeast(intptr_t still_to_find,
                                    intptr_t budget,
                                    bool not_at_start) {
  if (budget <= 0) return 0;
  // If we know we are not at the start and we are asked "how many characters
  // will you match if you succeed?" then we can answer anything since false
  // implies false.  So lets just return the max answer (still_to_find) since
  // that won't prevent us from preloading a lot of characters for the other
  // branches in the node graph.
  if (assertion_type() == AT_START && not_at_start) return still_to_find;
  return on_success()->EatsAtLeast(still_to_find, budget - 1, not_at_start);
}

void AssertionNode::FillInBMInfo(intptr_t offset,
                                 intptr_t budget,
                                 BoyerMooreLookahead* bm,
                                 bool not_at_start) {
  // Match the behaviour of EatsAtLeast on this node.
  if (assertion_type() == AT_START && not_at_start) return;
  on_success()->FillInBMInfo(offset, budget - 1, bm, not_at_start);
  SaveBMInfo(bm, not_at_start, offset);
}

intptr_t BackReferenceNode::EatsAtLeast(intptr_t still_to_find,
                                        intptr_t budget,
                                        bool not_at_start) {
  if (read_backward()) return 0;
  if (budget <= 0) return 0;
  return on_success()->EatsAtLeast(still_to_find, budget - 1, not_at_start);
}

intptr_t TextNode::EatsAtLeast(intptr_t still_to_find,
                               intptr_t budget,
                               bool not_at_start) {
  if (read_backward()) return 0;
  intptr_t answer = Length();
  if (answer >= still_to_find) return answer;
  if (budget <= 0) return answer;
  // We are not at start after this node so we set the last argument to 'true'.
  return answer +
         on_success()->EatsAtLeast(still_to_find - answer, budget - 1, true);
}

intptr_t NegativeLookaroundChoiceNode::EatsAtLeast(intptr_t still_to_find,
                                                   intptr_t budget,
                                                   bool not_at_start) {
  if (budget <= 0) return 0;
  // Alternative 0 is the negative lookahead, alternative 1 is what comes
  // afterwards.
  RegExpNode* node = (*alternatives_)[1].node();
  return node->EatsAtLeast(still_to_find, budget - 1, not_at_start);
}

void NegativeLookaroundChoiceNode::GetQuickCheckDetails(
    QuickCheckDetails* details,
    RegExpCompiler* compiler,
    intptr_t filled_in,
    bool not_at_start) {
  // Alternative 0 is the negative lookahead, alternative 1 is what comes
  // afterwards.
  RegExpNode* node = (*alternatives_)[1].node();
  return node->GetQuickCheckDetails(details, compiler, filled_in, not_at_start);
}

intptr_t ChoiceNode::EatsAtLeastHelper(intptr_t still_to_find,
                                       intptr_t budget,
                                       RegExpNode* ignore_this_node,
                                       bool not_at_start) {
  if (budget <= 0) return 0;
  intptr_t min = 100;
  intptr_t choice_count = alternatives_->length();
  budget = (budget - 1) / choice_count;
  for (intptr_t i = 0; i < choice_count; i++) {
    RegExpNode* node = (*alternatives_)[i].node();
    if (node == ignore_this_node) continue;
    intptr_t node_eats_at_least =
        node->EatsAtLeast(still_to_find, budget, not_at_start);
    if (node_eats_at_least < min) min = node_eats_at_least;
    if (min == 0) return 0;
  }
  return min;
}

intptr_t LoopChoiceNode::EatsAtLeast(intptr_t still_to_find,
                                     intptr_t budget,
                                     bool not_at_start) {
  return EatsAtLeastHelper(still_to_find, budget - 1, loop_node_, not_at_start);
}

intptr_t ChoiceNode::EatsAtLeast(intptr_t still_to_find,
                                 intptr_t budget,
                                 bool not_at_start) {
  return EatsAtLeastHelper(still_to_find, budget, NULL, not_at_start);
}

// Takes the left-most 1-bit and smears it out, setting all bits to its right.
static inline uint32_t SmearBitsRight(uint32_t v) {
  v |= v >> 1;
  v |= v >> 2;
  v |= v >> 4;
  v |= v >> 8;
  v |= v >> 16;
  return v;
}

bool QuickCheckDetails::Rationalize(bool asc) {
  bool found_useful_op = false;
  uint32_t char_mask;
  if (asc) {
    char_mask = Symbols::kMaxOneCharCodeSymbol;
  } else {
    char_mask = Utf16::kMaxCodeUnit;
  }
  mask_ = 0;
  value_ = 0;
  intptr_t char_shift = 0;
  for (intptr_t i = 0; i < characters_; i++) {
    Position* pos = &positions_[i];
    if ((pos->mask & Symbols::kMaxOneCharCodeSymbol) != 0) {
      found_useful_op = true;
    }
    mask_ |= (pos->mask & char_mask) << char_shift;
    value_ |= (pos->value & char_mask) << char_shift;
    char_shift += asc ? 8 : 16;
  }
  return found_useful_op;
}

bool RegExpNode::EmitQuickCheck(RegExpCompiler* compiler,
                                Trace* bounds_check_trace,
                                Trace* trace,
                                bool preload_has_checked_bounds,
                                BlockLabel* on_possible_success,
                                QuickCheckDetails* details,
                                bool fall_through_on_failure) {
  if (details->characters() == 0) return false;
  GetQuickCheckDetails(details, compiler, 0,
                       trace->at_start() == Trace::FALSE_VALUE);
  if (details->cannot_match()) return false;
  if (!details->Rationalize(compiler->one_byte())) return false;
  ASSERT(details->characters() == 1 ||
         compiler->macro_assembler()->CanReadUnaligned());
  uint32_t mask = details->mask();
  uint32_t value = details->value();

  RegExpMacroAssembler* assembler = compiler->macro_assembler();

  if (trace->characters_preloaded() != details->characters()) {
    ASSERT(trace->cp_offset() == bounds_check_trace->cp_offset());
    // We are attempting to preload the minimum number of characters
    // any choice would eat, so if the bounds check fails, then none of the
    // choices can succeed, so we can just immediately backtrack, rather
    // than go to the next choice.
    assembler->LoadCurrentCharacter(
        trace->cp_offset(), bounds_check_trace->backtrack(),
        !preload_has_checked_bounds, details->characters());
  }

  bool need_mask = true;

  if (details->characters() == 1) {
    // If number of characters preloaded is 1 then we used a byte or 16 bit
    // load so the value is already masked down.
    uint32_t char_mask;
    if (compiler->one_byte()) {
      char_mask = Symbols::kMaxOneCharCodeSymbol;
    } else {
      char_mask = Utf16::kMaxCodeUnit;
    }
    if ((mask & char_mask) == char_mask) need_mask = false;
    mask &= char_mask;
  } else {
    // For 2-character preloads in one-byte mode or 1-character preloads in
    // two-byte mode we also use a 16 bit load with zero extend.
    if (details->characters() == 2 && compiler->one_byte()) {
      if ((mask & 0xffff) == 0xffff) need_mask = false;
    } else if (details->characters() == 1 && !compiler->one_byte()) {
      if ((mask & 0xffff) == 0xffff) need_mask = false;
    } else {
      if (mask == 0xffffffff) need_mask = false;
    }
  }

  if (fall_through_on_failure) {
    if (need_mask) {
      assembler->CheckCharacterAfterAnd(value, mask, on_possible_success);
    } else {
      assembler->CheckCharacter(value, on_possible_success);
    }
  } else {
    if (need_mask) {
      assembler->CheckNotCharacterAfterAnd(value, mask, trace->backtrack());
    } else {
      assembler->CheckNotCharacter(value, trace->backtrack());
    }
  }
  return true;
}

// Here is the meat of GetQuickCheckDetails (see also the comment on the
// super-class in the .h file).
//
// We iterate along the text object, building up for each character a
// mask and value that can be used to test for a quick failure to match.
// The masks and values for the positions will be combined into a single
// machine word for the current character width in order to be used in
// generating a quick check.
void TextNode::GetQuickCheckDetails(QuickCheckDetails* details,
                                    RegExpCompiler* compiler,
                                    intptr_t characters_filled_in,
                                    bool not_at_start) {
#if defined(__GNUC__) && defined(__BYTE_ORDER__)
  // TODO(zerny): Make the combination code byte-order independent.
  ASSERT(details->characters() == 1 ||
         (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__));
#endif
  // Do not collect any quick check details if the text node reads backward,
  // since it reads in the opposite direction than we use for quick checks.
  if (read_backward()) return;
  ASSERT(characters_filled_in < details->characters());
  intptr_t characters = details->characters();
  int32_t char_mask;
  if (compiler->one_byte()) {
    char_mask = Symbols::kMaxOneCharCodeSymbol;
  } else {
    char_mask = Utf16::kMaxCodeUnit;
  }
  for (intptr_t k = 0; k < elms_->length(); k++) {
    TextElement elm = elms_->At(k);
    if (elm.text_type() == TextElement::ATOM) {
      ZoneGrowableArray<uint16_t>* quarks = elm.atom()->data();
      for (intptr_t i = 0; i < characters && i < quarks->length(); i++) {
        QuickCheckDetails::Position* pos =
            details->positions(characters_filled_in);
        uint16_t c = quarks->At(i);
        if (c > char_mask) {
          // If we expect a non-Latin1 character from an one-byte string,
          // there is no way we can match. Not even case independent
          // matching can turn an Latin1 character into non-Latin1 or
          // vice versa.
          // TODO(dcarney): issue 3550.  Verify that this works as expected.
          // For example, \u0178 is uppercase of \u00ff (y-umlaut).
          details->set_cannot_match();
          pos->determines_perfectly = false;
          return;
        }
        if (elm.atom()->ignore_case()) {
          int32_t chars[unibrow::Ecma262UnCanonicalize::kMaxWidth];
          intptr_t length =
              GetCaseIndependentLetters(c, compiler->one_byte(), chars);
          ASSERT(length != 0);  // Can only happen if c > char_mask (see above).
          if (length == 1) {
            // This letter has no case equivalents, so it's nice and simple
            // and the mask-compare will determine definitely whether we have
            // a match at this character position.
            pos->mask = char_mask;
            pos->value = c;
            pos->determines_perfectly = true;
          } else {
            uint32_t common_bits = char_mask;
            uint32_t bits = chars[0];
            for (intptr_t j = 1; j < length; j++) {
              uint32_t differing_bits = ((chars[j] & common_bits) ^ bits);
              common_bits ^= differing_bits;
              bits &= common_bits;
            }
            // If length is 2 and common bits has only one zero in it then
            // our mask and compare instruction will determine definitely
            // whether we have a match at this character position.  Otherwise
            // it can only be an approximate check.
            uint32_t one_zero = (common_bits | ~char_mask);
            if (length == 2 && ((~one_zero) & ((~one_zero) - 1)) == 0) {
              pos->determines_perfectly = true;
            }
            pos->mask = common_bits;
            pos->value = bits;
          }
        } else {
          // Don't ignore case.  Nice simple case where the mask-compare will
          // determine definitely whether we have a match at this character
          // position.
          pos->mask = char_mask;
          pos->value = c;
          pos->determines_perfectly = true;
        }
        characters_filled_in++;
        ASSERT(characters_filled_in <= details->characters());
        if (characters_filled_in == details->characters()) {
          return;
        }
      }
    } else {
      QuickCheckDetails::Position* pos =
          details->positions(characters_filled_in);
      RegExpCharacterClass* tree = elm.char_class();
      ZoneGrowableArray<CharacterRange>* ranges = tree->ranges();
      ASSERT(!ranges->is_empty());
      if (tree->is_negated()) {
        // A quick check uses multi-character mask and compare.  There is no
        // useful way to incorporate a negative char class into this scheme
        // so we just conservatively create a mask and value that will always
        // succeed.
        pos->mask = 0;
        pos->value = 0;
      } else {
        intptr_t first_range = 0;
        while (ranges->At(first_range).from() > char_mask) {
          first_range++;
          if (first_range == ranges->length()) {
            details->set_cannot_match();
            pos->determines_perfectly = false;
            return;
          }
        }
        CharacterRange range = ranges->At(first_range);
        uint16_t from = range.from();
        uint16_t to = range.to();
        if (to > char_mask) {
          to = char_mask;
        }
        uint32_t differing_bits = (from ^ to);
        // A mask and compare is only perfect if the differing bits form a
        // number like 00011111 with one single block of trailing 1s.
        if ((differing_bits & (differing_bits + 1)) == 0 &&
            from + differing_bits == to) {
          pos->determines_perfectly = true;
        }
        uint32_t common_bits = ~SmearBitsRight(differing_bits);
        uint32_t bits = (from & common_bits);
        for (intptr_t i = first_range + 1; i < ranges->length(); i++) {
          CharacterRange range = ranges->At(i);
          uint16_t from = range.from();
          uint16_t to = range.to();
          if (from > char_mask) continue;
          if (to > char_mask) to = char_mask;
          // Here we are combining more ranges into the mask and compare
          // value.  With each new range the mask becomes more sparse and
          // so the chances of a false positive rise.  A character class
          // with multiple ranges is assumed never to be equivalent to a
          // mask and compare operation.
          pos->determines_perfectly = false;
          uint32_t new_common_bits = (from ^ to);
          new_common_bits = ~SmearBitsRight(new_common_bits);
          common_bits &= new_common_bits;
          bits &= new_common_bits;
          uint32_t differing_bits = (from & common_bits) ^ bits;
          common_bits ^= differing_bits;
          bits &= common_bits;
        }
        pos->mask = common_bits;
        pos->value = bits;
      }
      characters_filled_in++;
      ASSERT(characters_filled_in <= details->characters());
      if (characters_filled_in == details->characters()) {
        return;
      }
    }
  }
  ASSERT(characters_filled_in != details->characters());
  if (!details->cannot_match()) {
    on_success()->GetQuickCheckDetails(details, compiler, characters_filled_in,
                                       true);
  }
}

void QuickCheckDetails::Clear() {
  for (int i = 0; i < characters_; i++) {
    positions_[i].mask = 0;
    positions_[i].value = 0;
    positions_[i].determines_perfectly = false;
  }
  characters_ = 0;
}

void QuickCheckDetails::Advance(intptr_t by, bool one_byte) {
  if (by >= characters_ || by < 0) {
    // check that by < 0 => characters_ == 0
    ASSERT(by >= 0 || characters_ == 0);
    Clear();
    return;
  }
  for (intptr_t i = 0; i < characters_ - by; i++) {
    positions_[i] = positions_[by + i];
  }
  for (intptr_t i = characters_ - by; i < characters_; i++) {
    positions_[i].mask = 0;
    positions_[i].value = 0;
    positions_[i].determines_perfectly = false;
  }
  characters_ -= by;
  // We could change mask_ and value_ here but we would never advance unless
  // they had already been used in a check and they won't be used again because
  // it would gain us nothing.  So there's no point.
}

void QuickCheckDetails::Merge(QuickCheckDetails* other, intptr_t from_index) {
  ASSERT(characters_ == other->characters_);
  if (other->cannot_match_) {
    return;
  }
  if (cannot_match_) {
    *this = *other;
    return;
  }
  for (intptr_t i = from_index; i < characters_; i++) {
    QuickCheckDetails::Position* pos = positions(i);
    QuickCheckDetails::Position* other_pos = other->positions(i);
    if (pos->mask != other_pos->mask || pos->value != other_pos->value ||
        !other_pos->determines_perfectly) {
      // Our mask-compare operation will be approximate unless we have the
      // exact same operation on both sides of the alternation.
      pos->determines_perfectly = false;
    }
    pos->mask &= other_pos->mask;
    pos->value &= pos->mask;
    other_pos->value &= pos->mask;
    uint16_t differing_bits = (pos->value ^ other_pos->value);
    pos->mask &= ~differing_bits;
    pos->value &= pos->mask;
  }
}

class VisitMarker : public ValueObject {
 public:
  explicit VisitMarker(NodeInfo* info) : info_(info) {
    ASSERT(!info->visited);
    info->visited = true;
  }
  ~VisitMarker() { info_->visited = false; }

 private:
  NodeInfo* info_;
};

RegExpNode* SeqRegExpNode::FilterOneByte(intptr_t depth) {
  if (info()->replacement_calculated) return replacement();
  if (depth < 0) return this;
  ASSERT(!info()->visited);
  VisitMarker marker(info());
  return FilterSuccessor(depth - 1);
}

RegExpNode* SeqRegExpNode::FilterSuccessor(intptr_t depth) {
  RegExpNode* next = on_success_->FilterOneByte(depth - 1);
  if (next == NULL) return set_replacement(NULL);
  on_success_ = next;
  return set_replacement(this);
}

// We need to check for the following characters: 0x39c 0x3bc 0x178.
static inline bool RangeContainsLatin1Equivalents(CharacterRange range) {
  // TODO(dcarney): this could be a lot more efficient.
  return range.Contains(0x39c) || range.Contains(0x3bc) ||
         range.Contains(0x178);
}

static bool RangesContainLatin1Equivalents(
    ZoneGrowableArray<CharacterRange>* ranges) {
  for (intptr_t i = 0; i < ranges->length(); i++) {
    // TODO(dcarney): this could be a lot more efficient.
    if (RangeContainsLatin1Equivalents(ranges->At(i))) return true;
  }
  return false;
}

static uint16_t ConvertNonLatin1ToLatin1(uint16_t c) {
  ASSERT(c > Symbols::kMaxOneCharCodeSymbol);
  switch (c) {
    // This are equivalent characters in unicode.
    case 0x39c:
    case 0x3bc:
      return 0xb5;
    // This is an uppercase of a Latin-1 character
    // outside of Latin-1.
    case 0x178:
      return 0xff;
  }
  return 0;
}

RegExpNode* TextNode::FilterOneByte(intptr_t depth) {
  if (info()->replacement_calculated) return replacement();
  if (depth < 0) return this;
  ASSERT(!info()->visited);
  VisitMarker marker(info());
  intptr_t element_count = elms_->length();
  for (intptr_t i = 0; i < element_count; i++) {
    TextElement elm = elms_->At(i);
    if (elm.text_type() == TextElement::ATOM) {
      ZoneGrowableArray<uint16_t>* quarks = elm.atom()->data();
      for (intptr_t j = 0; j < quarks->length(); j++) {
        uint16_t c = quarks->At(j);
        if (c <= Symbols::kMaxOneCharCodeSymbol) continue;
        if (!elm.atom()->ignore_case()) return set_replacement(NULL);
        // Here, we need to check for characters whose upper and lower cases
        // are outside the Latin-1 range.
        uint16_t converted = ConvertNonLatin1ToLatin1(c);
        // Character is outside Latin-1 completely
        if (converted == 0) return set_replacement(NULL);
        // Convert quark to Latin-1 in place.
        (*quarks)[0] = converted;
      }
    } else {
      ASSERT(elm.text_type() == TextElement::CHAR_CLASS);
      RegExpCharacterClass* cc = elm.char_class();
      ZoneGrowableArray<CharacterRange>* ranges = cc->ranges();
      if (!CharacterRange::IsCanonical(ranges)) {
        CharacterRange::Canonicalize(ranges);
      }
      // Now they are in order so we only need to look at the first.
      intptr_t range_count = ranges->length();
      if (cc->is_negated()) {
        if (range_count != 0 && ranges->At(0).from() == 0 &&
            ranges->At(0).to() >= Symbols::kMaxOneCharCodeSymbol) {
          // This will be handled in a later filter.
          if (cc->flags().IgnoreCase() &&
              RangesContainLatin1Equivalents(ranges)) {
            continue;
          }
          return set_replacement(NULL);
        }
      } else {
        if (range_count == 0 ||
            ranges->At(0).from() > Symbols::kMaxOneCharCodeSymbol) {
          // This will be handled in a later filter.
          if (cc->flags().IgnoreCase() &&
              RangesContainLatin1Equivalents(ranges))
            continue;
          return set_replacement(NULL);
        }
      }
    }
  }
  return FilterSuccessor(depth - 1);
}

RegExpNode* LoopChoiceNode::FilterOneByte(intptr_t depth) {
  if (info()->replacement_calculated) return replacement();
  if (depth < 0) return this;
  if (info()->visited) return this;
  {
    VisitMarker marker(info());

    RegExpNode* continue_replacement = continue_node_->FilterOneByte(depth - 1);
    // If we can't continue after the loop then there is no sense in doing the
    // loop.
    if (continue_replacement == NULL) return set_replacement(NULL);
  }

  return ChoiceNode::FilterOneByte(depth - 1);
}

RegExpNode* ChoiceNode::FilterOneByte(intptr_t depth) {
  if (info()->replacement_calculated) return replacement();
  if (depth < 0) return this;
  if (info()->visited) return this;
  VisitMarker marker(info());
  intptr_t choice_count = alternatives_->length();

  for (intptr_t i = 0; i < choice_count; i++) {
    GuardedAlternative alternative = alternatives_->At(i);
    if (alternative.guards() != NULL && alternative.guards()->length() != 0) {
      set_replacement(this);
      return this;
    }
  }

  intptr_t surviving = 0;
  RegExpNode* survivor = NULL;
  for (intptr_t i = 0; i < choice_count; i++) {
    GuardedAlternative alternative = alternatives_->At(i);
    RegExpNode* replacement = alternative.node()->FilterOneByte(depth - 1);
    ASSERT(replacement != this);  // No missing EMPTY_MATCH_CHECK.
    if (replacement != NULL) {
      (*alternatives_)[i].set_node(replacement);
      surviving++;
      survivor = replacement;
    }
  }
  if (surviving < 2) return set_replacement(survivor);

  set_replacement(this);
  if (surviving == choice_count) {
    return this;
  }
  // Only some of the nodes survived the filtering.  We need to rebuild the
  // alternatives list.
  ZoneGrowableArray<GuardedAlternative>* new_alternatives =
      new (Z) ZoneGrowableArray<GuardedAlternative>(surviving);
  for (intptr_t i = 0; i < choice_count; i++) {
    RegExpNode* replacement =
        (*alternatives_)[i].node()->FilterOneByte(depth - 1);
    if (replacement != NULL) {
      (*alternatives_)[i].set_node(replacement);
      new_alternatives->Add((*alternatives_)[i]);
    }
  }
  alternatives_ = new_alternatives;
  return this;
}

RegExpNode* NegativeLookaroundChoiceNode::FilterOneByte(intptr_t depth) {
  if (info()->replacement_calculated) return replacement();
  if (depth < 0) return this;
  if (info()->visited) return this;
  VisitMarker marker(info());
  // Alternative 0 is the negative lookahead, alternative 1 is what comes
  // afterwards.
  RegExpNode* node = (*alternatives_)[1].node();
  RegExpNode* replacement = node->FilterOneByte(depth - 1);
  if (replacement == NULL) return set_replacement(NULL);
  (*alternatives_)[1].set_node(replacement);

  RegExpNode* neg_node = (*alternatives_)[0].node();
  RegExpNode* neg_replacement = neg_node->FilterOneByte(depth - 1);
  // If the negative lookahead is always going to fail then
  // we don't need to check it.
  if (neg_replacement == NULL) return set_replacement(replacement);
  (*alternatives_)[0].set_node(neg_replacement);
  return set_replacement(this);
}

void LoopChoiceNode::GetQuickCheckDetails(QuickCheckDetails* details,
                                          RegExpCompiler* compiler,
                                          intptr_t characters_filled_in,
                                          bool not_at_start) {
  if (body_can_be_zero_length_ || info()->visited) return;
  VisitMarker marker(info());
  return ChoiceNode::GetQuickCheckDetails(details, compiler,
                                          characters_filled_in, not_at_start);
}

void LoopChoiceNode::FillInBMInfo(intptr_t offset,
                                  intptr_t budget,
                                  BoyerMooreLookahead* bm,
                                  bool not_at_start) {
  if (body_can_be_zero_length_ || budget <= 0) {
    bm->SetRest(offset);
    SaveBMInfo(bm, not_at_start, offset);
    return;
  }
  ChoiceNode::FillInBMInfo(offset, budget - 1, bm, not_at_start);
  SaveBMInfo(bm, not_at_start, offset);
}

void ChoiceNode::GetQuickCheckDetails(QuickCheckDetails* details,
                                      RegExpCompiler* compiler,
                                      intptr_t characters_filled_in,
                                      bool not_at_start) {
  not_at_start = (not_at_start || not_at_start_);
  intptr_t choice_count = alternatives_->length();
  ASSERT(choice_count > 0);
  (*alternatives_)[0].node()->GetQuickCheckDetails(
      details, compiler, characters_filled_in, not_at_start);
  for (intptr_t i = 1; i < choice_count; i++) {
    QuickCheckDetails new_details(details->characters());
    RegExpNode* node = (*alternatives_)[i].node();
    node->GetQuickCheckDetails(&new_details, compiler, characters_filled_in,
                               not_at_start);
    // Here we merge the quick match details of the two branches.
    details->Merge(&new_details, characters_filled_in);
  }
}

// Check for [0-9A-Z_a-z].
static void EmitWordCheck(RegExpMacroAssembler* assembler,
                          BlockLabel* word,
                          BlockLabel* non_word,
                          bool fall_through_on_word) {
  if (assembler->CheckSpecialCharacterClass(
          fall_through_on_word ? 'w' : 'W',
          fall_through_on_word ? non_word : word)) {
    // Optimized implementation available.
    return;
  }
  assembler->CheckCharacterGT('z', non_word);
  assembler->CheckCharacterLT('0', non_word);
  assembler->CheckCharacterGT('a' - 1, word);
  assembler->CheckCharacterLT('9' + 1, word);
  assembler->CheckCharacterLT('A', non_word);
  assembler->CheckCharacterLT('Z' + 1, word);
  if (fall_through_on_word) {
    assembler->CheckNotCharacter('_', non_word);
  } else {
    assembler->CheckCharacter('_', word);
  }
}

// Emit the code to check for a ^ in multiline mode (1-character lookbehind
// that matches newline or the start of input).
static void EmitHat(RegExpCompiler* compiler,
                    RegExpNode* on_success,
                    Trace* trace) {
  RegExpMacroAssembler* assembler = compiler->macro_assembler();
  // We will be loading the previous character into the current character
  // register.
  Trace new_trace(*trace);
  new_trace.InvalidateCurrentCharacter();

  BlockLabel ok;
  if (new_trace.cp_offset() == 0) {
    // The start of input counts as a newline in this context, so skip to
    // ok if we are at the start.
    assembler->CheckAtStart(&ok);
  }
  // We already checked that we are not at the start of input so it must be
  // OK to load the previous character.
  assembler->LoadCurrentCharacter(new_trace.cp_offset() - 1,
                                  new_trace.backtrack(), false);
  if (!assembler->CheckSpecialCharacterClass('n', new_trace.backtrack())) {
    // Newline means \n, \r, 0x2028 or 0x2029.
    if (!compiler->one_byte()) {
      assembler->CheckCharacterAfterAnd(0x2028, 0xfffe, &ok);
    }
    assembler->CheckCharacter('\n', &ok);
    assembler->CheckNotCharacter('\r', new_trace.backtrack());
  }
  assembler->BindBlock(&ok);
  on_success->Emit(compiler, &new_trace);
}

// Emit the code to handle \b and \B (word-boundary or non-word-boundary).
void AssertionNode::EmitBoundaryCheck(RegExpCompiler* compiler, Trace* trace) {
  RegExpMacroAssembler* assembler = compiler->macro_assembler();
  Trace::TriBool next_is_word_character = Trace::UNKNOWN;
  bool not_at_start = (trace->at_start() == Trace::FALSE_VALUE);
  BoyerMooreLookahead* lookahead = bm_info(not_at_start);
  if (lookahead == NULL) {
    intptr_t eats_at_least =
        Utils::Minimum(kMaxLookaheadForBoyerMoore,
                       EatsAtLeast(kMaxLookaheadForBoyerMoore, kRecursionBudget,
                                   not_at_start));
    if (eats_at_least >= 1) {
      BoyerMooreLookahead* bm =
          new (Z) BoyerMooreLookahead(eats_at_least, compiler, Z);
      FillInBMInfo(0, kRecursionBudget, bm, not_at_start);
      if (bm->at(0)->is_non_word()) next_is_word_character = Trace::FALSE_VALUE;
      if (bm->at(0)->is_word()) next_is_word_character = Trace::TRUE_VALUE;
    }
  } else {
    if (lookahead->at(0)->is_non_word())
      next_is_word_character = Trace::FALSE_VALUE;
    if (lookahead->at(0)->is_word()) next_is_word_character = Trace::TRUE_VALUE;
  }
  bool at_boundary = (assertion_type_ == AssertionNode::AT_BOUNDARY);
  if (next_is_word_character == Trace::UNKNOWN) {
    BlockLabel before_non_word;
    BlockLabel before_word;
    if (trace->characters_preloaded() != 1) {
      assembler->LoadCurrentCharacter(trace->cp_offset(), &before_non_word);
    }
    // Fall through on non-word.
    EmitWordCheck(assembler, &before_word, &before_non_word, false);
    // Next character is not a word character.
    assembler->BindBlock(&before_non_word);
    BlockLabel ok;
    // Backtrack on \B (non-boundary check) if previous is a word,
    // since we know next *is not* a word and this would be a boundary.
    BacktrackIfPrevious(compiler, trace, at_boundary ? kIsNonWord : kIsWord);

    if (!assembler->IsClosed()) {
      assembler->GoTo(&ok);
    }

    assembler->BindBlock(&before_word);
    BacktrackIfPrevious(compiler, trace, at_boundary ? kIsWord : kIsNonWord);
    assembler->BindBlock(&ok);
  } else if (next_is_word_character == Trace::TRUE_VALUE) {
    BacktrackIfPrevious(compiler, trace, at_boundary ? kIsWord : kIsNonWord);
  } else {
    ASSERT(next_is_word_character == Trace::FALSE_VALUE);
    BacktrackIfPrevious(compiler, trace, at_boundary ? kIsNonWord : kIsWord);
  }
}

void AssertionNode::BacktrackIfPrevious(
    RegExpCompiler* compiler,
    Trace* trace,
    AssertionNode::IfPrevious backtrack_if_previous) {
  RegExpMacroAssembler* assembler = compiler->macro_assembler();
  Trace new_trace(*trace);
  new_trace.InvalidateCurrentCharacter();

  BlockLabel fall_through, dummy;

  BlockLabel* non_word = backtrack_if_previous == kIsNonWord
                             ? new_trace.backtrack()
                             : &fall_through;
  BlockLabel* word = backtrack_if_previous == kIsNonWord
                         ? &fall_through
                         : new_trace.backtrack();

  if (new_trace.cp_offset() == 0) {
    // The start of input counts as a non-word character, so the question is
    // decided if we are at the start.
    assembler->CheckAtStart(non_word);
  }
  // We already checked that we are not at the start of input so it must be
  // OK to load the previous character.
  assembler->LoadCurrentCharacter(new_trace.cp_offset() - 1, &dummy, false);
  EmitWordCheck(assembler, word, non_word, backtrack_if_previous == kIsNonWord);

  assembler->BindBlock(&fall_through);
  on_success()->Emit(compiler, &new_trace);
}

void AssertionNode::GetQuickCheckDetails(QuickCheckDetails* details,
                                         RegExpCompiler* compiler,
                                         intptr_t filled_in,
                                         bool not_at_start) {
  if (assertion_type_ == AT_START && not_at_start) {
    details->set_cannot_match();
    return;
  }
  return on_success()->GetQuickCheckDetails(details, compiler, filled_in,
                                            not_at_start);
}

void AssertionNode::Emit(RegExpCompiler* compiler, Trace* trace) {
  RegExpMacroAssembler* assembler = compiler->macro_assembler();
  switch (assertion_type_) {
    case AT_END: {
      BlockLabel ok;
      assembler->CheckPosition(trace->cp_offset(), &ok);
      assembler->GoTo(trace->backtrack());
      assembler->BindBlock(&ok);
      break;
    }
    case AT_START: {
      if (trace->at_start() == Trace::FALSE_VALUE) {
        assembler->GoTo(trace->backtrack());
        return;
      }
      if (trace->at_start() == Trace::UNKNOWN) {
        assembler->CheckNotAtStart(trace->cp_offset(), trace->backtrack());
        Trace at_start_trace = *trace;
        at_start_trace.set_at_start(Trace::TRUE_VALUE);
        on_success()->Emit(compiler, &at_start_trace);
        return;
      }
    } break;
    case AFTER_NEWLINE:
      EmitHat(compiler, on_success(), trace);
      return;
    case AT_BOUNDARY:
    case AT_NON_BOUNDARY: {
      EmitBoundaryCheck(compiler, trace);
      return;
    }
  }
  on_success()->Emit(compiler, trace);
}

static bool DeterminedAlready(QuickCheckDetails* quick_check, intptr_t offset) {
  if (quick_check == NULL) return false;
  if (offset >= quick_check->characters()) return false;
  return quick_check->positions(offset)->determines_perfectly;
}

static void UpdateBoundsCheck(intptr_t index, intptr_t* checked_up_to) {
  if (index > *checked_up_to) {
    *checked_up_to = index;
  }
}

// We call this repeatedly to generate code for each pass over the text node.
// The passes are in increasing order of difficulty because we hope one
// of the first passes will fail in which case we are saved the work of the
// later passes.  for example for the case independent regexp /%[asdfghjkl]a/
// we will check the '%' in the first pass, the case independent 'a' in the
// second pass and the character class in the last pass.
//
// The passes are done from right to left, so for example to test for /bar/
// we will first test for an 'r' with offset 2, then an 'a' with offset 1
// and then a 'b' with offset 0.  This means we can avoid the end-of-input
// bounds check most of the time.  In the example we only need to check for
// end-of-input when loading the putative 'r'.
//
// A slight complication involves the fact that the first character may already
// be fetched into a register by the previous node.  In this case we want to
// do the test for that character first.  We do this in separate passes.  The
// 'preloaded' argument indicates that we are doing such a 'pass'.  If such a
// pass has been performed then subsequent passes will have true in
// first_element_checked to indicate that that character does not need to be
// checked again.
//
// In addition to all this we are passed a Trace, which can
// contain an AlternativeGeneration object.  In this AlternativeGeneration
// object we can see details of any quick check that was already passed in
// order to get to the code we are now generating.  The quick check can involve
// loading characters, which means we do not need to recheck the bounds
// up to the limit the quick check already checked.  In addition the quick
// check can have involved a mask and compare operation which may simplify
// or obviate the need for further checks at some character positions.
void TextNode::TextEmitPass(RegExpCompiler* compiler,
                            TextEmitPassType pass,
                            bool preloaded,
                            Trace* trace,
                            bool first_element_checked,
                            intptr_t* checked_up_to) {
  RegExpMacroAssembler* assembler = compiler->macro_assembler();
  bool one_byte = compiler->one_byte();
  BlockLabel* backtrack = trace->backtrack();
  QuickCheckDetails* quick_check = trace->quick_check_performed();
  intptr_t element_count = elms_->length();
  intptr_t backward_offset = read_backward() ? -Length() : 0;
  for (intptr_t i = preloaded ? 0 : element_count - 1; i >= 0; i--) {
    TextElement elm = elms_->At(i);
    intptr_t cp_offset = trace->cp_offset() + elm.cp_offset() + backward_offset;
    if (elm.text_type() == TextElement::ATOM) {
      ZoneGrowableArray<uint16_t>* quarks = elm.atom()->data();
      for (intptr_t j = preloaded ? 0 : quarks->length() - 1; j >= 0; j--) {
        if (SkipPass(pass, elm.atom()->ignore_case())) continue;
        if (first_element_checked && i == 0 && j == 0) continue;
        if (DeterminedAlready(quick_check, elm.cp_offset() + j)) continue;
        EmitCharacterFunction* emit_function = NULL;
        uint16_t quark = quarks->At(j);
        if (elm.atom()->ignore_case()) {
          // Everywhere else we assume that a non-Latin-1 character cannot match
          // a Latin-1 character. Avoid the cases where this is assumption is
          // invalid by using the Latin1 equivalent instead.
          quark = Latin1::TryConvertToLatin1(quark);
        }
        switch (pass) {
          case NON_LATIN1_MATCH:
            ASSERT(one_byte);
            if (quark > Symbols::kMaxOneCharCodeSymbol) {
              assembler->GoTo(backtrack);
              return;
            }
            break;
          case NON_LETTER_CHARACTER_MATCH:
            emit_function = &EmitAtomNonLetter;
            break;
          case SIMPLE_CHARACTER_MATCH:
            emit_function = &EmitSimpleCharacter;
            break;
          case CASE_CHARACTER_MATCH:
            emit_function = &EmitAtomLetter;
            break;
          default:
            break;
        }
        if (emit_function != NULL) {
          const bool bounds_check =
              *checked_up_to < (cp_offset + j) || read_backward();
          bool bound_checked =
              emit_function(Z, compiler, quarks->At(j), backtrack,
                            cp_offset + j, bounds_check, preloaded);
          if (bound_checked) UpdateBoundsCheck(cp_offset + j, checked_up_to);
        }
      }
    } else {
      ASSERT(elm.text_type() == TextElement::CHAR_CLASS);
      if (pass == CHARACTER_CLASS_MATCH) {
        if (first_element_checked && i == 0) continue;
        if (DeterminedAlready(quick_check, elm.cp_offset())) continue;
        RegExpCharacterClass* cc = elm.char_class();
        bool bounds_check = *checked_up_to < cp_offset || read_backward();
        EmitCharClass(assembler, cc, one_byte, backtrack, cp_offset,
                      bounds_check, preloaded, Z);
        UpdateBoundsCheck(cp_offset, checked_up_to);
      }
    }
  }
}

intptr_t TextNode::Length() {
  TextElement elm = elms_->Last();
  ASSERT(elm.cp_offset() >= 0);
  return elm.cp_offset() + elm.length();
}

bool TextNode::SkipPass(intptr_t intptr_t_pass, bool ignore_case) {
  TextEmitPassType pass = static_cast<TextEmitPassType>(intptr_t_pass);
  if (ignore_case) {
    return pass == SIMPLE_CHARACTER_MATCH;
  } else {
    return pass == NON_LETTER_CHARACTER_MATCH || pass == CASE_CHARACTER_MATCH;
  }
}

TextNode* TextNode::CreateForCharacterRanges(
    ZoneGrowableArray<CharacterRange>* ranges,
    bool read_backward,
    RegExpNode* on_success,
    RegExpFlags flags) {
  ASSERT(ranges != nullptr);
  ZoneGrowableArray<TextElement>* elms = new ZoneGrowableArray<TextElement>(1);
  elms->Add(TextElement::CharClass(new RegExpCharacterClass(ranges, flags)));
  return new TextNode(elms, read_backward, on_success);
}

TextNode* TextNode::CreateForSurrogatePair(CharacterRange lead,
                                           CharacterRange trail,
                                           bool read_backward,
                                           RegExpNode* on_success,
                                           RegExpFlags flags) {
  auto lead_ranges = CharacterRange::List(on_success->zone(), lead);
  auto trail_ranges = CharacterRange::List(on_success->zone(), trail);
  auto elms = new ZoneGrowableArray<TextElement>(2);

  elms->Add(
      TextElement::CharClass(new RegExpCharacterClass(lead_ranges, flags)));
  elms->Add(
      TextElement::CharClass(new RegExpCharacterClass(trail_ranges, flags)));

  return new TextNode(elms, read_backward, on_success);
}

// This generates the code to match a text node.  A text node can contain
// straight character sequences (possibly to be matched in a case-independent
// way) and character classes.  For efficiency we do not do this in a single
// pass from left to right.  Instead we pass over the text node several times,
// emitting code for some character positions every time.  See the comment on
// TextEmitPass for details.
void TextNode::Emit(RegExpCompiler* compiler, Trace* trace) {
  LimitResult limit_result = LimitVersions(compiler, trace);
  if (limit_result == DONE) return;
  ASSERT(limit_result == CONTINUE);

  if (trace->cp_offset() + Length() > RegExpMacroAssembler::kMaxCPOffset) {
    compiler->SetRegExpTooBig();
    return;
  }

  if (compiler->one_byte()) {
    intptr_t dummy = 0;
    TextEmitPass(compiler, NON_LATIN1_MATCH, false, trace, false, &dummy);
  }

  bool first_elt_done = false;
  intptr_t bound_checked_to = trace->cp_offset() - 1;
  bound_checked_to += trace->bound_checked_up_to();

  // If a character is preloaded into the current character register then
  // check that now.
  if (trace->characters_preloaded() == 1) {
    for (intptr_t pass = kFirstRealPass; pass <= kLastPass; pass++) {
      TextEmitPass(compiler, static_cast<TextEmitPassType>(pass), true, trace,
                   false, &bound_checked_to);
    }
    first_elt_done = true;
  }

  for (intptr_t pass = kFirstRealPass; pass <= kLastPass; pass++) {
    TextEmitPass(compiler, static_cast<TextEmitPassType>(pass), false, trace,
                 first_elt_done, &bound_checked_to);
  }

  Trace successor_trace(*trace);
  // If we advance backward, we may end up at the start.
  successor_trace.AdvanceCurrentPositionInTrace(
      read_backward() ? -Length() : Length(), compiler);
  successor_trace.set_at_start(read_backward() ? Trace::UNKNOWN
                                               : Trace::FALSE_VALUE);
  RecursionCheck rc(compiler);
  on_success()->Emit(compiler, &successor_trace);
}

void Trace::InvalidateCurrentCharacter() {
  characters_preloaded_ = 0;
}

void Trace::AdvanceCurrentPositionInTrace(intptr_t by,
                                          RegExpCompiler* compiler) {
  // We don't have an instruction for shifting the current character register
  // down or for using a shifted value for anything so lets just forget that
  // we preloaded any characters into it.
  characters_preloaded_ = 0;
  // Adjust the offsets of the quick check performed information.  This
  // information is used to find out what we already determined about the
  // characters by means of mask and compare.
  quick_check_performed_.Advance(by, compiler->one_byte());
  cp_offset_ += by;
  if (cp_offset_ > RegExpMacroAssembler::kMaxCPOffset) {
    compiler->SetRegExpTooBig();
    cp_offset_ = 0;
  }
  bound_checked_up_to_ =
      Utils::Maximum(static_cast<intptr_t>(0), bound_checked_up_to_ - by);
}

void TextNode::MakeCaseIndependent(bool is_one_byte) {
  intptr_t element_count = elms_->length();
  for (intptr_t i = 0; i < element_count; i++) {
    TextElement elm = elms_->At(i);
    if (elm.text_type() == TextElement::CHAR_CLASS) {
      RegExpCharacterClass* cc = elm.char_class();
      bool case_equivalents_already_added =
          cc->flags().NeedsUnicodeCaseEquivalents();
      if (cc->flags().IgnoreCase() && !case_equivalents_already_added) {
        // None of the standard character classes is different in the case
        // independent case and it slows us down if we don't know that.
        if (cc->is_standard()) continue;
        CharacterRange::AddCaseEquivalents(cc->ranges(), is_one_byte, Z);
      }
    }
  }
}

intptr_t TextNode::GreedyLoopTextLength() {
  TextElement elm = elms_->At(elms_->length() - 1);
  return elm.cp_offset() + elm.length();
}

RegExpNode* TextNode::GetSuccessorOfOmnivorousTextNode(
    RegExpCompiler* compiler) {
  if (read_backward()) return nullptr;
  if (elms_->length() != 1) return NULL;
  TextElement elm = elms_->At(0);
  if (elm.text_type() != TextElement::CHAR_CLASS) return NULL;
  RegExpCharacterClass* node = elm.char_class();
  ZoneGrowableArray<CharacterRange>* ranges = node->ranges();
  if (!CharacterRange::IsCanonical(ranges)) {
    CharacterRange::Canonicalize(ranges);
  }
  if (node->is_negated()) {
    return ranges->length() == 0 ? on_success() : NULL;
  }
  if (ranges->length() != 1) return NULL;
  uint32_t max_char;
  if (compiler->one_byte()) {
    max_char = Symbols::kMaxOneCharCodeSymbol;
  } else {
    max_char = Utf16::kMaxCodeUnit;
  }
  return ranges->At(0).IsEverything(max_char) ? on_success() : NULL;
}

// Finds the fixed match length of a sequence of nodes that goes from
// this alternative and back to this choice node.  If there are variable
// length nodes or other complications in the way then return a sentinel
// value indicating that a greedy loop cannot be constructed.
intptr_t ChoiceNode::GreedyLoopTextLengthForAlternative(
    const GuardedAlternative* alternative) {
  intptr_t length = 0;
  RegExpNode* node = alternative->node();
  // Later we will generate code for all these text nodes using recursion
  // so we have to limit the max number.
  intptr_t recursion_depth = 0;
  while (node != this) {
    if (recursion_depth++ > RegExpCompiler::kMaxRecursion) {
      return kNodeIsTooComplexForGreedyLoops;
    }
    intptr_t node_length = node->GreedyLoopTextLength();
    if (node_length == kNodeIsTooComplexForGreedyLoops) {
      return kNodeIsTooComplexForGreedyLoops;
    }
    length += node_length;
    SeqRegExpNode* seq_node = static_cast<SeqRegExpNode*>(node);
    node = seq_node->on_success();
  }
  return read_backward() ? -length : length;
}

void LoopChoiceNode::AddLoopAlternative(GuardedAlternative alt) {
  ASSERT(loop_node_ == NULL);
  AddAlternative(alt);
  loop_node_ = alt.node();
}

void LoopChoiceNode::AddContinueAlternative(GuardedAlternative alt) {
  ASSERT(continue_node_ == NULL);
  AddAlternative(alt);
  continue_node_ = alt.node();
}

void LoopChoiceNode::Emit(RegExpCompiler* compiler, Trace* trace) {
  RegExpMacroAssembler* macro_assembler = compiler->macro_assembler();
  if (trace->stop_node() == this) {
    // Back edge of greedy optimized loop node graph.
    intptr_t text_length =
        GreedyLoopTextLengthForAlternative(&alternatives_->At(0));
    ASSERT(text_length != kNodeIsTooComplexForGreedyLoops);
    // Update the counter-based backtracking info on the stack.  This is an
    // optimization for greedy loops (see below).
    ASSERT(trace->cp_offset() == text_length);
    macro_assembler->AdvanceCurrentPosition(text_length);
    macro_assembler->GoTo(trace->loop_label());
    return;
  }
  ASSERT(trace->stop_node() == NULL);
  if (!trace->is_trivial()) {
    trace->Flush(compiler, this);
    return;
  }
  ChoiceNode::Emit(compiler, trace);
}

intptr_t ChoiceNode::CalculatePreloadCharacters(RegExpCompiler* compiler,
                                                intptr_t eats_at_least) {
  intptr_t preload_characters =
      Utils::Minimum(static_cast<intptr_t>(4), eats_at_least);
  if (compiler->macro_assembler()->CanReadUnaligned()) {
    bool one_byte = compiler->one_byte();
    if (one_byte) {
      if (preload_characters > 4) preload_characters = 4;
      // We can't preload 3 characters because there is no machine instruction
      // to do that.  We can't just load 4 because we could be reading
      // beyond the end of the string, which could cause a memory fault.
      if (preload_characters == 3) preload_characters = 2;
    } else {
      if (preload_characters > 2) preload_characters = 2;
    }
  } else {
    if (preload_characters > 1) preload_characters = 1;
  }
  return preload_characters;
}

// This structure is used when generating the alternatives in a choice node.  It
// records the way the alternative is being code generated.
struct AlternativeGeneration {
  AlternativeGeneration()
      : possible_success(),
        expects_preload(false),
        after(),
        quick_check_details() {}
  BlockLabel possible_success;
  bool expects_preload;
  BlockLabel after;
  QuickCheckDetails quick_check_details;
};

// Creates a list of AlternativeGenerations.  If the list has a reasonable
// size then it is on the stack, otherwise the excess is on the heap.
class AlternativeGenerationList {
 public:
  explicit AlternativeGenerationList(intptr_t count) : count_(count) {
    ASSERT(count >= 0);
    if (count > kAFew) {
      excess_alt_gens_.reset(new AlternativeGeneration[count - kAFew]);
    }
  }

  AlternativeGeneration* at(intptr_t i) {
    ASSERT(0 <= i);
    ASSERT(i < count_);
    if (i < kAFew) {
      return &a_few_alt_gens_[i];
    }
    return &excess_alt_gens_[i - kAFew];
  }

 private:
  static const intptr_t kAFew = 10;

  intptr_t count_;
  AlternativeGeneration a_few_alt_gens_[kAFew];
  std::unique_ptr<AlternativeGeneration[]> excess_alt_gens_;

  DISALLOW_ALLOCATION();
  DISALLOW_COPY_AND_ASSIGN(AlternativeGenerationList);
};

static const int32_t kRangeEndMarker = Utf::kMaxCodePoint + 1;

// The '2' variant is inclusive from and exclusive to.
// This covers \s as defined in ECMA-262 5.1, 15.10.2.12,
// which include WhiteSpace (7.2) or LineTerminator (7.3) values.
// 0x180E has been removed from Unicode's Zs category and thus
// from ECMAScript's WhiteSpace category as of Unicode 6.3.
static const int32_t kSpaceRanges[] = {
    '\t',   '\r' + 1, ' ',    ' ' + 1, 0x00A0, 0x00A1, 0x1680,
    0x1681, 0x2000,   0x200B, 0x2028,  0x202A, 0x202F, 0x2030,
    0x205F, 0x2060,   0x3000, 0x3001,  0xFEFF, 0xFF00, kRangeEndMarker};
static const intptr_t kSpaceRangeCount = ARRAY_SIZE(kSpaceRanges);
static const int32_t kWordRanges[] = {
    '0', '9' + 1, 'A', 'Z' + 1, '_', '_' + 1, 'a', 'z' + 1, kRangeEndMarker};
static const intptr_t kWordRangeCount = ARRAY_SIZE(kWordRanges);
static const int32_t kDigitRanges[] = {'0', '9' + 1, kRangeEndMarker};
static const intptr_t kDigitRangeCount = ARRAY_SIZE(kDigitRanges);
static const int32_t kSurrogateRanges[] = {0xd800, 0xe000, kRangeEndMarker};
static const intptr_t kSurrogateRangeCount = ARRAY_SIZE(kSurrogateRanges);
static const int32_t kLineTerminatorRanges[] = {
    0x000A, 0x000B, 0x000D, 0x000E, 0x2028, 0x202A, kRangeEndMarker};
static const intptr_t kLineTerminatorRangeCount =
    ARRAY_SIZE(kLineTerminatorRanges);

void BoyerMoorePositionInfo::Set(intptr_t character) {
  SetInterval(Interval(character, character));
}

void BoyerMoorePositionInfo::SetInterval(const Interval& interval) {
  s_ = AddRange(s_, kSpaceRanges, kSpaceRangeCount, interval);
  w_ = AddRange(w_, kWordRanges, kWordRangeCount, interval);
  d_ = AddRange(d_, kDigitRanges, kDigitRangeCount, interval);
  surrogate_ =
      AddRange(surrogate_, kSurrogateRanges, kSurrogateRangeCount, interval);
  if (interval.to() - interval.from() >= kMapSize - 1) {
    if (map_count_ != kMapSize) {
      map_count_ = kMapSize;
      for (intptr_t i = 0; i < kMapSize; i++)
        (*map_)[i] = true;
    }
    return;
  }
  for (intptr_t i = interval.from(); i <= interval.to(); i++) {
    intptr_t mod_character = (i & kMask);
    if (!map_->At(mod_character)) {
      map_count_++;
      (*map_)[mod_character] = true;
    }
    if (map_count_ == kMapSize) return;
  }
}

void BoyerMoorePositionInfo::SetAll() {
  s_ = w_ = d_ = kLatticeUnknown;
  if (map_count_ != kMapSize) {
    map_count_ = kMapSize;
    for (intptr_t i = 0; i < kMapSize; i++)
      (*map_)[i] = true;
  }
}

BoyerMooreLookahead::BoyerMooreLookahead(intptr_t length,
                                         RegExpCompiler* compiler,
                                         Zone* zone)
    : length_(length), compiler_(compiler) {
  if (compiler->one_byte()) {
    max_char_ = Symbols::kMaxOneCharCodeSymbol;
  } else {
    max_char_ = Utf16::kMaxCodeUnit;
  }
  bitmaps_ = new (zone) ZoneGrowableArray<BoyerMoorePositionInfo*>(length);
  for (intptr_t i = 0; i < length; i++) {
    bitmaps_->Add(new (zone) BoyerMoorePositionInfo(zone));
  }
}

// Find the longest range of lookahead that has the fewest number of different
// characters that can occur at a given position.  Since we are optimizing two
// different parameters at once this is a tradeoff.
bool BoyerMooreLookahead::FindWorthwhileInterval(intptr_t* from, intptr_t* to) {
  intptr_t biggest_points = 0;
  // If more than 32 characters out of 128 can occur it is unlikely that we can
  // be lucky enough to step forwards much of the time.
  const intptr_t kMaxMax = 32;
  for (intptr_t max_number_of_chars = 4; max_number_of_chars < kMaxMax;
       max_number_of_chars *= 2) {
    biggest_points =
        FindBestInterval(max_number_of_chars, biggest_points, from, to);
  }
  if (biggest_points == 0) return false;
  return true;
}

// Find the highest-points range between 0 and length_ where the character
// information is not too vague.  'Too vague' means that there are more than
// max_number_of_chars that can occur at this position.  Calculates the number
// of points as the product of width-of-the-range and
// probability-of-finding-one-of-the-characters, where the probability is
// calculated using the frequency distribution of the sample subject string.
intptr_t BoyerMooreLookahead::FindBestInterval(intptr_t max_number_of_chars,
                                               intptr_t old_biggest_points,
                                               intptr_t* from,
                                               intptr_t* to) {
  intptr_t biggest_points = old_biggest_points;
  static const intptr_t kSize = RegExpMacroAssembler::kTableSize;
  for (intptr_t i = 0; i < length_;) {
    while (i < length_ && Count(i) > max_number_of_chars)
      i++;
    if (i == length_) break;
    intptr_t remembered_from = i;
    bool union_map[kSize];
    for (intptr_t j = 0; j < kSize; j++)
      union_map[j] = false;
    while (i < length_ && Count(i) <= max_number_of_chars) {
      BoyerMoorePositionInfo* map = bitmaps_->At(i);
      for (intptr_t j = 0; j < kSize; j++)
        union_map[j] |= map->at(j);
      i++;
    }
    intptr_t frequency = 0;
    for (intptr_t j = 0; j < kSize; j++) {
      if (union_map[j]) {
        // Add 1 to the frequency to give a small per-character boost for
        // the cases where our sampling is not good enough and many
        // characters have a frequency of zero.  This means the frequency
        // can theoretically be up to 2*kSize though we treat it mostly as
        // a fraction of kSize.
        frequency += compiler_->frequency_collator()->Frequency(j) + 1;
      }
    }
    // We use the probability of skipping times the distance we are skipping to
    // judge the effectiveness of this.  Actually we have a cut-off:  By
    // dividing by 2 we switch off the skipping if the probability of skipping
    // is less than 50%.  This is because the multibyte mask-and-compare
    // skipping in quickcheck is more likely to do well on this case.
    bool in_quickcheck_range =
        ((i - remembered_from < 4) ||
         (compiler_->one_byte() ? remembered_from <= 4 : remembered_from <= 2));
    // Called 'probability' but it is only a rough estimate and can actually
    // be outside the 0-kSize range.
    intptr_t probability =
        (in_quickcheck_range ? kSize / 2 : kSize) - frequency;
    intptr_t points = (i - remembered_from) * probability;
    if (points > biggest_points) {
      *from = remembered_from;
      *to = i - 1;
      biggest_points = points;
    }
  }
  return biggest_points;
}

// Take all the characters that will not prevent a successful match if they
// occur in the subject string in the range between min_lookahead and
// max_lookahead (inclusive) measured from the current position.  If the
// character at max_lookahead offset is not one of these characters, then we
// can safely skip forwards by the number of characters in the range.
intptr_t BoyerMooreLookahead::GetSkipTable(
    intptr_t min_lookahead,
    intptr_t max_lookahead,
    const TypedData& boolean_skip_table) {
  const intptr_t kSize = RegExpMacroAssembler::kTableSize;

  const intptr_t kSkipArrayEntry = 0;
  const intptr_t kDontSkipArrayEntry = 1;

  for (intptr_t i = 0; i < kSize; i++) {
    boolean_skip_table.SetUint8(i, kSkipArrayEntry);
  }
  intptr_t skip = max_lookahead + 1 - min_lookahead;

  for (intptr_t i = max_lookahead; i >= min_lookahead; i--) {
    BoyerMoorePositionInfo* map = bitmaps_->At(i);
    for (intptr_t j = 0; j < kSize; j++) {
      if (map->at(j)) {
        boolean_skip_table.SetUint8(j, kDontSkipArrayEntry);
      }
    }
  }

  return skip;
}

// See comment above on the implementation of GetSkipTable.
void BoyerMooreLookahead::EmitSkipInstructions(RegExpMacroAssembler* masm) {
  const intptr_t kSize = RegExpMacroAssembler::kTableSize;

  intptr_t min_lookahead = 0;
  intptr_t max_lookahead = 0;

  if (!FindWorthwhileInterval(&min_lookahead, &max_lookahead)) return;

  bool found_single_character = false;
  intptr_t single_character = 0;
  for (intptr_t i = max_lookahead; i >= min_lookahead; i--) {
    BoyerMoorePositionInfo* map = bitmaps_->At(i);
    if (map->map_count() > 1 ||
        (found_single_character && map->map_count() != 0)) {
      found_single_character = false;
      break;
    }
    for (intptr_t j = 0; j < kSize; j++) {
      if (map->at(j)) {
        found_single_character = true;
        single_character = j;
        break;
      }
    }
  }

  intptr_t lookahead_width = max_lookahead + 1 - min_lookahead;

  if (found_single_character && lookahead_width == 1 && max_lookahead < 3) {
    // The mask-compare can probably handle this better.
    return;
  }

  if (found_single_character) {
    BlockLabel cont, again;
    masm->BindBlock(&again);
    masm->LoadCurrentCharacter(max_lookahead, &cont, true);
    if (max_char_ > kSize) {
      masm->CheckCharacterAfterAnd(single_character,
                                   RegExpMacroAssembler::kTableMask, &cont);
    } else {
      masm->CheckCharacter(single_character, &cont);
    }
    masm->AdvanceCurrentPosition(lookahead_width);
    masm->GoTo(&again);
    masm->BindBlock(&cont);
    return;
  }

  const TypedData& boolean_skip_table = TypedData::ZoneHandle(
      compiler_->zone(),
      TypedData::New(kTypedDataUint8ArrayCid, kSize, Heap::kOld));
  intptr_t skip_distance =
      GetSkipTable(min_lookahead, max_lookahead, boolean_skip_table);
  ASSERT(skip_distance != 0);

  BlockLabel cont, again;

  masm->BindBlock(&again);
  masm->CheckPreemption(/*is_backtrack=*/false);
  masm->LoadCurrentCharacter(max_lookahead, &cont, true);
  masm->CheckBitInTable(boolean_skip_table, &cont);
  masm->AdvanceCurrentPosition(skip_distance);
  masm->GoTo(&again);
  masm->BindBlock(&cont);

  return;
}

/* Code generation for choice nodes.
 *
 * We generate quick checks that do a mask and compare to eliminate a
 * choice.  If the quick check succeeds then it jumps to the continuation to
 * do slow checks and check subsequent nodes.  If it fails (the common case)
 * it falls through to the next choice.
 *
 * Here is the desired flow graph.  Nodes directly below each other imply
 * fallthrough.  Alternatives 1 and 2 have quick checks.  Alternative
 * 3 doesn't have a quick check so we have to call the slow check.
 * Nodes are marked Qn for quick checks and Sn for slow checks.  The entire
 * regexp continuation is generated directly after the Sn node, up to the
 * next GoTo if we decide to reuse some already generated code.  Some
 * nodes expect preload_characters to be preloaded into the current
 * character register.  R nodes do this preloading.  Vertices are marked
 * F for failures and S for success (possible success in the case of quick
 * nodes).  L, V, < and > are used as arrow heads.
 *
 * ----------> R
 *             |
 *             V
 *            Q1 -----> S1
 *             |   S   /
 *            F|      /
 *             |    F/
 *             |    /
 *             |   R
 *             |  /
 *             V L
 *            Q2 -----> S2
 *             |   S   /
 *            F|      /
 *             |    F/
 *             |    /
 *             |   R
 *             |  /
 *             V L
 *            S3
 *             |
 *            F|
 *             |
 *             R
 *             |
 * backtrack   V
 * <----------Q4
 *   \    F    |
 *    \        |S
 *     \   F   V
 *      \-----S4
 *
 * For greedy loops we push the current position, then generate the code that
 * eats the input specially in EmitGreedyLoop.  The other choice (the
 * continuation) is generated by the normal code in EmitChoices, and steps back
 * in the input to the starting position when it fails to match.  The loop code
 * looks like this (U is the unwind code that steps back in the greedy loop).
 *
 *              _____
 *             /     \
 *             V     |
 * ----------> S1    |
 *            /|     |
 *           / |S    |
 *         F/  \_____/
 *         /
 *        |<-----
 *        |      \
 *        V       |S
 *        Q2 ---> U----->backtrack
 *        |  F   /
 *       S|     /
 *        V  F /
 *        S2--/
 */

GreedyLoopState::GreedyLoopState(bool not_at_start) {
  counter_backtrack_trace_.set_backtrack(&label_);
  if (not_at_start) counter_backtrack_trace_.set_at_start(Trace::FALSE_VALUE);
}

void ChoiceNode::AssertGuardsMentionRegisters(Trace* trace) {
#ifdef DEBUG
  intptr_t choice_count = alternatives_->length();
  for (intptr_t i = 0; i < choice_count - 1; i++) {
    GuardedAlternative alternative = alternatives_->At(i);
    ZoneGrowableArray<Guard*>* guards = alternative.guards();
    intptr_t guard_count = (guards == NULL) ? 0 : guards->length();
    for (intptr_t j = 0; j < guard_count; j++) {
      ASSERT(!trace->mentions_reg(guards->At(j)->reg()));
    }
  }
#endif
}

void ChoiceNode::SetUpPreLoad(RegExpCompiler* compiler,
                              Trace* current_trace,
                              PreloadState* state) {
  if (state->eats_at_least_ == PreloadState::kEatsAtLeastNotYetInitialized) {
    // Save some time by looking at most one machine word ahead.
    state->eats_at_least_ =
        EatsAtLeast(compiler->one_byte() ? 4 : 2, kRecursionBudget,
                    current_trace->at_start() == Trace::FALSE_VALUE);
  }
  state->preload_characters_ =
      CalculatePreloadCharacters(compiler, state->eats_at_least_);

  state->preload_is_current_ =
      (current_trace->characters_preloaded() == state->preload_characters_);
  state->preload_has_checked_bounds_ = state->preload_is_current_;
}

void ChoiceNode::Emit(RegExpCompiler* compiler, Trace* trace) {
  intptr_t choice_count = alternatives_->length();

  if (choice_count == 1 && alternatives_->At(0).guards() == nullptr) {
    alternatives_->At(0).node()->Emit(compiler, trace);
    return;
  }

  AssertGuardsMentionRegisters(trace);

  LimitResult limit_result = LimitVersions(compiler, trace);
  if (limit_result == DONE) return;
  ASSERT(limit_result == CONTINUE);

  // For loop nodes we already flushed (see LoopChoiceNode::Emit), but for
  // other choice nodes we only flush if we are out of code size budget.
  if (trace->flush_budget() == 0 && trace->actions() != NULL) {
    trace->Flush(compiler, this);
    return;
  }

  RecursionCheck rc(compiler);

  PreloadState preload;
  preload.init();
  GreedyLoopState greedy_loop_state(not_at_start());

  intptr_t text_length =
      GreedyLoopTextLengthForAlternative(&alternatives_->At(0));
  AlternativeGenerationList alt_gens(choice_count);

  if (choice_count > 1 && text_length != kNodeIsTooComplexForGreedyLoops) {
    trace = EmitGreedyLoop(compiler, trace, &alt_gens, &preload,
                           &greedy_loop_state, text_length);
  } else {
    // TODO(erikcorry): Delete this.  We don't need this label, but it makes us
    // match the traces produced pre-cleanup.
    BlockLabel second_choice;
    compiler->macro_assembler()->BindBlock(&second_choice);

    preload.eats_at_least_ = EmitOptimizedUnanchoredSearch(compiler, trace);

    EmitChoices(compiler, &alt_gens, 0, trace, &preload);
  }

  // At this point we need to generate slow checks for the alternatives where
  // the quick check was inlined.  We can recognize these because the associated
  // label was bound.
  intptr_t new_flush_budget = trace->flush_budget() / choice_count;
  for (intptr_t i = 0; i < choice_count; i++) {
    AlternativeGeneration* alt_gen = alt_gens.at(i);
    Trace new_trace(*trace);
    // If there are actions to be flushed we have to limit how many times
    // they are flushed.  Take the budget of the parent trace and distribute
    // it fairly amongst the children.
    if (new_trace.actions() != NULL) {
      new_trace.set_flush_budget(new_flush_budget);
    }
    bool next_expects_preload =
        i == choice_count - 1 ? false : alt_gens.at(i + 1)->expects_preload;
    EmitOutOfLineContinuation(compiler, &new_trace, alternatives_->At(i),
                              alt_gen, preload.preload_characters_,
                              next_expects_preload);
  }
}

Trace* ChoiceNode::EmitGreedyLoop(RegExpCompiler* compiler,
                                  Trace* trace,
                                  AlternativeGenerationList* alt_gens,
                                  PreloadState* preload,
                                  GreedyLoopState* greedy_loop_state,
                                  intptr_t text_length) {
  RegExpMacroAssembler* macro_assembler = compiler->macro_assembler();
  // Here we have special handling for greedy loops containing only text nodes
  // and other simple nodes.  These are handled by pushing the current
  // position on the stack and then incrementing the current position each
  // time around the switch.  On backtrack we decrement the current position
  // and check it against the pushed value.  This avoids pushing backtrack
  // information for each iteration of the loop, which could take up a lot of
  // space.
  ASSERT(trace->stop_node() == NULL);
  macro_assembler->PushCurrentPosition();
  BlockLabel greedy_match_failed;
  Trace greedy_match_trace;
  if (not_at_start()) greedy_match_trace.set_at_start(Trace::FALSE_VALUE);
  greedy_match_trace.set_backtrack(&greedy_match_failed);
  BlockLabel loop_label;
  macro_assembler->BindBlock(&loop_label);
  macro_assembler->CheckPreemption(/*is_backtrack=*/false);
  greedy_match_trace.set_stop_node(this);
  greedy_match_trace.set_loop_label(&loop_label);
  (*alternatives_)[0].node()->Emit(compiler, &greedy_match_trace);
  macro_assembler->BindBlock(&greedy_match_failed);

  BlockLabel second_choice;  // For use in greedy matches.
  macro_assembler->BindBlock(&second_choice);

  Trace* new_trace = greedy_loop_state->counter_backtrack_trace();

  EmitChoices(compiler, alt_gens, 1, new_trace, preload);

  macro_assembler->BindBlock(greedy_loop_state->label());
  // If we have unwound to the bottom then backtrack.
  macro_assembler->CheckGreedyLoop(trace->backtrack());
  // Otherwise try the second priority at an earlier position.
  macro_assembler->AdvanceCurrentPosition(-text_length);
  macro_assembler->GoTo(&second_choice);
  return new_trace;
}

intptr_t ChoiceNode::EmitOptimizedUnanchoredSearch(RegExpCompiler* compiler,
                                                   Trace* trace) {
  intptr_t eats_at_least = PreloadState::kEatsAtLeastNotYetInitialized;
  if (alternatives_->length() != 2) return eats_at_least;

  GuardedAlternative alt1 = alternatives_->At(1);
  if (alt1.guards() != NULL && alt1.guards()->length() != 0) {
    return eats_at_least;
  }
  RegExpNode* eats_anything_node = alt1.node();
  if (eats_anything_node->GetSuccessorOfOmnivorousTextNode(compiler) != this) {
    return eats_at_least;
  }

  // Really we should be creating a new trace when we execute this function,
  // but there is no need, because the code it generates cannot backtrack, and
  // we always arrive here with a trivial trace (since it's the entry to a
  // loop.  That also implies that there are no preloaded characters, which is
  // good, because it means we won't be violating any assumptions by
  // overwriting those characters with new load instructions.
  ASSERT(trace->is_trivial());

  RegExpMacroAssembler* macro_assembler = compiler->macro_assembler();
  // At this point we know that we are at a non-greedy loop that will eat
  // any character one at a time.  Any non-anchored regexp has such a
  // loop prepended to it in order to find where it starts.  We look for
  // a pattern of the form ...abc... where we can look 6 characters ahead
  // and step forwards 3 if the character is not one of abc.  Abc need
  // not be atoms, they can be any reasonably limited character class or
  // small alternation.
  BoyerMooreLookahead* bm = bm_info(false);
  if (bm == NULL) {
    eats_at_least = Utils::Minimum(
        kMaxLookaheadForBoyerMoore,
        EatsAtLeast(kMaxLookaheadForBoyerMoore, kRecursionBudget, false));
    if (eats_at_least >= 1) {
      bm = new (Z) BoyerMooreLookahead(eats_at_least, compiler, Z);
      GuardedAlternative alt0 = alternatives_->At(0);
      alt0.node()->FillInBMInfo(0, kRecursionBudget, bm, false);
    }
  }
  if (bm != NULL) {
    bm->EmitSkipInstructions(macro_assembler);
  }
  return eats_at_least;
}

void ChoiceNode::EmitChoices(RegExpCompiler* compiler,
                             AlternativeGenerationList* alt_gens,
                             intptr_t first_choice,
                             Trace* trace,
                             PreloadState* preload) {
  RegExpMacroAssembler* macro_assembler = compiler->macro_assembler();
  SetUpPreLoad(compiler, trace, preload);

  // For now we just call all choices one after the other.  The idea ultimately
  // is to use the Dispatch table to try only the relevant ones.
  intptr_t choice_count = alternatives_->length();

  intptr_t new_flush_budget = trace->flush_budget() / choice_count;

  for (intptr_t i = first_choice; i < choice_count; i++) {
    bool is_last = i == choice_count - 1;
    bool fall_through_on_failure = !is_last;
    GuardedAlternative alternative = alternatives_->At(i);
    AlternativeGeneration* alt_gen = alt_gens->at(i);
    alt_gen->quick_check_details.set_characters(preload->preload_characters_);
    ZoneGrowableArray<Guard*>* guards = alternative.guards();
    intptr_t guard_count = (guards == NULL) ? 0 : guards->length();
    Trace new_trace(*trace);
    new_trace.set_characters_preloaded(
        preload->preload_is_current_ ? preload->preload_characters_ : 0);
    if (preload->preload_has_checked_bounds_) {
      new_trace.set_bound_checked_up_to(preload->preload_characters_);
    }
    new_trace.quick_check_performed()->Clear();
    if (not_at_start_) new_trace.set_at_start(Trace::FALSE_VALUE);
    if (!is_last) {
      new_trace.set_backtrack(&alt_gen->after);
    }
    alt_gen->expects_preload = preload->preload_is_current_;
    bool generate_full_check_inline = false;
    if (kRegexpOptimization &&
        try_to_emit_quick_check_for_alternative(i == 0) &&
        alternative.node()->EmitQuickCheck(
            compiler, trace, &new_trace, preload->preload_has_checked_bounds_,
            &alt_gen->possible_success, &alt_gen->quick_check_details,
            fall_through_on_failure)) {
      // Quick check was generated for this choice.
      preload->preload_is_current_ = true;
      preload->preload_has_checked_bounds_ = true;
      // If we generated the quick check to fall through on possible success,
      // we now need to generate the full check inline.
      if (!fall_through_on_failure) {
        macro_assembler->BindBlock(&alt_gen->possible_success);
        new_trace.set_quick_check_performed(&alt_gen->quick_check_details);
        new_trace.set_characters_preloaded(preload->preload_characters_);
        new_trace.set_bound_checked_up_to(preload->preload_characters_);
        generate_full_check_inline = true;
      }
    } else if (alt_gen->quick_check_details.cannot_match()) {
      if (!fall_through_on_failure) {
        macro_assembler->GoTo(trace->backtrack());
      }
      continue;
    } else {
      // No quick check was generated.  Put the full code here.
      // If this is not the first choice then there could be slow checks from
      // previous cases that go here when they fail.  There's no reason to
      // insist that they preload characters since the slow check we are about
      // to generate probably can't use it.
      if (i != first_choice) {
        alt_gen->expects_preload = false;
        new_trace.InvalidateCurrentCharacter();
      }
      generate_full_check_inline = true;
    }
    if (generate_full_check_inline) {
      if (new_trace.actions() != NULL) {
        new_trace.set_flush_budget(new_flush_budget);
      }
      for (intptr_t j = 0; j < guard_count; j++) {
        GenerateGuard(macro_assembler, guards->At(j), &new_trace);
      }
      alternative.node()->Emit(compiler, &new_trace);
      preload->preload_is_current_ = false;
    }
    macro_assembler->BindBlock(&alt_gen->after);
  }
}

void ChoiceNode::EmitOutOfLineContinuation(RegExpCompiler* compiler,
                                           Trace* trace,
                                           GuardedAlternative alternative,
                                           AlternativeGeneration* alt_gen,
                                           intptr_t preload_characters,
                                           bool next_expects_preload) {
  if (!alt_gen->possible_success.IsLinked()) return;

  RegExpMacroAssembler* macro_assembler = compiler->macro_assembler();
  macro_assembler->BindBlock(&alt_gen->possible_success);
  Trace out_of_line_trace(*trace);
  out_of_line_trace.set_characters_preloaded(preload_characters);
  out_of_line_trace.set_quick_check_performed(&alt_gen->quick_check_details);
  if (not_at_start_) out_of_line_trace.set_at_start(Trace::FALSE_VALUE);
  ZoneGrowableArray<Guard*>* guards = alternative.guards();
  intptr_t guard_count = (guards == NULL) ? 0 : guards->length();
  if (next_expects_preload) {
    BlockLabel reload_current_char;
    out_of_line_trace.set_backtrack(&reload_current_char);
    for (intptr_t j = 0; j < guard_count; j++) {
      GenerateGuard(macro_assembler, guards->At(j), &out_of_line_trace);
    }
    alternative.node()->Emit(compiler, &out_of_line_trace);
    macro_assembler->BindBlock(&reload_current_char);
    // Reload the current character, since the next quick check expects that.
    // We don't need to check bounds here because we only get into this
    // code through a quick check which already did the checked load.
    macro_assembler->LoadCurrentCharacter(trace->cp_offset(), NULL, false,
                                          preload_characters);
    macro_assembler->GoTo(&(alt_gen->after));
  } else {
    out_of_line_trace.set_backtrack(&(alt_gen->after));
    for (intptr_t j = 0; j < guard_count; j++) {
      GenerateGuard(macro_assembler, guards->At(j), &out_of_line_trace);
    }
    alternative.node()->Emit(compiler, &out_of_line_trace);
  }
}

void ActionNode::Emit(RegExpCompiler* compiler, Trace* trace) {
  RegExpMacroAssembler* assembler = compiler->macro_assembler();
  LimitResult limit_result = LimitVersions(compiler, trace);
  if (limit_result == DONE) return;
  ASSERT(limit_result == CONTINUE);

  RecursionCheck rc(compiler);

  switch (action_type_) {
    case STORE_POSITION: {
      Trace::DeferredCapture new_capture(data_.u_position_register.reg,
                                         data_.u_position_register.is_capture,
                                         trace);
      Trace new_trace = *trace;
      new_trace.add_action(&new_capture);
      on_success()->Emit(compiler, &new_trace);
      break;
    }
    case INCREMENT_REGISTER: {
      Trace::DeferredIncrementRegister new_increment(
          data_.u_increment_register.reg);
      Trace new_trace = *trace;
      new_trace.add_action(&new_increment);
      on_success()->Emit(compiler, &new_trace);
      break;
    }
    case SET_REGISTER: {
      Trace::DeferredSetRegister new_set(data_.u_store_register.reg,
                                         data_.u_store_register.value);
      Trace new_trace = *trace;
      new_trace.add_action(&new_set);
      on_success()->Emit(compiler, &new_trace);
      break;
    }
    case CLEAR_CAPTURES: {
      Trace::DeferredClearCaptures new_capture(Interval(
          data_.u_clear_captures.range_from, data_.u_clear_captures.range_to));
      Trace new_trace = *trace;
      new_trace.add_action(&new_capture);
      on_success()->Emit(compiler, &new_trace);
      break;
    }
    case BEGIN_SUBMATCH:
      if (!trace->is_trivial()) {
        trace->Flush(compiler, this);
      } else {
        assembler->WriteCurrentPositionToRegister(
            data_.u_submatch.current_position_register, 0);
        assembler->WriteStackPointerToRegister(
            data_.u_submatch.stack_pointer_register);
        on_success()->Emit(compiler, trace);
      }
      break;
    case EMPTY_MATCH_CHECK: {
      intptr_t start_pos_reg = data_.u_empty_match_check.start_register;
      intptr_t stored_pos = 0;
      intptr_t rep_reg = data_.u_empty_match_check.repetition_register;
      bool has_minimum = (rep_reg != RegExpCompiler::kNoRegister);
      bool know_dist = trace->GetStoredPosition(start_pos_reg, &stored_pos);
      if (know_dist && !has_minimum && stored_pos == trace->cp_offset()) {
        // If we know we haven't advanced and there is no minimum we
        // can just backtrack immediately.
        assembler->GoTo(trace->backtrack());
      } else if (know_dist && stored_pos < trace->cp_offset()) {
        // If we know we've advanced we can generate the continuation
        // immediately.
        on_success()->Emit(compiler, trace);
      } else if (!trace->is_trivial()) {
        trace->Flush(compiler, this);
      } else {
        BlockLabel skip_empty_check;
        // If we have a minimum number of repetitions we check the current
        // number first and skip the empty check if it's not enough.
        if (has_minimum) {
          intptr_t limit = data_.u_empty_match_check.repetition_limit;
          assembler->IfRegisterLT(rep_reg, limit, &skip_empty_check);
        }
        // If the match is empty we bail out, otherwise we fall through
        // to the on-success continuation.
        assembler->IfRegisterEqPos(data_.u_empty_match_check.start_register,
                                   trace->backtrack());
        assembler->BindBlock(&skip_empty_check);
        on_success()->Emit(compiler, trace);
      }
      break;
    }
    case POSITIVE_SUBMATCH_SUCCESS: {
      if (!trace->is_trivial()) {
        trace->Flush(compiler, this);
        return;
      }
      assembler->ReadCurrentPositionFromRegister(
          data_.u_submatch.current_position_register);
      assembler->ReadStackPointerFromRegister(
          data_.u_submatch.stack_pointer_register);
      intptr_t clear_register_count = data_.u_submatch.clear_register_count;
      if (clear_register_count == 0) {
        on_success()->Emit(compiler, trace);
        return;
      }
      intptr_t clear_registers_from = data_.u_submatch.clear_register_from;
      BlockLabel clear_registers_backtrack;
      Trace new_trace = *trace;
      new_trace.set_backtrack(&clear_registers_backtrack);
      on_success()->Emit(compiler, &new_trace);

      assembler->BindBlock(&clear_registers_backtrack);
      intptr_t clear_registers_to =
          clear_registers_from + clear_register_count - 1;
      assembler->ClearRegisters(clear_registers_from, clear_registers_to);

      ASSERT(trace->backtrack() == NULL);
      assembler->Backtrack();
      return;
    }
    default:
      UNREACHABLE();
  }
}

void BackReferenceNode::Emit(RegExpCompiler* compiler, Trace* trace) {
  RegExpMacroAssembler* assembler = compiler->macro_assembler();
  if (!trace->is_trivial()) {
    trace->Flush(compiler, this);
    return;
  }

  LimitResult limit_result = LimitVersions(compiler, trace);
  if (limit_result == DONE) return;
  ASSERT(limit_result == CONTINUE);

  RecursionCheck rc(compiler);

  ASSERT(start_reg_ + 1 == end_reg_);
  if (flags_.IgnoreCase()) {
    assembler->CheckNotBackReferenceIgnoreCase(
        start_reg_, read_backward(), flags_.IsUnicode(), trace->backtrack());
  } else {
    assembler->CheckNotBackReference(start_reg_, read_backward(),
                                     trace->backtrack());
  }
  // We are going to advance backward, so we may end up at the start.
  if (read_backward()) trace->set_at_start(Trace::UNKNOWN);

  // Check that the back reference does not end inside a surrogate pair.
  if (flags_.IsUnicode() && !compiler->one_byte()) {
    assembler->CheckNotInSurrogatePair(trace->cp_offset(), trace->backtrack());
  }

  on_success()->Emit(compiler, trace);
}

// -------------------------------------------------------------------
// Dot/dotty output

#ifdef DEBUG

class DotPrinter : public NodeVisitor {
 public:
  explicit DotPrinter(bool ignore_case) {}
  void PrintNode(const char* label, RegExpNode* node);
  void Visit(RegExpNode* node);
  void PrintAttributes(RegExpNode* from);
  void PrintOnFailure(RegExpNode* from, RegExpNode* to);
#define DECLARE_VISIT(Type) virtual void Visit##Type(Type##Node* that);
  FOR_EACH_NODE_TYPE(DECLARE_VISIT)
#undef DECLARE_VISIT
};

void DotPrinter::PrintNode(const char* label, RegExpNode* node) {
  OS::PrintErr("digraph G {\n  graph [label=\"");
  for (intptr_t i = 0; label[i]; i++) {
    switch (label[i]) {
      case '\\':
        OS::PrintErr("\\\\");
        break;
      case '"':
        OS::PrintErr("\"");
        break;
      default:
        OS::PrintErr("%c", label[i]);
        break;
    }
  }
  OS::PrintErr("\"];\n");
  Visit(node);
  OS::PrintErr("}\n");
}

void DotPrinter::Visit(RegExpNode* node) {
  if (node->info()->visited) return;
  node->info()->visited = true;
  node->Accept(this);
}

void DotPrinter::PrintOnFailure(RegExpNode* from, RegExpNode* on_failure) {
  OS::PrintErr("  n%p -> n%p [style=dotted];\n", from, on_failure);
  Visit(on_failure);
}

class AttributePrinter : public ValueObject {
 public:
  AttributePrinter() : first_(true) {}
  void PrintSeparator() {
    if (first_) {
      first_ = false;
    } else {
      OS::PrintErr("|");
    }
  }
  void PrintBit(const char* name, bool value) {
    if (!value) return;
    PrintSeparator();
    OS::PrintErr("{%s}", name);
  }
  void PrintPositive(const char* name, intptr_t value) {
    if (value < 0) return;
    PrintSeparator();
    OS::PrintErr("{%s|%" Pd "}", name, value);
  }

 private:
  bool first_;
};

void DotPrinter::PrintAttributes(RegExpNode* that) {
  OS::PrintErr(
      "  a%p [shape=Mrecord, color=grey, fontcolor=grey, "
      "margin=0.1, fontsize=10, label=\"{",
      that);
  AttributePrinter printer;
  NodeInfo* info = that->info();
  printer.PrintBit("NI", info->follows_newline_interest);
  printer.PrintBit("WI", info->follows_word_interest);
  printer.PrintBit("SI", info->follows_start_interest);
  BlockLabel* label = that->label();
  if (label->IsBound()) printer.PrintPositive("@", label->Position());
  OS::PrintErr(
      "}\"];\n"
      "  a%p -> n%p [style=dashed, color=grey, arrowhead=none];\n",
      that, that);
}

void DotPrinter::VisitChoice(ChoiceNode* that) {
  OS::PrintErr("  n%p [shape=Mrecord, label=\"?\"];\n", that);
  for (intptr_t i = 0; i < that->alternatives()->length(); i++) {
    GuardedAlternative alt = that->alternatives()->At(i);
    OS::PrintErr("  n%p -> n%p", that, alt.node());
  }
  for (intptr_t i = 0; i < that->alternatives()->length(); i++) {
    GuardedAlternative alt = that->alternatives()->At(i);
    alt.node()->Accept(this);
  }
}

void DotPrinter::VisitText(TextNode* that) {
  OS::PrintErr("  n%p [label=\"", that);
  for (intptr_t i = 0; i < that->elements()->length(); i++) {
    if (i > 0) OS::PrintErr(" ");
    TextElement elm = that->elements()->At(i);
    switch (elm.text_type()) {
      case TextElement::ATOM: {
        ZoneGrowableArray<uint16_t>* data = elm.atom()->data();
        for (intptr_t i = 0; i < data->length(); i++) {
          OS::PrintErr("%c", static_cast<char>(data->At(i)));
        }
        break;
      }
      case TextElement::CHAR_CLASS: {
        RegExpCharacterClass* node = elm.char_class();
        OS::PrintErr("[");
        if (node->is_negated()) OS::PrintErr("^");
        for (intptr_t j = 0; j < node->ranges()->length(); j++) {
          CharacterRange range = node->ranges()->At(j);
          PrintUtf16(range.from());
          OS::PrintErr("-");
          PrintUtf16(range.to());
        }
        OS::PrintErr("]");
        break;
      }
      default:
        UNREACHABLE();
    }
  }
  OS::PrintErr("\", shape=box, peripheries=2];\n");
  PrintAttributes(that);
  OS::PrintErr("  n%p -> n%p;\n", that, that->on_success());
  Visit(that->on_success());
}

void DotPrinter::VisitBackReference(BackReferenceNode* that) {
  OS::PrintErr("  n%p [label=\"$%" Pd "..$%" Pd "\", shape=doubleoctagon];\n",
               that, that->start_register(), that->end_register());
  PrintAttributes(that);
  OS::PrintErr("  n%p -> n%p;\n", that, that->on_success());
  Visit(that->on_success());
}

void DotPrinter::VisitEnd(EndNode* that) {
  OS::PrintErr("  n%p [style=bold, shape=point];\n", that);
  PrintAttributes(that);
}

void DotPrinter::VisitAssertion(AssertionNode* that) {
  OS::PrintErr("  n%p [", that);
  switch (that->assertion_type()) {
    case AssertionNode::AT_END:
      OS::PrintErr("label=\"$\", shape=septagon");
      break;
    case AssertionNode::AT_START:
      OS::PrintErr("label=\"^\", shape=septagon");
      break;
    case AssertionNode::AT_BOUNDARY:
      OS::PrintErr("label=\"\\b\", shape=septagon");
      break;
    case AssertionNode::AT_NON_BOUNDARY:
      OS::PrintErr("label=\"\\B\", shape=septagon");
      break;
    case AssertionNode::AFTER_NEWLINE:
      OS::PrintErr("label=\"(?<=\\n)\", shape=septagon");
      break;
  }
  OS::PrintErr("];\n");
  PrintAttributes(that);
  RegExpNode* successor = that->on_success();
  OS::PrintErr("  n%p -> n%p;\n", that, successor);
  Visit(successor);
}

void DotPrinter::VisitAction(ActionNode* that) {
  OS::PrintErr("  n%p [", that);
  switch (that->action_type_) {
    case ActionNode::SET_REGISTER:
      OS::PrintErr("label=\"$%" Pd ":=%" Pd "\", shape=octagon",
                   that->data_.u_store_register.reg,
                   that->data_.u_store_register.value);
      break;
    case ActionNode::INCREMENT_REGISTER:
      OS::PrintErr("label=\"$%" Pd "++\", shape=octagon",
                   that->data_.u_increment_register.reg);
      break;
    case ActionNode::STORE_POSITION:
      OS::PrintErr("label=\"$%" Pd ":=$pos\", shape=octagon",
                   that->data_.u_position_register.reg);
      break;
    case ActionNode::BEGIN_SUBMATCH:
      OS::PrintErr("label=\"$%" Pd ":=$pos,begin\", shape=septagon",
                   that->data_.u_submatch.current_position_register);
      break;
    case ActionNode::POSITIVE_SUBMATCH_SUCCESS:
      OS::PrintErr("label=\"escape\", shape=septagon");
      break;
    case ActionNode::EMPTY_MATCH_CHECK:
      OS::PrintErr("label=\"$%" Pd "=$pos?,$%" Pd "<%" Pd "?\", shape=septagon",
                   that->data_.u_empty_match_check.start_register,
                   that->data_.u_empty_match_check.repetition_register,
                   that->data_.u_empty_match_check.repetition_limit);
      break;
    case ActionNode::CLEAR_CAPTURES: {
      OS::PrintErr("label=\"clear $%" Pd " to $%" Pd "\", shape=septagon",
                   that->data_.u_clear_captures.range_from,
                   that->data_.u_clear_captures.range_to);
      break;
    }
  }
  OS::PrintErr("];\n");
  PrintAttributes(that);
  RegExpNode* successor = that->on_success();
  OS::PrintErr("  n%p -> n%p;\n", that, successor);
  Visit(successor);
}

void RegExpEngine::DotPrint(const char* label,
                            RegExpNode* node,
                            bool ignore_case) {
  DotPrinter printer(ignore_case);
  printer.PrintNode(label, node);
}

#endif  // DEBUG

// -------------------------------------------------------------------
// Tree to graph conversion

// The zone in which we allocate graph nodes.
#define OZ (on_success->zone())

RegExpNode* RegExpAtom::ToNode(RegExpCompiler* compiler,
                               RegExpNode* on_success) {
  ZoneGrowableArray<TextElement>* elms =
      new (OZ) ZoneGrowableArray<TextElement>(1);
  elms->Add(TextElement::Atom(this));
  return new (OZ) TextNode(elms, compiler->read_backward(), on_success);
}

RegExpNode* RegExpText::ToNode(RegExpCompiler* compiler,
                               RegExpNode* on_success) {
  ZoneGrowableArray<TextElement>* elms =
      new (OZ) ZoneGrowableArray<TextElement>(1);
  for (intptr_t i = 0; i < elements()->length(); i++) {
    elms->Add(elements()->At(i));
  }
  return new (OZ) TextNode(elms, compiler->read_backward(), on_success);
}

static bool CompareInverseRanges(ZoneGrowableArray<CharacterRange>* ranges,
                                 const int32_t* special_class,
                                 intptr_t length) {
  length--;  // Remove final kRangeEndMarker.
  ASSERT(special_class[length] == kRangeEndMarker);
  ASSERT(ranges->length() != 0);
  ASSERT(length != 0);
  ASSERT(special_class[0] != 0);
  if (ranges->length() != (length >> 1) + 1) {
    return false;
  }
  CharacterRange range = ranges->At(0);
  if (range.from() != 0) {
    return false;
  }
  for (intptr_t i = 0; i < length; i += 2) {
    if (special_class[i] != (range.to() + 1)) {
      return false;
    }
    range = ranges->At((i >> 1) + 1);
    if (special_class[i + 1] != range.from()) {
      return false;
    }
  }
  if (range.to() != Utf::kMaxCodePoint) {
    return false;
  }
  return true;
}

static bool CompareRanges(ZoneGrowableArray<CharacterRange>* ranges,
                          const int32_t* special_class,
                          intptr_t length) {
  length--;  // Remove final kRangeEndMarker.
  ASSERT(special_class[length] == kRangeEndMarker);
  if (ranges->length() * 2 != length) {
    return false;
  }
  for (intptr_t i = 0; i < length; i += 2) {
    CharacterRange range = ranges->At(i >> 1);
    if (range.from() != special_class[i] ||
        range.to() != special_class[i + 1] - 1) {
      return false;
    }
  }
  return true;
}

bool RegExpCharacterClass::is_standard() {
  // TODO(lrn): Remove need for this function, by not throwing away information
  // along the way.
  if (is_negated()) {
    return false;
  }
  if (set_.is_standard()) {
    return true;
  }
  if (CompareRanges(set_.ranges(), kSpaceRanges, kSpaceRangeCount)) {
    set_.set_standard_set_type('s');
    return true;
  }
  if (CompareInverseRanges(set_.ranges(), kSpaceRanges, kSpaceRangeCount)) {
    set_.set_standard_set_type('S');
    return true;
  }
  if (CompareInverseRanges(set_.ranges(), kLineTerminatorRanges,
                           kLineTerminatorRangeCount)) {
    set_.set_standard_set_type('.');
    return true;
  }
  if (CompareRanges(set_.ranges(), kLineTerminatorRanges,
                    kLineTerminatorRangeCount)) {
    set_.set_standard_set_type('n');
    return true;
  }
  if (CompareRanges(set_.ranges(), kWordRanges, kWordRangeCount)) {
    set_.set_standard_set_type('w');
    return true;
  }
  if (CompareInverseRanges(set_.ranges(), kWordRanges, kWordRangeCount)) {
    set_.set_standard_set_type('W');
    return true;
  }
  return false;
}

UnicodeRangeSplitter::UnicodeRangeSplitter(
    Zone* zone,
    ZoneGrowableArray<CharacterRange>* base)
    : zone_(zone),
      table_(zone),
      bmp_(nullptr),
      lead_surrogates_(nullptr),
      trail_surrogates_(nullptr),
      non_bmp_(nullptr) {
  // The unicode range splitter categorizes given character ranges into:
  // - Code points from the BMP representable by one code unit.
  // - Code points outside the BMP that need to be split into surrogate pairs.
  // - Lone lead surrogates.
  // - Lone trail surrogates.
  // Lone surrogates are valid code points, even though no actual characters.
  // They require special matching to make sure we do not split surrogate pairs.
  // We use the dispatch table to accomplish this. The base range is split up
  // by the table by the overlay ranges, and the Call callback is used to
  // filter and collect ranges for each category.
  for (intptr_t i = 0; i < base->length(); i++) {
    table_.AddRange(base->At(i), kBase, zone_);
  }
  // Add overlay ranges.
  table_.AddRange(CharacterRange::Range(0, Utf16::kLeadSurrogateStart - 1),
                  kBmpCodePoints, zone_);
  table_.AddRange(CharacterRange::Range(Utf16::kLeadSurrogateStart,
                                        Utf16::kLeadSurrogateEnd),
                  kLeadSurrogates, zone_);
  table_.AddRange(CharacterRange::Range(Utf16::kTrailSurrogateStart,
                                        Utf16::kTrailSurrogateEnd),
                  kTrailSurrogates, zone_);
  table_.AddRange(
      CharacterRange::Range(Utf16::kTrailSurrogateEnd + 1, Utf16::kMaxCodeUnit),
      kBmpCodePoints, zone_);
  table_.AddRange(
      CharacterRange::Range(Utf16::kMaxCodeUnit + 1, Utf::kMaxCodePoint),
      kNonBmpCodePoints, zone_);
  table_.ForEach(this);
}

void UnicodeRangeSplitter::Call(uint32_t from, DispatchTable::Entry entry) {
  OutSet* outset = entry.out_set();
  if (!outset->Get(kBase)) return;
  ZoneGrowableArray<CharacterRange>** target = nullptr;
  if (outset->Get(kBmpCodePoints)) {
    target = &bmp_;
  } else if (outset->Get(kLeadSurrogates)) {
    target = &lead_surrogates_;
  } else if (outset->Get(kTrailSurrogates)) {
    target = &trail_surrogates_;
  } else {
    ASSERT(outset->Get(kNonBmpCodePoints));
    target = &non_bmp_;
  }
  if (*target == nullptr) {
    *target = new (zone_) ZoneGrowableArray<CharacterRange>(2);
  }
  (*target)->Add(CharacterRange::Range(entry.from(), entry.to()));
}

void AddBmpCharacters(RegExpCompiler* compiler,
                      ChoiceNode* result,
                      RegExpNode* on_success,
                      UnicodeRangeSplitter* splitter) {
  ZoneGrowableArray<CharacterRange>* bmp = splitter->bmp();
  if (bmp == nullptr) return;
  result->AddAlternative(GuardedAlternative(TextNode::CreateForCharacterRanges(
      bmp, compiler->read_backward(), on_success, RegExpFlags())));
}

void AddNonBmpSurrogatePairs(RegExpCompiler* compiler,
                             ChoiceNode* result,
                             RegExpNode* on_success,
                             UnicodeRangeSplitter* splitter) {
  ZoneGrowableArray<CharacterRange>* non_bmp = splitter->non_bmp();
  if (non_bmp == nullptr) return;
  ASSERT(!compiler->one_byte());
  CharacterRange::Canonicalize(non_bmp);
  for (int i = 0; i < non_bmp->length(); i++) {
    // Match surrogate pair.
    // E.g. [\u10005-\u11005] becomes
    //      \ud800[\udc05-\udfff]|
    //      [\ud801-\ud803][\udc00-\udfff]|
    //      \ud804[\udc00-\udc05]
    uint32_t from = non_bmp->At(i).from();
    uint32_t to = non_bmp->At(i).to();
    uint16_t from_points[2];
    Utf16::Encode(from, from_points);
    uint16_t to_points[2];
    Utf16::Encode(to, to_points);
    if (from_points[0] == to_points[0]) {
      // The lead surrogate is the same.
      result->AddAlternative(
          GuardedAlternative(TextNode::CreateForSurrogatePair(
              CharacterRange::Singleton(from_points[0]),
              CharacterRange::Range(from_points[1], to_points[1]),
              compiler->read_backward(), on_success, RegExpFlags())));
    } else {
      if (from_points[1] != Utf16::kTrailSurrogateStart) {
        // Add [from_l][from_t-\udfff]
        result->AddAlternative(
            GuardedAlternative(TextNode::CreateForSurrogatePair(
                CharacterRange::Singleton(from_points[0]),
                CharacterRange::Range(from_points[1],
                                      Utf16::kTrailSurrogateEnd),
                compiler->read_backward(), on_success, RegExpFlags())));
        from_points[0]++;
      }
      if (to_points[1] != Utf16::kTrailSurrogateEnd) {
        // Add [to_l][\udc00-to_t]
        result->AddAlternative(
            GuardedAlternative(TextNode::CreateForSurrogatePair(
                CharacterRange::Singleton(to_points[0]),
                CharacterRange::Range(Utf16::kTrailSurrogateStart,
                                      to_points[1]),
                compiler->read_backward(), on_success, RegExpFlags())));
        to_points[0]--;
      }
      if (from_points[0] <= to_points[0]) {
        // Add [from_l-to_l][\udc00-\udfff]
        result->AddAlternative(
            GuardedAlternative(TextNode::CreateForSurrogatePair(
                CharacterRange::Range(from_points[0], to_points[0]),
                CharacterRange::Range(Utf16::kTrailSurrogateStart,
                                      Utf16::kTrailSurrogateEnd),
                compiler->read_backward(), on_success, RegExpFlags())));
      }
    }
  }
}

RegExpNode* NegativeLookaroundAgainstReadDirectionAndMatch(
    RegExpCompiler* compiler,
    ZoneGrowableArray<CharacterRange>* lookbehind,
    ZoneGrowableArray<CharacterRange>* match,
    RegExpNode* on_success,
    bool read_backward,
    RegExpFlags flags) {
  RegExpNode* match_node = TextNode::CreateForCharacterRanges(
      match, read_backward, on_success, flags);
  int stack_register = compiler->UnicodeLookaroundStackRegister();
  int position_register = compiler->UnicodeLookaroundPositionRegister();
  RegExpLookaround::Builder lookaround(false, match_node, stack_register,
                                       position_register);
  RegExpNode* negative_match = TextNode::CreateForCharacterRanges(
      lookbehind, !read_backward, lookaround.on_match_success(), flags);
  return lookaround.ForMatch(negative_match);
}

RegExpNode* MatchAndNegativeLookaroundInReadDirection(
    RegExpCompiler* compiler,
    ZoneGrowableArray<CharacterRange>* match,
    ZoneGrowableArray<CharacterRange>* lookahead,
    RegExpNode* on_success,
    bool read_backward,
    RegExpFlags flags) {
  int stack_register = compiler->UnicodeLookaroundStackRegister();
  int position_register = compiler->UnicodeLookaroundPositionRegister();
  RegExpLookaround::Builder lookaround(false, on_success, stack_register,
                                       position_register);
  RegExpNode* negative_match = TextNode::CreateForCharacterRanges(
      lookahead, read_backward, lookaround.on_match_success(), flags);
  return TextNode::CreateForCharacterRanges(
      match, read_backward, lookaround.ForMatch(negative_match), flags);
}

void AddLoneLeadSurrogates(RegExpCompiler* compiler,
                           ChoiceNode* result,
                           RegExpNode* on_success,
                           UnicodeRangeSplitter* splitter) {
  auto lead_surrogates = splitter->lead_surrogates();
  if (lead_surrogates == nullptr) return;
  // E.g. \ud801 becomes \ud801(?![\udc00-\udfff]).
  auto trail_surrogates = CharacterRange::List(
      on_success->zone(), CharacterRange::Range(Utf16::kTrailSurrogateStart,
                                                Utf16::kTrailSurrogateEnd));

  RegExpNode* match;
  if (compiler->read_backward()) {
    // Reading backward. Assert that reading forward, there is no trail
    // surrogate, and then backward match the lead surrogate.
    match = NegativeLookaroundAgainstReadDirectionAndMatch(
        compiler, trail_surrogates, lead_surrogates, on_success, true,
        RegExpFlags());
  } else {
    // Reading forward. Forward match the lead surrogate and assert that
    // no trail surrogate follows.
    match = MatchAndNegativeLookaroundInReadDirection(
        compiler, lead_surrogates, trail_surrogates, on_success, false,
        RegExpFlags());
  }
  result->AddAlternative(GuardedAlternative(match));
}

void AddLoneTrailSurrogates(RegExpCompiler* compiler,
                            ChoiceNode* result,
                            RegExpNode* on_success,
                            UnicodeRangeSplitter* splitter) {
  auto trail_surrogates = splitter->trail_surrogates();
  if (trail_surrogates == nullptr) return;
  // E.g. \udc01 becomes (?<![\ud800-\udbff])\udc01
  auto lead_surrogates = CharacterRange::List(
      on_success->zone(), CharacterRange::Range(Utf16::kLeadSurrogateStart,
                                                Utf16::kLeadSurrogateEnd));

  RegExpNode* match;
  if (compiler->read_backward()) {
    // Reading backward. Backward match the trail surrogate and assert that no
    // lead surrogate precedes it.
    match = MatchAndNegativeLookaroundInReadDirection(
        compiler, trail_surrogates, lead_surrogates, on_success, true,
        RegExpFlags());
  } else {
    // Reading forward. Assert that reading backward, there is no lead
    // surrogate, and then forward match the trail surrogate.
    match = NegativeLookaroundAgainstReadDirectionAndMatch(
        compiler, lead_surrogates, trail_surrogates, on_success, false,
        RegExpFlags());
  }
  result->AddAlternative(GuardedAlternative(match));
}

RegExpNode* UnanchoredAdvance(RegExpCompiler* compiler,
                              RegExpNode* on_success) {
  // This implements ES2015 21.2.5.2.3, AdvanceStringIndex.
  ASSERT(!compiler->read_backward());
  // Advance any character. If the character happens to be a lead surrogate and
  // we advanced into the middle of a surrogate pair, it will work out, as
  // nothing will match from there. We will have to advance again, consuming
  // the associated trail surrogate.
  auto range = CharacterRange::List(
      on_success->zone(), CharacterRange::Range(0, Utf16::kMaxCodeUnit));
  return TextNode::CreateForCharacterRanges(range, false, on_success,
                                            RegExpFlags());
}

void AddUnicodeCaseEquivalents(ZoneGrowableArray<CharacterRange>* ranges) {
  ASSERT(CharacterRange::IsCanonical(ranges));

  // Micro-optimization to avoid passing large ranges to UnicodeSet::closeOver.
  // See also https://crbug.com/v8/6727.
  // TODO(sstrickl): This only covers the special case of the {0,0x10FFFF}
  // range, which we use frequently internally. But large ranges can also easily
  // be created by the user. We might want to have a more general caching
  // mechanism for such ranges.
  if (ranges->length() == 1 && ranges->At(0).IsEverything(Utf::kMaxCodePoint)) {
    return;
  }

  icu::UnicodeSet set;
  for (int i = 0; i < ranges->length(); i++) {
    set.add(ranges->At(i).from(), ranges->At(i).to());
  }
  ranges->Clear();
  set.closeOver(USET_CASE_INSENSITIVE);
  // Full case mapping map single characters to multiple characters.
  // Those are represented as strings in the set. Remove them so that
  // we end up with only simple and common case mappings.
  set.removeAllStrings();
  for (int i = 0; i < set.getRangeCount(); i++) {
    ranges->Add(
        CharacterRange::Range(set.getRangeStart(i), set.getRangeEnd(i)));
  }
  // No errors and everything we collected have been ranges.
  CharacterRange::Canonicalize(ranges);
}

RegExpNode* RegExpCharacterClass::ToNode(RegExpCompiler* compiler,
                                         RegExpNode* on_success) {
  set_.Canonicalize();
  ZoneGrowableArray<CharacterRange>* ranges = this->ranges();
  if (flags_.NeedsUnicodeCaseEquivalents()) {
    AddUnicodeCaseEquivalents(ranges);
  }
  if (flags_.IsUnicode() && !compiler->one_byte() &&
      !contains_split_surrogate()) {
    if (is_negated()) {
      ZoneGrowableArray<CharacterRange>* negated =
          new ZoneGrowableArray<CharacterRange>(2);
      CharacterRange::Negate(ranges, negated);
      ranges = negated;
    }
    if (ranges->length() == 0) {
      RegExpCharacterClass* fail =
          new RegExpCharacterClass(ranges, RegExpFlags());
      return new TextNode(fail, compiler->read_backward(), on_success);
    }
    if (standard_type() == '*') {
      return UnanchoredAdvance(compiler, on_success);
    } else {
      ChoiceNode* result = new (OZ) ChoiceNode(2, OZ);
      UnicodeRangeSplitter splitter(OZ, ranges);
      AddBmpCharacters(compiler, result, on_success, &splitter);
      AddNonBmpSurrogatePairs(compiler, result, on_success, &splitter);
      AddLoneLeadSurrogates(compiler, result, on_success, &splitter);
      AddLoneTrailSurrogates(compiler, result, on_success, &splitter);
      return result;
    }
  } else {
    return new TextNode(this, compiler->read_backward(), on_success);
  }
  return new (OZ) TextNode(this, compiler->read_backward(), on_success);
}

RegExpNode* RegExpDisjunction::ToNode(RegExpCompiler* compiler,
                                      RegExpNode* on_success) {
  ZoneGrowableArray<RegExpTree*>* alternatives = this->alternatives();
  intptr_t length = alternatives->length();
  ChoiceNode* result = new (OZ) ChoiceNode(length, OZ);
  for (intptr_t i = 0; i < length; i++) {
    GuardedAlternative alternative(
        alternatives->At(i)->ToNode(compiler, on_success));
    result->AddAlternative(alternative);
  }
  return result;
}

RegExpNode* RegExpQuantifier::ToNode(RegExpCompiler* compiler,
                                     RegExpNode* on_success) {
  return ToNode(min(), max(), is_greedy(), body(), compiler, on_success);
}

// Scoped object to keep track of how much we unroll quantifier loops in the
// regexp graph generator.
class RegExpExpansionLimiter : public ValueObject {
 public:
  static const intptr_t kMaxExpansionFactor = 6;
  RegExpExpansionLimiter(RegExpCompiler* compiler, intptr_t factor)
      : compiler_(compiler),
        saved_expansion_factor_(compiler->current_expansion_factor()),
        ok_to_expand_(saved_expansion_factor_ <= kMaxExpansionFactor) {
    ASSERT(factor > 0);
    if (ok_to_expand_) {
      if (factor > kMaxExpansionFactor) {
        // Avoid integer overflow of the current expansion factor.
        ok_to_expand_ = false;
        compiler->set_current_expansion_factor(kMaxExpansionFactor + 1);
      } else {
        intptr_t new_factor = saved_expansion_factor_ * factor;
        ok_to_expand_ = (new_factor <= kMaxExpansionFactor);
        compiler->set_current_expansion_factor(new_factor);
      }
    }
  }

  ~RegExpExpansionLimiter() {
    compiler_->set_current_expansion_factor(saved_expansion_factor_);
  }

  bool ok_to_expand() { return ok_to_expand_; }

 private:
  RegExpCompiler* compiler_;
  intptr_t saved_expansion_factor_;
  bool ok_to_expand_;

  DISALLOW_IMPLICIT_CONSTRUCTORS(RegExpExpansionLimiter);
};

RegExpNode* RegExpQuantifier::ToNode(intptr_t min,
                                     intptr_t max,
                                     bool is_greedy,
                                     RegExpTree* body,
                                     RegExpCompiler* compiler,
                                     RegExpNode* on_success,
                                     bool not_at_start) {
  // x{f, t} becomes this:
  //
  //             (r++)<-.
  //               |     `
  //               |     (x)
  //               v     ^
  //      (r=0)-->(?)---/ [if r < t]
  //               |
  //   [if r >= f] \----> ...
  //

  // 15.10.2.5 RepeatMatcher algorithm.
  // The parser has already eliminated the case where max is 0.  In the case
  // where max_match is zero the parser has removed the quantifier if min was
  // > 0 and removed the atom if min was 0.  See AddQuantifierToAtom.

  // If we know that we cannot match zero length then things are a little
  // simpler since we don't need to make the special zero length match check
  // from step 2.1.  If the min and max are small we can unroll a little in
  // this case.
  // Unroll (foo)+ and (foo){3,}
  static const intptr_t kMaxUnrolledMinMatches = 3;
  // Unroll (foo)? and (foo){x,3}
  static const intptr_t kMaxUnrolledMaxMatches = 3;
  if (max == 0) return on_success;  // This can happen due to recursion.
  bool body_can_be_empty = (body->min_match() == 0);
  intptr_t body_start_reg = RegExpCompiler::kNoRegister;
  Interval capture_registers = body->CaptureRegisters();
  bool needs_capture_clearing = !capture_registers.is_empty();
  Zone* zone = compiler->zone();

  if (body_can_be_empty) {
    body_start_reg = compiler->AllocateRegister();
  } else if (kRegexpOptimization && !needs_capture_clearing) {
    // Only unroll if there are no captures and the body can't be
    // empty.
    {
      RegExpExpansionLimiter limiter(compiler, min + ((max != min) ? 1 : 0));
      if (min > 0 && min <= kMaxUnrolledMinMatches && limiter.ok_to_expand()) {
        intptr_t new_max = (max == kInfinity) ? max : max - min;
        // Recurse once to get the loop or optional matches after the fixed
        // ones.
        RegExpNode* answer =
            ToNode(0, new_max, is_greedy, body, compiler, on_success, true);
        // Unroll the forced matches from 0 to min.  This can cause chains of
        // TextNodes (which the parser does not generate).  These should be
        // combined if it turns out they hinder good code generation.
        for (intptr_t i = 0; i < min; i++) {
          answer = body->ToNode(compiler, answer);
        }
        return answer;
      }
    }
    if (max <= kMaxUnrolledMaxMatches && min == 0) {
      ASSERT(max > 0);  // Due to the 'if' above.
      RegExpExpansionLimiter limiter(compiler, max);
      if (limiter.ok_to_expand()) {
        // Unroll the optional matches up to max.
        RegExpNode* answer = on_success;
        for (intptr_t i = 0; i < max; i++) {
          ChoiceNode* alternation = new (zone) ChoiceNode(2, zone);
          if (is_greedy) {
            alternation->AddAlternative(
                GuardedAlternative(body->ToNode(compiler, answer)));
            alternation->AddAlternative(GuardedAlternative(on_success));
          } else {
            alternation->AddAlternative(GuardedAlternative(on_success));
            alternation->AddAlternative(
                GuardedAlternative(body->ToNode(compiler, answer)));
          }
          answer = alternation;
          if (not_at_start && !compiler->read_backward()) {
            alternation->set_not_at_start();
          }
        }
        return answer;
      }
    }
  }
  bool has_min = min > 0;
  bool has_max = max < RegExpTree::kInfinity;
  bool needs_counter = has_min || has_max;
  intptr_t reg_ctr = needs_counter ? compiler->AllocateRegister()
                                   : RegExpCompiler::kNoRegister;
  LoopChoiceNode* center = new (zone)
      LoopChoiceNode(body->min_match() == 0, compiler->read_backward(), zone);
  if (not_at_start && !compiler->read_backward()) center->set_not_at_start();
  RegExpNode* loop_return =
      needs_counter ? static_cast<RegExpNode*>(
                          ActionNode::IncrementRegister(reg_ctr, center))
                    : static_cast<RegExpNode*>(center);
  if (body_can_be_empty) {
    // If the body can be empty we need to check if it was and then
    // backtrack.
    loop_return =
        ActionNode::EmptyMatchCheck(body_start_reg, reg_ctr, min, loop_return);
  }
  RegExpNode* body_node = body->ToNode(compiler, loop_return);
  if (body_can_be_empty) {
    // If the body can be empty we need to store the start position
    // so we can bail out if it was empty.
    body_node = ActionNode::StorePosition(body_start_reg, false, body_node);
  }
  if (needs_capture_clearing) {
    // Before entering the body of this loop we need to clear captures.
    body_node = ActionNode::ClearCaptures(capture_registers, body_node);
  }
  GuardedAlternative body_alt(body_node);
  if (has_max) {
    Guard* body_guard = new (zone) Guard(reg_ctr, Guard::LT, max);
    body_alt.AddGuard(body_guard, zone);
  }
  GuardedAlternative rest_alt(on_success);
  if (has_min) {
    Guard* rest_guard = new (zone) Guard(reg_ctr, Guard::GEQ, min);
    rest_alt.AddGuard(rest_guard, zone);
  }
  if (is_greedy) {
    center->AddLoopAlternative(body_alt);
    center->AddContinueAlternative(rest_alt);
  } else {
    center->AddContinueAlternative(rest_alt);
    center->AddLoopAlternative(body_alt);
  }
  if (needs_counter) {
    return ActionNode::SetRegister(reg_ctr, 0, center);
  } else {
    return center;
  }
}

namespace {
// Desugar \b to (?<=\w)(?=\W)|(?<=\W)(?=\w) and
//         \B to (?<=\w)(?=\w)|(?<=\W)(?=\W)
RegExpNode* BoundaryAssertionAsLookaround(RegExpCompiler* compiler,
                                          RegExpNode* on_success,
                                          RegExpAssertion::AssertionType type,
                                          RegExpFlags flags) {
  ASSERT(flags.NeedsUnicodeCaseEquivalents());
  ZoneGrowableArray<CharacterRange>* word_range =
      new ZoneGrowableArray<CharacterRange>(2);
  CharacterRange::AddClassEscape('w', word_range, true);
  int stack_register = compiler->UnicodeLookaroundStackRegister();
  int position_register = compiler->UnicodeLookaroundPositionRegister();
  ChoiceNode* result = new (OZ) ChoiceNode(2, OZ);
  // Add two choices. The (non-)boundary could start with a word or
  // a non-word-character.
  for (int i = 0; i < 2; i++) {
    bool lookbehind_for_word = i == 0;
    bool lookahead_for_word =
        (type == RegExpAssertion::BOUNDARY) ^ lookbehind_for_word;
    // Look to the left.
    RegExpLookaround::Builder lookbehind(lookbehind_for_word, on_success,
                                         stack_register, position_register);
    RegExpNode* backward = TextNode::CreateForCharacterRanges(
        word_range, true, lookbehind.on_match_success(), flags);
    // Look to the right.
    RegExpLookaround::Builder lookahead(lookahead_for_word,
                                        lookbehind.ForMatch(backward),
                                        stack_register, position_register);
    RegExpNode* forward = TextNode::CreateForCharacterRanges(
        word_range, false, lookahead.on_match_success(), flags);
    result->AddAlternative(GuardedAlternative(lookahead.ForMatch(forward)));
  }
  return result;
}
}  // anonymous namespace

RegExpNode* RegExpAssertion::ToNode(RegExpCompiler* compiler,
                                    RegExpNode* on_success) {
  switch (assertion_type()) {
    case START_OF_LINE:
      return AssertionNode::AfterNewline(on_success);
    case START_OF_INPUT:
      return AssertionNode::AtStart(on_success);
    case BOUNDARY:
      return flags_.NeedsUnicodeCaseEquivalents()
                 ? BoundaryAssertionAsLookaround(compiler, on_success, BOUNDARY,
                                                 flags_)
                 : AssertionNode::AtBoundary(on_success);
    case NON_BOUNDARY:
      return flags_.NeedsUnicodeCaseEquivalents()
                 ? BoundaryAssertionAsLookaround(compiler, on_success,
                                                 NON_BOUNDARY, flags_)
                 : AssertionNode::AtNonBoundary(on_success);
    case END_OF_INPUT:
      return AssertionNode::AtEnd(on_success);
    case END_OF_LINE: {
      // Compile $ in multiline regexps as an alternation with a positive
      // lookahead in one side and an end-of-input on the other side.
      // We need two registers for the lookahead.
      intptr_t stack_pointer_register = compiler->AllocateRegister();
      intptr_t position_register = compiler->AllocateRegister();
      // The ChoiceNode to distinguish between a newline and end-of-input.
      ChoiceNode* result = new ChoiceNode(2, on_success->zone());
      // Create a newline atom.
      ZoneGrowableArray<CharacterRange>* newline_ranges =
          new ZoneGrowableArray<CharacterRange>(3);
      CharacterRange::AddClassEscape('n', newline_ranges);
      RegExpCharacterClass* newline_atom =
          new RegExpCharacterClass('n', RegExpFlags());
      TextNode* newline_matcher =
          new TextNode(newline_atom, /*read_backwards=*/false,
                       ActionNode::PositiveSubmatchSuccess(
                           stack_pointer_register, position_register,
                           0,   // No captures inside.
                           -1,  // Ignored if no captures.
                           on_success));
      // Create an end-of-input matcher.
      RegExpNode* end_of_line = ActionNode::BeginSubmatch(
          stack_pointer_register, position_register, newline_matcher);
      // Add the two alternatives to the ChoiceNode.
      GuardedAlternative eol_alternative(end_of_line);
      result->AddAlternative(eol_alternative);
      GuardedAlternative end_alternative(AssertionNode::AtEnd(on_success));
      result->AddAlternative(end_alternative);
      return result;
    }
    default:
      UNREACHABLE();
  }
  return on_success;
}

RegExpNode* RegExpBackReference::ToNode(RegExpCompiler* compiler,
                                        RegExpNode* on_success) {
  return new (OZ) BackReferenceNode(RegExpCapture::StartRegister(index()),
                                    RegExpCapture::EndRegister(index()), flags_,
                                    compiler->read_backward(), on_success);
}

RegExpNode* RegExpEmpty::ToNode(RegExpCompiler* compiler,
                                RegExpNode* on_success) {
  return on_success;
}

RegExpLookaround::Builder::Builder(bool is_positive,
                                   RegExpNode* on_success,
                                   intptr_t stack_pointer_register,
                                   intptr_t position_register,
                                   intptr_t capture_register_count,
                                   intptr_t capture_register_start)
    : is_positive_(is_positive),
      on_success_(on_success),
      stack_pointer_register_(stack_pointer_register),
      position_register_(position_register) {
  if (is_positive_) {
    on_match_success_ = ActionNode::PositiveSubmatchSuccess(
        stack_pointer_register, position_register, capture_register_count,
        capture_register_start, on_success);
  } else {
    on_match_success_ = new (OZ) NegativeSubmatchSuccess(
        stack_pointer_register, position_register, capture_register_count,
        capture_register_start, OZ);
  }
}

RegExpNode* RegExpLookaround::Builder::ForMatch(RegExpNode* match) {
  if (is_positive_) {
    return ActionNode::BeginSubmatch(stack_pointer_register_,
                                     position_register_, match);
  } else {
    Zone* zone = on_success_->zone();
    // We use a ChoiceNode to represent the negative lookaround. The first
    // alternative is the negative match. On success, the end node backtracks.
    // On failure, the second alternative is tried and leads to success.
    // NegativeLookaroundChoiceNode is a special ChoiceNode that ignores the
    // first exit when calculating quick checks.
    ChoiceNode* choice_node = new (zone) NegativeLookaroundChoiceNode(
        GuardedAlternative(match), GuardedAlternative(on_success_), zone);
    return ActionNode::BeginSubmatch(stack_pointer_register_,
                                     position_register_, choice_node);
  }
}

RegExpNode* RegExpLookaround::ToNode(RegExpCompiler* compiler,
                                     RegExpNode* on_success) {
  intptr_t stack_pointer_register = compiler->AllocateRegister();
  intptr_t position_register = compiler->AllocateRegister();

  const intptr_t registers_per_capture = 2;
  const intptr_t register_of_first_capture = 2;
  intptr_t register_count = capture_count_ * registers_per_capture;
  intptr_t register_start =
      register_of_first_capture + capture_from_ * registers_per_capture;

  RegExpNode* result;
  bool was_reading_backward = compiler->read_backward();
  compiler->set_read_backward(type() == LOOKBEHIND);
  Builder builder(is_positive(), on_success, stack_pointer_register,
                  position_register, register_count, register_start);
  RegExpNode* match = body_->ToNode(compiler, builder.on_match_success());
  result = builder.ForMatch(match);
  compiler->set_read_backward(was_reading_backward);
  return result;
}

RegExpNode* RegExpCapture::ToNode(RegExpCompiler* compiler,
                                  RegExpNode* on_success) {
  return ToNode(body(), index(), compiler, on_success);
}

RegExpNode* RegExpCapture::ToNode(RegExpTree* body,
                                  intptr_t index,
                                  RegExpCompiler* compiler,
                                  RegExpNode* on_success) {
  ASSERT(body != nullptr);
  intptr_t start_reg = RegExpCapture::StartRegister(index);
  intptr_t end_reg = RegExpCapture::EndRegister(index);
  if (compiler->read_backward()) {
    intptr_t tmp = end_reg;
    end_reg = start_reg;
    start_reg = tmp;
  }
  RegExpNode* store_end = ActionNode::StorePosition(end_reg, true, on_success);
  RegExpNode* body_node = body->ToNode(compiler, store_end);
  return ActionNode::StorePosition(start_reg, true, body_node);
}

RegExpNode* RegExpAlternative::ToNode(RegExpCompiler* compiler,
                                      RegExpNode* on_success) {
  ZoneGrowableArray<RegExpTree*>* children = nodes();
  RegExpNode* current = on_success;
  if (compiler->read_backward()) {
    for (intptr_t i = 0; i < children->length(); i++) {
      current = children->At(i)->ToNode(compiler, current);
    }
  } else {
    for (intptr_t i = children->length() - 1; i >= 0; i--) {
      current = children->At(i)->ToNode(compiler, current);
    }
  }
  return current;
}

static void AddClass(const int32_t* elmv,
                     intptr_t elmc,
                     ZoneGrowableArray<CharacterRange>* ranges) {
  elmc--;
  ASSERT(elmv[elmc] == kRangeEndMarker);
  for (intptr_t i = 0; i < elmc; i += 2) {
    ASSERT(elmv[i] < elmv[i + 1]);
    ranges->Add(CharacterRange(elmv[i], elmv[i + 1] - 1));
  }
}

static void AddClassNegated(const int32_t* elmv,
                            intptr_t elmc,
                            ZoneGrowableArray<CharacterRange>* ranges) {
  elmc--;
  ASSERT(elmv[elmc] == kRangeEndMarker);
  ASSERT(elmv[0] != 0x0000);
  ASSERT(elmv[elmc - 1] != Utf::kMaxCodePoint);
  uint16_t last = 0x0000;
  for (intptr_t i = 0; i < elmc; i += 2) {
    ASSERT(last <= elmv[i] - 1);
    ASSERT(elmv[i] < elmv[i + 1]);
    ranges->Add(CharacterRange(last, elmv[i] - 1));
    last = elmv[i + 1];
  }
  ranges->Add(CharacterRange(last, Utf::kMaxCodePoint));
}

void CharacterRange::AddClassEscape(uint16_t type,
                                    ZoneGrowableArray<CharacterRange>* ranges,
                                    bool add_unicode_case_equivalents) {
  if (add_unicode_case_equivalents && (type == 'w' || type == 'W')) {
    // See #sec-runtime-semantics-wordcharacters-abstract-operation
    // In case of unicode and ignore_case, we need to create the closure over
    // case equivalent characters before negating.
    ZoneGrowableArray<CharacterRange>* new_ranges =
        new ZoneGrowableArray<CharacterRange>(2);
    AddClass(kWordRanges, kWordRangeCount, new_ranges);
    AddUnicodeCaseEquivalents(new_ranges);
    if (type == 'W') {
      ZoneGrowableArray<CharacterRange>* negated =
          new ZoneGrowableArray<CharacterRange>(2);
      CharacterRange::Negate(new_ranges, negated);
      new_ranges = negated;
    }
    ranges->AddArray(*new_ranges);
    return;
  }
  AddClassEscape(type, ranges);
}

void CharacterRange::AddClassEscape(uint16_t type,
                                    ZoneGrowableArray<CharacterRange>* ranges) {
  switch (type) {
    case 's':
      AddClass(kSpaceRanges, kSpaceRangeCount, ranges);
      break;
    case 'S':
      AddClassNegated(kSpaceRanges, kSpaceRangeCount, ranges);
      break;
    case 'w':
      AddClass(kWordRanges, kWordRangeCount, ranges);
      break;
    case 'W':
      AddClassNegated(kWordRanges, kWordRangeCount, ranges);
      break;
    case 'd':
      AddClass(kDigitRanges, kDigitRangeCount, ranges);
      break;
    case 'D':
      AddClassNegated(kDigitRanges, kDigitRangeCount, ranges);
      break;
    case '.':
      AddClassNegated(kLineTerminatorRanges, kLineTerminatorRangeCount, ranges);
      break;
    // This is not a character range as defined by the spec but a
    // convenient shorthand for a character class that matches any
    // character.
    case '*':
      ranges->Add(CharacterRange::Everything());
      break;
    // This is the set of characters matched by the $ and ^ symbols
    // in multiline mode.
    case 'n':
      AddClass(kLineTerminatorRanges, kLineTerminatorRangeCount, ranges);
      break;
    default:
      UNREACHABLE();
  }
}

void CharacterRange::AddCaseEquivalents(
    ZoneGrowableArray<CharacterRange>* ranges,
    bool is_one_byte,
    Zone* zone) {
  CharacterRange::Canonicalize(ranges);
  int range_count = ranges->length();
  for (intptr_t i = 0; i < range_count; i++) {
    CharacterRange range = ranges->At(i);
    int32_t bottom = range.from();
    if (bottom > Utf16::kMaxCodeUnit) continue;
    int32_t top = Utils::Minimum(range.to(), Utf16::kMaxCodeUnit);
    // Nothing to be done for surrogates
    if (bottom >= Utf16::kLeadSurrogateStart &&
        top <= Utf16::kTrailSurrogateEnd) {
      continue;
    }
    if (is_one_byte && !RangeContainsLatin1Equivalents(range)) {
      if (bottom > Symbols::kMaxOneCharCodeSymbol) continue;
      if (top > Symbols::kMaxOneCharCodeSymbol) {
        top = Symbols::kMaxOneCharCodeSymbol;
      }
    }

    unibrow::Mapping<unibrow::Ecma262UnCanonicalize> jsregexp_uncanonicalize;
    unibrow::Mapping<unibrow::CanonicalizationRange> jsregexp_canonrange;
    int32_t chars[unibrow::Ecma262UnCanonicalize::kMaxWidth];
    if (top == bottom) {
      // If this is a singleton we just expand the one character.
      intptr_t length = jsregexp_uncanonicalize.get(bottom, '\0', chars);
      for (intptr_t i = 0; i < length; i++) {
        int32_t chr = chars[i];
        if (chr != bottom) {
          ranges->Add(CharacterRange::Singleton(chars[i]));
        }
      }
    } else {
      // If this is a range we expand the characters block by block,
      // expanding contiguous subranges (blocks) one at a time.
      // The approach is as follows.  For a given start character we
      // look up the remainder of the block that contains it (represented
      // by the end point), for instance we find 'z' if the character
      // is 'c'.  A block is characterized by the property
      // that all characters uncanonicalize in the same way, except that
      // each entry in the result is incremented by the distance from the first
      // element.  So a-z is a block because 'a' uncanonicalizes to ['a', 'A']
      // and the k'th letter uncanonicalizes to ['a' + k, 'A' + k].
      // Once we've found the end point we look up its uncanonicalization
      // and produce a range for each element.  For instance for [c-f]
      // we look up ['z', 'Z'] and produce [c-f] and [C-F].  We then only
      // add a range if it is not already contained in the input, so [c-f]
      // will be skipped but [C-F] will be added.  If this range is not
      // completely contained in a block we do this for all the blocks
      // covered by the range (handling characters that is not in a block
      // as a "singleton block").
      int32_t range[unibrow::Ecma262UnCanonicalize::kMaxWidth];
      intptr_t pos = bottom;
      while (pos <= top) {
        intptr_t length = jsregexp_canonrange.get(pos, '\0', range);
        int32_t block_end;
        if (length == 0) {
          block_end = pos;
        } else {
          ASSERT(length == 1);
          block_end = range[0];
        }
        intptr_t end = (block_end > top) ? top : block_end;
        length = jsregexp_uncanonicalize.get(block_end, '\0', range);
        for (intptr_t i = 0; i < length; i++) {
          int32_t c = range[i];
          int32_t range_from = c - (block_end - pos);
          int32_t range_to = c - (block_end - end);
          if (!(bottom <= range_from && range_to <= top)) {
            ranges->Add(CharacterRange(range_from, range_to));
          }
        }
        pos = end + 1;
      }
    }
  }
}

bool CharacterRange::IsCanonical(ZoneGrowableArray<CharacterRange>* ranges) {
  ASSERT(ranges != NULL);
  intptr_t n = ranges->length();
  if (n <= 1) return true;
  intptr_t max = ranges->At(0).to();
  for (intptr_t i = 1; i < n; i++) {
    CharacterRange next_range = ranges->At(i);
    if (next_range.from() <= max + 1) return false;
    max = next_range.to();
  }
  return true;
}

ZoneGrowableArray<CharacterRange>* CharacterSet::ranges() {
  if (ranges_ == NULL) {
    ranges_ = new ZoneGrowableArray<CharacterRange>(2);
    CharacterRange::AddClassEscape(standard_set_type_, ranges_);
  }
  return ranges_;
}

// Move a number of elements in a zone array to another position
// in the same array. Handles overlapping source and target areas.
static void MoveRanges(ZoneGrowableArray<CharacterRange>* list,
                       intptr_t from,
                       intptr_t to,
                       intptr_t count) {
  // Ranges are potentially overlapping.
  if (from < to) {
    for (intptr_t i = count - 1; i >= 0; i--) {
      (*list)[to + i] = list->At(from + i);
    }
  } else {
    for (intptr_t i = 0; i < count; i++) {
      (*list)[to + i] = list->At(from + i);
    }
  }
}

static intptr_t InsertRangeInCanonicalList(
    ZoneGrowableArray<CharacterRange>* list,
    intptr_t count,
    CharacterRange insert) {
  // Inserts a range into list[0..count[, which must be sorted
  // by from value and non-overlapping and non-adjacent, using at most
  // list[0..count] for the result. Returns the number of resulting
  // canonicalized ranges. Inserting a range may collapse existing ranges into
  // fewer ranges, so the return value can be anything in the range 1..count+1.
  int32_t from = insert.from();
  int32_t to = insert.to();
  intptr_t start_pos = 0;
  intptr_t end_pos = count;
  for (intptr_t i = count - 1; i >= 0; i--) {
    CharacterRange current = list->At(i);
    if (current.from() > to + 1) {
      end_pos = i;
    } else if (current.to() + 1 < from) {
      start_pos = i + 1;
      break;
    }
  }

  // Inserted range overlaps, or is adjacent to, ranges at positions
  // [start_pos..end_pos[. Ranges before start_pos or at or after end_pos are
  // not affected by the insertion.
  // If start_pos == end_pos, the range must be inserted before start_pos.
  // if start_pos < end_pos, the entire range from start_pos to end_pos
  // must be merged with the insert range.

  if (start_pos == end_pos) {
    // Insert between existing ranges at position start_pos.
    if (start_pos < count) {
      MoveRanges(list, start_pos, start_pos + 1, count - start_pos);
    }
    (*list)[start_pos] = insert;
    return count + 1;
  }
  if (start_pos + 1 == end_pos) {
    // Replace single existing range at position start_pos.
    CharacterRange to_replace = list->At(start_pos);
    intptr_t new_from = Utils::Minimum(to_replace.from(), from);
    intptr_t new_to = Utils::Maximum(to_replace.to(), to);
    (*list)[start_pos] = CharacterRange(new_from, new_to);
    return count;
  }
  // Replace a number of existing ranges from start_pos to end_pos - 1.
  // Move the remaining ranges down.

  intptr_t new_from = Utils::Minimum(list->At(start_pos).from(), from);
  intptr_t new_to = Utils::Maximum(list->At(end_pos - 1).to(), to);
  if (end_pos < count) {
    MoveRanges(list, end_pos, start_pos + 1, count - end_pos);
  }
  (*list)[start_pos] = CharacterRange(new_from, new_to);
  return count - (end_pos - start_pos) + 1;
}

void CharacterSet::Canonicalize() {
  // Special/default classes are always considered canonical. The result
  // of calling ranges() will be sorted.
  if (ranges_ == NULL) return;
  CharacterRange::Canonicalize(ranges_);
}

void CharacterRange::Canonicalize(
    ZoneGrowableArray<CharacterRange>* character_ranges) {
  if (character_ranges->length() <= 1) return;
  // Check whether ranges are already canonical (increasing, non-overlapping,
  // non-adjacent).
  intptr_t n = character_ranges->length();
  intptr_t max = character_ranges->At(0).to();
  intptr_t i = 1;
  while (i < n) {
    CharacterRange current = character_ranges->At(i);
    if (current.from() <= max + 1) {
      break;
    }
    max = current.to();
    i++;
  }
  // Canonical until the i'th range. If that's all of them, we are done.
  if (i == n) return;

  // The ranges at index i and forward are not canonicalized. Make them so by
  // doing the equivalent of insertion sort (inserting each into the previous
  // list, in order).
  // Notice that inserting a range can reduce the number of ranges in the
  // result due to combining of adjacent and overlapping ranges.
  intptr_t read = i;           // Range to insert.
  intptr_t num_canonical = i;  // Length of canonicalized part of list.
  do {
    num_canonical = InsertRangeInCanonicalList(character_ranges, num_canonical,
                                               character_ranges->At(read));
    read++;
  } while (read < n);
  character_ranges->TruncateTo(num_canonical);

  ASSERT(CharacterRange::IsCanonical(character_ranges));
}

void CharacterRange::Negate(ZoneGrowableArray<CharacterRange>* ranges,
                            ZoneGrowableArray<CharacterRange>* negated_ranges) {
  ASSERT(CharacterRange::IsCanonical(ranges));
  ASSERT(negated_ranges->length() == 0);
  intptr_t range_count = ranges->length();
  uint32_t from = 0;
  intptr_t i = 0;
  if (range_count > 0 && ranges->At(0).from() == 0) {
    from = ranges->At(0).to();
    i = 1;
  }
  while (i < range_count) {
    CharacterRange range = ranges->At(i);
    negated_ranges->Add(CharacterRange(from + 1, range.from() - 1));
    from = range.to();
    i++;
  }
  if (from < Utf::kMaxCodePoint) {
    negated_ranges->Add(CharacterRange(from + 1, Utf::kMaxCodePoint));
  }
}

// -------------------------------------------------------------------
// Splay tree

// Workaround for the fact that ZoneGrowableArray does not have contains().
static bool ArrayContains(ZoneGrowableArray<unsigned>* array, unsigned value) {
  for (intptr_t i = 0; i < array->length(); i++) {
    if (array->At(i) == value) {
      return true;
    }
  }
  return false;
}

OutSet* OutSet::Extend(unsigned value, Zone* zone) {
  if (Get(value)) return this;
  if (successors() != nullptr) {
    for (int i = 0; i < successors()->length(); i++) {
      OutSet* successor = successors()->At(i);
      if (successor->Get(value)) return successor;
    }
  } else {
    successors_ = new (zone) ZoneGrowableArray<OutSet*>(2);
  }
  OutSet* result = new (zone) OutSet(first_, remaining_);
  result->Set(value, zone);
  successors()->Add(result);
  return result;
}

void OutSet::Set(unsigned value, Zone* zone) {
  if (value < kFirstLimit) {
    first_ |= (1 << value);
  } else {
    if (remaining_ == NULL)
      remaining_ = new (zone) ZoneGrowableArray<unsigned>(1);

    bool remaining_contains_value = ArrayContains(remaining_, value);
    if (remaining_->is_empty() || !remaining_contains_value) {
      remaining_->Add(value);
    }
  }
}

bool OutSet::Get(unsigned value) const {
  if (value < kFirstLimit) {
    return (first_ & (1 << value)) != 0;
  } else if (remaining_ == NULL) {
    return false;
  } else {
    return ArrayContains(remaining_, value);
  }
}

const int32_t DispatchTable::Config::kNoKey = Utf::kInvalidChar;

void DispatchTable::AddRange(CharacterRange full_range,
                             int32_t value,
                             Zone* zone) {
  CharacterRange current = full_range;
  if (tree()->is_empty()) {
    // If this is the first range we just insert into the table.
    ZoneSplayTree<Config>::Locator loc;
    bool inserted = tree()->Insert(current.from(), &loc);
    ASSERT(inserted);
    USE(inserted);
    loc.set_value(
        Entry(current.from(), current.to(), empty()->Extend(value, zone)));
    return;
  }
  // First see if there is a range to the left of this one that
  // overlaps.
  ZoneSplayTree<Config>::Locator loc;
  if (tree()->FindGreatestLessThan(current.from(), &loc)) {
    Entry* entry = &loc.value();
    // If we've found a range that overlaps with this one, and it
    // starts strictly to the left of this one, we have to fix it
    // because the following code only handles ranges that start on
    // or after the start point of the range we're adding.
    if (entry->from() < current.from() && entry->to() >= current.from()) {
      // Snap the overlapping range in half around the start point of
      // the range we're adding.
      CharacterRange left =
          CharacterRange::Range(entry->from(), current.from() - 1);
      CharacterRange right = CharacterRange::Range(current.from(), entry->to());
      // The left part of the overlapping range doesn't overlap.
      // Truncate the whole entry to be just the left part.
      entry->set_to(left.to());
      // The right part is the one that overlaps.  We add this part
      // to the map and let the next step deal with merging it with
      // the range we're adding.
      ZoneSplayTree<Config>::Locator loc;
      bool inserted = tree()->Insert(right.from(), &loc);
      ASSERT(inserted);
      USE(inserted);
      loc.set_value(Entry(right.from(), right.to(), entry->out_set()));
    }
  }
  while (current.is_valid()) {
    if (tree()->FindLeastGreaterThan(current.from(), &loc) &&
        (loc.value().from() <= current.to()) &&
        (loc.value().to() >= current.from())) {
      Entry* entry = &loc.value();
      // We have overlap.  If there is space between the start point of
      // the range we're adding and where the overlapping range starts
      // then we have to add a range covering just that space.
      if (current.from() < entry->from()) {
        ZoneSplayTree<Config>::Locator ins;
        bool inserted = tree()->Insert(current.from(), &ins);
        ASSERT(inserted);
        USE(inserted);
        ins.set_value(Entry(current.from(), entry->from() - 1,
                            empty()->Extend(value, zone)));
        current.set_from(entry->from());
      }
      ASSERT(current.from() == entry->from());
      // If the overlapping range extends beyond the one we want to add
      // we have to snap the right part off and add it separately.
      if (entry->to() > current.to()) {
        ZoneSplayTree<Config>::Locator ins;
        bool inserted = tree()->Insert(current.to() + 1, &ins);
        ASSERT(inserted);
        USE(inserted);
        ins.set_value(Entry(current.to() + 1, entry->to(), entry->out_set()));
        entry->set_to(current.to());
      }
      ASSERT(entry->to() <= current.to());
      // The overlapping range is now completely contained by the range
      // we're adding so we can just update it and move the start point
      // of the range we're adding just past it.
      entry->AddValue(value, zone);
      ASSERT(entry->to() + 1 > current.from());
      current.set_from(entry->to() + 1);
    } else {
      // There is no overlap so we can just add the range
      ZoneSplayTree<Config>::Locator ins;
      bool inserted = tree()->Insert(current.from(), &ins);
      ASSERT(inserted);
      USE(inserted);
      ins.set_value(
          Entry(current.from(), current.to(), empty()->Extend(value, zone)));
      break;
    }
  }
}

OutSet* DispatchTable::Get(int32_t value) {
  ZoneSplayTree<Config>::Locator loc;
  if (!tree()->FindGreatestLessThan(value, &loc)) return empty();
  Entry* entry = &loc.value();
  if (value <= entry->to())
    return entry->out_set();
  else
    return empty();
}

// -------------------------------------------------------------------
// Analysis

void Analysis::EnsureAnalyzed(RegExpNode* that) {
  if (that->info()->been_analyzed || that->info()->being_analyzed) return;
  that->info()->being_analyzed = true;
  that->Accept(this);
  that->info()->being_analyzed = false;
  that->info()->been_analyzed = true;
}

void Analysis::VisitEnd(EndNode* that) {
  // nothing to do
}

void TextNode::CalculateOffsets() {
  intptr_t element_count = elements()->length();
  // Set up the offsets of the elements relative to the start.  This is a fixed
  // quantity since a TextNode can only contain fixed-width things.
  intptr_t cp_offset = 0;
  for (intptr_t i = 0; i < element_count; i++) {
    TextElement& elm = (*elements())[i];
    elm.set_cp_offset(cp_offset);
    cp_offset += elm.length();
  }
}

void Analysis::VisitText(TextNode* that) {
  that->MakeCaseIndependent(is_one_byte_);
  EnsureAnalyzed(that->on_success());
  if (!has_failed()) {
    that->CalculateOffsets();
  }
}

void Analysis::VisitAction(ActionNode* that) {
  RegExpNode* target = that->on_success();
  EnsureAnalyzed(target);
  if (!has_failed()) {
    // If the next node is interested in what it follows then this node
    // has to be interested too so it can pass the information on.
    that->info()->AddFromFollowing(target->info());
  }
}

void Analysis::VisitChoice(ChoiceNode* that) {
  NodeInfo* info = that->info();
  for (intptr_t i = 0; i < that->alternatives()->length(); i++) {
    RegExpNode* node = (*that->alternatives())[i].node();
    EnsureAnalyzed(node);
    if (has_failed()) return;
    // Anything the following nodes need to know has to be known by
    // this node also, so it can pass it on.
    info->AddFromFollowing(node->info());
  }
}

void Analysis::VisitLoopChoice(LoopChoiceNode* that) {
  NodeInfo* info = that->info();
  for (intptr_t i = 0; i < that->alternatives()->length(); i++) {
    RegExpNode* node = (*that->alternatives())[i].node();
    if (node != that->loop_node()) {
      EnsureAnalyzed(node);
      if (has_failed()) return;
      info->AddFromFollowing(node->info());
    }
  }
  // Check the loop last since it may need the value of this node
  // to get a correct result.
  EnsureAnalyzed(that->loop_node());
  if (!has_failed()) {
    info->AddFromFollowing(that->loop_node()->info());
  }
}

void Analysis::VisitBackReference(BackReferenceNode* that) {
  EnsureAnalyzed(that->on_success());
}

void Analysis::VisitAssertion(AssertionNode* that) {
  EnsureAnalyzed(that->on_success());
}

void BackReferenceNode::FillInBMInfo(intptr_t offset,
                                     intptr_t budget,
                                     BoyerMooreLookahead* bm,
                                     bool not_at_start) {
  // Working out the set of characters that a backreference can match is too
  // hard, so we just say that any character can match.
  bm->SetRest(offset);
  SaveBMInfo(bm, not_at_start, offset);
}

COMPILE_ASSERT(BoyerMoorePositionInfo::kMapSize ==
               RegExpMacroAssembler::kTableSize);

void ChoiceNode::FillInBMInfo(intptr_t offset,
                              intptr_t budget,
                              BoyerMooreLookahead* bm,
                              bool not_at_start) {
  ZoneGrowableArray<GuardedAlternative>* alts = alternatives();
  budget = (budget - 1) / alts->length();
  for (intptr_t i = 0; i < alts->length(); i++) {
    GuardedAlternative& alt = (*alts)[i];
    if (alt.guards() != NULL && alt.guards()->length() != 0) {
      bm->SetRest(offset);  // Give up trying to fill in info.
      SaveBMInfo(bm, not_at_start, offset);
      return;
    }
    alt.node()->FillInBMInfo(offset, budget, bm, not_at_start);
  }
  SaveBMInfo(bm, not_at_start, offset);
}

void TextNode::FillInBMInfo(intptr_t initial_offset,
                            intptr_t budget,
                            BoyerMooreLookahead* bm,
                            bool not_at_start) {
  if (initial_offset >= bm->length()) return;
  intptr_t offset = initial_offset;
  intptr_t max_char = bm->max_char();
  for (intptr_t i = 0; i < elements()->length(); i++) {
    if (offset >= bm->length()) {
      if (initial_offset == 0) set_bm_info(not_at_start, bm);
      return;
    }
    TextElement text = elements()->At(i);
    if (text.text_type() == TextElement::ATOM) {
      RegExpAtom* atom = text.atom();
      for (intptr_t j = 0; j < atom->length(); j++, offset++) {
        if (offset >= bm->length()) {
          if (initial_offset == 0) set_bm_info(not_at_start, bm);
          return;
        }
        uint16_t character = atom->data()->At(j);
        if (atom->flags().IgnoreCase()) {
          int32_t chars[unibrow::Ecma262UnCanonicalize::kMaxWidth];
          intptr_t length = GetCaseIndependentLetters(
              character, bm->max_char() == Symbols::kMaxOneCharCodeSymbol,
              chars);
          for (intptr_t j = 0; j < length; j++) {
            bm->Set(offset, chars[j]);
          }
        } else {
          if (character <= max_char) bm->Set(offset, character);
        }
      }
    } else {
      ASSERT(text.text_type() == TextElement::CHAR_CLASS);
      RegExpCharacterClass* char_class = text.char_class();
      ZoneGrowableArray<CharacterRange>* ranges = char_class->ranges();
      if (char_class->is_negated()) {
        bm->SetAll(offset);
      } else {
        for (intptr_t k = 0; k < ranges->length(); k++) {
          const CharacterRange& range = ranges->At(k);
          if (range.from() > max_char) continue;
          intptr_t to =
              Utils::Minimum(max_char, static_cast<intptr_t>(range.to()));
          bm->SetInterval(offset, Interval(range.from(), to));
        }
      }
      offset++;
    }
  }
  if (offset >= bm->length()) {
    if (initial_offset == 0) set_bm_info(not_at_start, bm);
    return;
  }
  on_success()->FillInBMInfo(offset, budget - 1, bm,
                             true);  // Not at start after a text node.
  if (initial_offset == 0) set_bm_info(not_at_start, bm);
}

RegExpNode* OptionallyStepBackToLeadSurrogate(RegExpCompiler* compiler,
                                              RegExpNode* on_success,
                                              RegExpFlags flags) {
  // If the regexp matching starts within a surrogate pair, step back
  // to the lead surrogate and start matching from there.
  ASSERT(!compiler->read_backward());
  Zone* zone = compiler->zone();

  auto lead_surrogates = CharacterRange::List(
      on_success->zone(), CharacterRange::Range(Utf16::kLeadSurrogateStart,
                                                Utf16::kLeadSurrogateEnd));
  auto trail_surrogates = CharacterRange::List(
      on_success->zone(), CharacterRange::Range(Utf16::kTrailSurrogateStart,
                                                Utf16::kTrailSurrogateEnd));

  ChoiceNode* optional_step_back = new (zone) ChoiceNode(2, zone);

  int stack_register = compiler->UnicodeLookaroundStackRegister();
  int position_register = compiler->UnicodeLookaroundPositionRegister();
  RegExpNode* step_back = TextNode::CreateForCharacterRanges(
      lead_surrogates, /*read_backward=*/true, on_success, flags);
  RegExpLookaround::Builder builder(/*is_positive=*/true, step_back,
                                    stack_register, position_register);
  RegExpNode* match_trail = TextNode::CreateForCharacterRanges(
      trail_surrogates, /*read_backward=*/false, builder.on_match_success(),
      flags);

  optional_step_back->AddAlternative(
      GuardedAlternative(builder.ForMatch(match_trail)));
  optional_step_back->AddAlternative(GuardedAlternative(on_success));

  return optional_step_back;
}

#if !defined(DART_PRECOMPILED_RUNTIME)
RegExpEngine::CompilationResult RegExpEngine::CompileIR(
    RegExpCompileData* data,
    const ParsedFunction* parsed_function,
    const ZoneGrowableArray<const ICData*>& ic_data_array,
    intptr_t osr_id) {
  ASSERT(!FLAG_interpret_irregexp);
  Zone* zone = Thread::Current()->zone();

  const Function& function = parsed_function->function();
  const intptr_t specialization_cid = function.string_specialization_cid();
  const intptr_t is_sticky = function.is_sticky_specialization();
  const bool is_one_byte = (specialization_cid == kOneByteStringCid ||
                            specialization_cid == kExternalOneByteStringCid);
  RegExp& regexp = RegExp::Handle(zone, function.regexp());
  const String& pattern = String::Handle(zone, regexp.pattern());

  ASSERT(!regexp.IsNull());
  ASSERT(!pattern.IsNull());

  const bool is_global = regexp.flags().IsGlobal();
  const bool is_unicode = regexp.flags().IsUnicode();

  RegExpCompiler compiler(data->capture_count, is_one_byte);

  // TODO(zerny): Frequency sampling is currently disabled because of several
  // issues. We do not want to store subject strings in the regexp object since
  // they might be long and we should not prevent their garbage collection.
  // Passing them to this function explicitly does not help, since we must
  // generate exactly the same IR for both the unoptimizing and optimizing
  // pipelines (otherwise it gets confused when i.e. deopt id's differ).
  // An option would be to store sampling results in the regexp object, but
  // I'm not sure the performance gains are relevant enough.

  // Wrap the body of the regexp in capture #0.
  RegExpNode* captured_body =
      RegExpCapture::ToNode(data->tree, 0, &compiler, compiler.accept());

  RegExpNode* node = captured_body;
  const bool is_end_anchored = data->tree->IsAnchoredAtEnd();
  const bool is_start_anchored = data->tree->IsAnchoredAtStart();
  intptr_t max_length = data->tree->max_match();
  if (!is_start_anchored && !is_sticky) {
    // Add a .*? at the beginning, outside the body capture, unless
    // this expression is anchored at the beginning or is sticky.
    RegExpNode* loop_node = RegExpQuantifier::ToNode(
        0, RegExpTree::kInfinity, false,
        new (zone) RegExpCharacterClass('*', RegExpFlags()), &compiler,
        captured_body, data->contains_anchor);

    if (data->contains_anchor) {
      // Unroll loop once, to take care of the case that might start
      // at the start of input.
      ChoiceNode* first_step_node = new (zone) ChoiceNode(2, zone);
      first_step_node->AddAlternative(GuardedAlternative(captured_body));
      first_step_node->AddAlternative(GuardedAlternative(new (zone) TextNode(
          new (zone) RegExpCharacterClass('*', RegExpFlags()),
          /*read_backwards=*/false, loop_node)));
      node = first_step_node;
    } else {
      node = loop_node;
    }
  }
  if (is_one_byte) {
    node = node->FilterOneByte(RegExpCompiler::kMaxRecursion);
    // Do it again to propagate the new nodes to places where they were not
    // put because they had not been calculated yet.
    if (node != NULL) {
      node = node->FilterOneByte(RegExpCompiler::kMaxRecursion);
    }
  } else if (is_unicode && (is_global || is_sticky)) {
    node = OptionallyStepBackToLeadSurrogate(&compiler, node, regexp.flags());
  }

  if (node == NULL) node = new (zone) EndNode(EndNode::BACKTRACK, zone);
  data->node = node;
  Analysis analysis(is_one_byte);
  analysis.EnsureAnalyzed(node);
  if (analysis.has_failed()) {
    const char* error_message = analysis.error_message();
    return CompilationResult(error_message);
  }

  // Native regexp implementation.

  IRRegExpMacroAssembler* macro_assembler = new (zone)
      IRRegExpMacroAssembler(specialization_cid, data->capture_count,
                             parsed_function, ic_data_array, osr_id, zone);

  // Inserted here, instead of in Assembler, because it depends on information
  // in the AST that isn't replicated in the Node structure.
  static const intptr_t kMaxBacksearchLimit = 1024;
  if (is_end_anchored && !is_start_anchored && !is_sticky &&
      max_length < kMaxBacksearchLimit) {
    macro_assembler->SetCurrentPositionFromEnd(max_length);
  }

  if (is_global) {
    RegExpMacroAssembler::GlobalMode mode = RegExpMacroAssembler::GLOBAL;
    if (data->tree->min_match() > 0) {
      mode = RegExpMacroAssembler::GLOBAL_NO_ZERO_LENGTH_CHECK;
    } else if (is_unicode) {
      mode = RegExpMacroAssembler::GLOBAL_UNICODE;
    }
    macro_assembler->set_global_mode(mode);
  }

  RegExpEngine::CompilationResult result =
      compiler.Assemble(macro_assembler, node, data->capture_count, pattern);

  if (FLAG_trace_irregexp) {
    macro_assembler->PrintBlocks();
  }

  return result;
}
#endif  // !defined(DART_PRECOMPILED_RUNTIME)

RegExpEngine::CompilationResult RegExpEngine::CompileBytecode(
    RegExpCompileData* data,
    const RegExp& regexp,
    bool is_one_byte,
    bool is_sticky,
    Zone* zone) {
  ASSERT(FLAG_interpret_irregexp);
  const String& pattern = String::Handle(zone, regexp.pattern());

  ASSERT(!regexp.IsNull());
  ASSERT(!pattern.IsNull());

  const bool is_global = regexp.flags().IsGlobal();
  const bool is_unicode = regexp.flags().IsUnicode();

  RegExpCompiler compiler(data->capture_count, is_one_byte);

  // TODO(zerny): Frequency sampling is currently disabled because of several
  // issues. We do not want to store subject strings in the regexp object since
  // they might be long and we should not prevent their garbage collection.
  // Passing them to this function explicitly does not help, since we must
  // generate exactly the same IR for both the unoptimizing and optimizing
  // pipelines (otherwise it gets confused when i.e. deopt id's differ).
  // An option would be to store sampling results in the regexp object, but
  // I'm not sure the performance gains are relevant enough.

  // Wrap the body of the regexp in capture #0.
  RegExpNode* captured_body =
      RegExpCapture::ToNode(data->tree, 0, &compiler, compiler.accept());

  RegExpNode* node = captured_body;
  bool is_end_anchored = data->tree->IsAnchoredAtEnd();
  bool is_start_anchored = data->tree->IsAnchoredAtStart();
  intptr_t max_length = data->tree->max_match();
  if (!is_start_anchored && !is_sticky) {
    // Add a .*? at the beginning, outside the body capture, unless
    // this expression is anchored at the beginning.
    RegExpNode* loop_node = RegExpQuantifier::ToNode(
        0, RegExpTree::kInfinity, false,
        new (zone) RegExpCharacterClass('*', RegExpFlags()), &compiler,
        captured_body, data->contains_anchor);

    if (data->contains_anchor) {
      // Unroll loop once, to take care of the case that might start
      // at the start of input.
      ChoiceNode* first_step_node = new (zone) ChoiceNode(2, zone);
      first_step_node->AddAlternative(GuardedAlternative(captured_body));
      first_step_node->AddAlternative(GuardedAlternative(new (zone) TextNode(
          new (zone) RegExpCharacterClass('*', RegExpFlags()),
          /*read_backwards=*/false, loop_node)));
      node = first_step_node;
    } else {
      node = loop_node;
    }
  }
  if (is_one_byte) {
    node = node->FilterOneByte(RegExpCompiler::kMaxRecursion);
    // Do it again to propagate the new nodes to places where they were not
    // put because they had not been calculated yet.
    if (node != NULL) {
      node = node->FilterOneByte(RegExpCompiler::kMaxRecursion);
    }
  } else if (is_unicode && (is_global || is_sticky)) {
    node = OptionallyStepBackToLeadSurrogate(&compiler, node, regexp.flags());
  }

  if (node == NULL) node = new (zone) EndNode(EndNode::BACKTRACK, zone);
  data->node = node;
  Analysis analysis(is_one_byte);
  analysis.EnsureAnalyzed(node);
  if (analysis.has_failed()) {
    const char* error_message = analysis.error_message();
    return CompilationResult(error_message);
  }

  // Bytecode regexp implementation.

  ZoneGrowableArray<uint8_t> buffer(zone, 1024);
  BytecodeRegExpMacroAssembler* macro_assembler =
      new (zone) BytecodeRegExpMacroAssembler(&buffer, zone);

  // Inserted here, instead of in Assembler, because it depends on information
  // in the AST that isn't replicated in the Node structure.
  static const intptr_t kMaxBacksearchLimit = 1024;
  if (is_end_anchored && !is_start_anchored && !is_sticky &&
      max_length < kMaxBacksearchLimit) {
    macro_assembler->SetCurrentPositionFromEnd(max_length);
  }

  if (is_global) {
    RegExpMacroAssembler::GlobalMode mode = RegExpMacroAssembler::GLOBAL;
    if (data->tree->min_match() > 0) {
      mode = RegExpMacroAssembler::GLOBAL_NO_ZERO_LENGTH_CHECK;
    } else if (is_unicode) {
      mode = RegExpMacroAssembler::GLOBAL_UNICODE;
    }
    macro_assembler->set_global_mode(mode);
  }

  RegExpEngine::CompilationResult result =
      compiler.Assemble(macro_assembler, node, data->capture_count, pattern);

  if (FLAG_trace_irregexp) {
    macro_assembler->PrintBlocks();
  }

  return result;
}

static void CreateSpecializedFunction(Thread* thread,
                                      Zone* zone,
                                      const RegExp& regexp,
                                      intptr_t specialization_cid,
                                      bool sticky,
                                      const Object& owner) {
  const intptr_t kParamCount = RegExpMacroAssembler::kParamCount;

  Function& fn =
      Function::Handle(zone, Function::New(Symbols::ColonMatcher(),
                                           RawFunction::kIrregexpFunction,
                                           true,   // Static.
                                           false,  // Not const.
                                           false,  // Not abstract.
                                           false,  // Not external.
                                           false,  // Not native.
                                           owner, TokenPosition::kMinSource));

  // TODO(zerny): Share these arrays between all irregexp functions.
  fn.set_num_fixed_parameters(kParamCount);
  fn.set_parameter_types(
      Array::Handle(zone, Array::New(kParamCount, Heap::kOld)));
  fn.set_parameter_names(
      Array::Handle(zone, Array::New(kParamCount, Heap::kOld)));
  fn.SetParameterTypeAt(RegExpMacroAssembler::kParamRegExpIndex,
                        Object::dynamic_type());
  fn.SetParameterNameAt(RegExpMacroAssembler::kParamRegExpIndex,
                        Symbols::This());
  fn.SetParameterTypeAt(RegExpMacroAssembler::kParamStringIndex,
                        Object::dynamic_type());
  fn.SetParameterNameAt(RegExpMacroAssembler::kParamStringIndex,
                        Symbols::string_param());
  fn.SetParameterTypeAt(RegExpMacroAssembler::kParamStartOffsetIndex,
                        Object::dynamic_type());
  fn.SetParameterNameAt(RegExpMacroAssembler::kParamStartOffsetIndex,
                        Symbols::start_index_param());
  fn.set_result_type(Type::Handle(zone, Type::ArrayType()));

  // Cache the result.
  regexp.set_function(specialization_cid, sticky, fn);

  fn.SetRegExpData(regexp, specialization_cid, sticky);
  fn.set_is_debuggable(false);

  // The function is compiled lazily during the first call.
}

RawRegExp* RegExpEngine::CreateRegExp(Thread* thread,
                                      const String& pattern,
                                      RegExpFlags flags) {
  Zone* zone = thread->zone();
  const RegExp& regexp = RegExp::Handle(RegExp::New());

  regexp.set_pattern(pattern);
  regexp.set_flags(flags);

  // TODO(zerny): We might want to use normal string searching algorithms
  // for simple patterns.
  regexp.set_is_complex();
  regexp.set_is_global();  // All dart regexps are global.

  if (!FLAG_interpret_irregexp) {
    const Library& lib = Library::Handle(zone, Library::CoreLibrary());
    const Class& owner =
        Class::Handle(zone, lib.LookupClass(Symbols::RegExp()));

    for (intptr_t cid = kOneByteStringCid; cid <= kExternalTwoByteStringCid;
         cid++) {
      CreateSpecializedFunction(thread, zone, regexp, cid, /*sticky=*/false,
                                owner);
      CreateSpecializedFunction(thread, zone, regexp, cid, /*sticky=*/true,
                                owner);
    }
  }

  return regexp.raw();
}

}  // namespace dart
