// 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_ast.h"
#include "vm/symbols.h"
#include "vm/thread.h"
#include "vm/unibrow-inl.h"

#if !defined(DART_PRECOMPILED_RUNTIME)
#include "vm/regexp_assembler_ir.h"
#endif  // !defined(DART_PRECOMPILED_RUNTIME)

#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()->is_bound()) {
    // 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()->is_bound()) {
    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.is_linked());
  // 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.is_linked()) {
    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_.is_bound()) {
      // 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->one_byte()) {
#if !defined(DART_COMPRESSED_POINTERS) && !defined(TARGET_ARCH_RISCV32)
    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
    // Ensure LoadCodeUnitsInstr can always produce a Smi. See
    // https://github.com/dart-lang/sdk/issues/29951
    if (preload_characters > 2) preload_characters = 2;
#endif
  } else {
#if !defined(DART_COMPRESSED_POINTERS) && !defined(TARGET_ARCH_RISCV32)
    if (preload_characters > 2) preload_characters = 2;
#else
    // Ensure LoadCodeUnitsInstr can always produce a Smi. See
    // https://github.com/dart-lang/sdk/issues/29951
    if (preload_characters > 1) preload_characters = 1;
#endif
  }
  if (!compiler->macro_assembler()->CanReadUnaligned()) {
    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.is_linked()) 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] != '\0'; 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->is_bound()) printer.PrintPositive("@", label->pos());
  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, ChoiceTable::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 ChoiceTable::Config::kNoKey = Utf::kInvalidChar;

void ChoiceTable::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* ChoiceTable::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 bool 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;
}

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

  const FunctionType& signature =
      FunctionType::Handle(zone, FunctionType::New());
  Function& fn =
      Function::Handle(zone, Function::New(signature, Symbols::ColonMatcher(),
                                           UntaggedFunction::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.
  // TODO(regis): Better, share a common signature.
  signature.set_num_fixed_parameters(kParamCount);
  signature.set_parameter_types(
      Array::Handle(zone, Array::New(kParamCount, Heap::kOld)));
  fn.CreateNameArray();
  signature.SetParameterTypeAt(RegExpMacroAssembler::kParamRegExpIndex,
                               Object::dynamic_type());
  fn.SetParameterNameAt(RegExpMacroAssembler::kParamRegExpIndex,
                        Symbols::This());
  signature.SetParameterTypeAt(RegExpMacroAssembler::kParamStringIndex,
                               Object::dynamic_type());
  fn.SetParameterNameAt(RegExpMacroAssembler::kParamStringIndex,
                        Symbols::string_param());
  signature.SetParameterTypeAt(RegExpMacroAssembler::kParamStartOffsetIndex,
                               Object::dynamic_type());
  fn.SetParameterNameAt(RegExpMacroAssembler::kParamStartOffsetIndex,
                        Symbols::start_index_param());
  signature.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.
}

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

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

}  // namespace dart
