// 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_assembler.h"

#include "vm/bit_vector.h"
#include "vm/compiler.h"
#include "vm/dart_entry.h"
#include "vm/flow_graph_builder.h"
#include "vm/il_printer.h"
#include "vm/object_store.h"
#include "vm/regexp.h"
#include "vm/resolver.h"
#include "vm/stack_frame.h"
#include "vm/unibrow-inl.h"
#include "vm/unicode.h"

#define I isolate()

// Debugging output macros. TAG() is called at the head of each interesting
// function and prints its name during execution if irregexp tracing is enabled.
#define TAG() if (FLAG_trace_irregexp) { TAG_(); }
#define TAG_() \
  Print(PushArgument( \
    Bind(new(I) ConstantInstr(String::ZoneHandle(I, String::Concat( \
        String::Handle(String::New("TAG: ")), \
        String::Handle(String::New(__FUNCTION__)), Heap::kOld))))));

#define PRINT(arg) if (FLAG_trace_irregexp) { Print(arg); }

namespace dart {

DEFINE_FLAG(bool, trace_irregexp, false, "Trace irregexps");


static const intptr_t kInvalidTryIndex = CatchClauseNode::kInvalidTryIndex;
static const intptr_t kNoSourcePos = Scanner::kNoSourcePos;
static const intptr_t kMinStackSize = 512;


void PrintUtf16(uint16_t c) {
  const char* format = (0x20 <= c && c <= 0x7F) ?
        "%c" : (c <= 0xff) ? "\\x%02x" : "\\u%04x";
  OS::Print(format, c);
}


/*
 * This assembler uses the following main local variables:
 * - stack_: A pointer to a growable list which we use as an all-purpose stack
 *           storing backtracking offsets, positions & stored register values.
 * - current_character_: Stores the currently loaded characters (possibly more
 *                       than one).
 * - current_position_: The current position within the string, stored as a
 *                      negative offset from the end of the string (i.e. the
 *                      position corresponding to str[0] is -str.length).
 *                      Note that current_position_ is *not* byte-based, unlike
 *                      original V8 code.
 *
 * Results are returned though an array of capture indices, stored at
 * matches_param_. A null array specifies a failure to match. The match indices
 * [start_inclusive, end_exclusive] for capture group i are stored at positions
 * matches_param_[i * 2] and matches_param_[i * 2 + 1], respectively. Match
 * indices of -1 denote non-matched groups. Note that we store these indices
 * as a negative offset from the end of the string in registers_array_
 * during processing, and convert them to standard indexes when copying them
 * to matches_param_ on successful match.
 */

RegExpMacroAssembler::RegExpMacroAssembler(Isolate* isolate)
  : slow_safe_compiler_(false),
    global_mode_(NOT_GLOBAL),
    isolate_(isolate) {
}


RegExpMacroAssembler::~RegExpMacroAssembler() {
}


IRRegExpMacroAssembler::IRRegExpMacroAssembler(
    intptr_t specialization_cid,
    intptr_t capture_count,
    const ParsedFunction* parsed_function,
    const ZoneGrowableArray<const ICData*>& ic_data_array,
    Isolate* isolate)
    : RegExpMacroAssembler(isolate),
      specialization_cid_(specialization_cid),
      parsed_function_(parsed_function),
      ic_data_array_(ic_data_array),
      current_instruction_(NULL),
      stack_(NULL),
      stack_pointer_(NULL),
      current_character_(NULL),
      current_position_(NULL),
      string_param_(NULL),
      string_param_length_(NULL),
      start_index_param_(NULL),
      registers_count_(0),
      saved_registers_count_((capture_count + 1) * 2),
      stack_array_cell_(Array::ZoneHandle(isolate, Array::New(1, Heap::kOld))),
      // The registers array is allocated at a fixed size after assembly.
      registers_array_(TypedData::ZoneHandle(isolate, TypedData::null())) {
  switch (specialization_cid) {
    case kOneByteStringCid:
    case kExternalOneByteStringCid: mode_ = ASCII; break;
    case kTwoByteStringCid:
    case kExternalTwoByteStringCid: mode_ = UC16; break;
    default: UNREACHABLE();
  }

  InitializeLocals();

  // Allocate an initial stack backing of the minimum stack size. The stack
  // backing is indirectly referred to so we can reuse it on subsequent matches
  // even in the case where the backing has been enlarged and thus reallocated.
  stack_array_cell_.SetAt(0, TypedData::Handle(isolate,
    TypedData::New(kTypedDataInt32ArrayCid, kMinStackSize / 4, Heap::kOld)));

  // Create and generate all preset blocks.
  entry_block_ =
      new(isolate) GraphEntryInstr(
        parsed_function_,
        new(isolate) TargetEntryInstr(block_id_.Alloc(), kInvalidTryIndex),
        Isolate::kNoDeoptId);
  start_block_ =
      new(isolate) JoinEntryInstr(block_id_.Alloc(), kInvalidTryIndex);
  success_block_ =
      new(isolate) JoinEntryInstr(block_id_.Alloc(), kInvalidTryIndex);
  backtrack_block_ =
      new(isolate) JoinEntryInstr(block_id_.Alloc(), kInvalidTryIndex);
  exit_block_ =
      new(isolate) JoinEntryInstr(block_id_.Alloc(), kInvalidTryIndex);

  GenerateEntryBlock();
  GenerateSuccessBlock();
  GenerateExitBlock();

  blocks_.Add(entry_block_);
  blocks_.Add(entry_block_->normal_entry());
  blocks_.Add(start_block_);
  blocks_.Add(success_block_);
  blocks_.Add(backtrack_block_);
  blocks_.Add(exit_block_);

  // Begin emission at the start_block_.
  set_current_instruction(start_block_);
}


IRRegExpMacroAssembler::~IRRegExpMacroAssembler() { }


void IRRegExpMacroAssembler::InitializeLocals() {
  // All generated functions are expected to have a current-context variable.
  // This variable is unused in irregexp functions.
  parsed_function_->current_context_var()->set_index(GetNextLocalIndex());

  // Create local variables and parameters.
  stack_ = Local(Symbols::stack());
  stack_pointer_ = Local(Symbols::stack_pointer());
  registers_ = Local(Symbols::position_registers());
  current_character_ = Local(Symbols::current_character());
  current_position_ = Local(Symbols::current_position());
  string_param_length_ = Local(Symbols::string_param_length());
  capture_length_ = Local(Symbols::capture_length());
  match_start_index_ = Local(Symbols::match_start_index());
  capture_start_index_ = Local(Symbols::capture_start_index());
  match_end_index_ = Local(Symbols::match_end_index());
  char_in_capture_ = Local(Symbols::char_in_capture());
  char_in_match_ = Local(Symbols::char_in_match());
  index_temp_ = Local(Symbols::index_temp());
  result_ = Local(Symbols::result());

  string_param_ = Parameter(Symbols::string_param(), 0);
  start_index_param_ = Parameter(Symbols::start_index_param(), 1);
}


void IRRegExpMacroAssembler::GenerateEntryBlock() {
  set_current_instruction(entry_block_->normal_entry());
  TAG();

  // Store string.length.
  PushArgumentInstr* string_push = PushLocal(string_param_);

  StoreLocal(
      string_param_length_,
      Bind(InstanceCall(
          InstanceCallDescriptor(
              String::ZoneHandle(Field::GetterSymbol(Symbols::Length()))),
          string_push)));

  // Store (start_index - string.length) as the current position (since it's a
  // negative offset from the end of the string).
  PushArgumentInstr* start_index_push = PushLocal(start_index_param_);
  PushArgumentInstr* length_push = PushLocal(string_param_length_);

  StoreLocal(current_position_, Bind(Sub(start_index_push, length_push)));

  // Generate a local list variable to represent "registers" and
  // initialize capture registers (others remain garbage).
  StoreLocal(registers_, Bind(new(I) ConstantInstr(registers_array_)));
  ClearRegisters(0, saved_registers_count_ - 1);

  // Generate a local list variable to represent the backtracking stack.
  PushArgumentInstr* stack_cell_push =
      PushArgument(Bind(new(I) ConstantInstr(stack_array_cell_)));
  StoreLocal(stack_, Bind(InstanceCall(
      InstanceCallDescriptor::FromToken(Token::kINDEX),
      stack_cell_push,
      PushArgument(Bind(Uint64Constant(0))))));
  StoreLocal(stack_pointer_, Bind(Int64Constant(-1)));

  // Jump to the start block.
  current_instruction_->Goto(start_block_);
}


void IRRegExpMacroAssembler::GenerateBacktrackBlock() {
  set_current_instruction(backtrack_block_);
  TAG();
  CheckPreemption();

  const intptr_t entries_count = entry_block_->indirect_entries().length();

  TypedData& offsets = TypedData::ZoneHandle(I,
      TypedData::New(kTypedDataInt32ArrayCid, entries_count, Heap::kOld));

  PushArgumentInstr* block_offsets_push =
      PushArgument(Bind(new(I) ConstantInstr(offsets)));
  PushArgumentInstr* block_id_push = PushArgument(Bind(PopStack()));

  Value* offset_value =
      Bind(InstanceCall(InstanceCallDescriptor::FromToken(Token::kINDEX),
                        block_offsets_push,
                        block_id_push));

  backtrack_goto_ = new(I) IndirectGotoInstr(&offsets, offset_value);
  CloseBlockWith(backtrack_goto_);

  // Add an edge from the "indirect" goto to each of the targets.
  for (intptr_t j = 0; j < entries_count; j++) {
    backtrack_goto_->AddSuccessor(
        TargetWithJoinGoto(entry_block_->indirect_entries().At(j)));
  }
}


void IRRegExpMacroAssembler::GenerateSuccessBlock() {
  set_current_instruction(success_block_);
  TAG();

  Value* type = Bind(new(I) ConstantInstr(
      TypeArguments::ZoneHandle(I, TypeArguments::null())));
  Value* length = Bind(Uint64Constant(saved_registers_count_));
  Value* array = Bind(new(I) CreateArrayInstr(kNoSourcePos, type, length));
  StoreLocal(result_, array);

  // Store captured offsets in the `matches` parameter.
  for (intptr_t i = 0; i < saved_registers_count_; i++) {
    PushArgumentInstr* matches_push = PushLocal(result_);
    PushArgumentInstr* index_push = PushArgument(Bind(Uint64Constant(i)));

    // Convert negative offsets from the end of the string to string indices.
    // TODO(zerny): use positive offsets from the get-go.
    PushArgumentInstr* offset_push = PushArgument(LoadRegister(i));
    PushArgumentInstr* len_push = PushLocal(string_param_length_);
    PushArgumentInstr* value_push =
        PushArgument(Bind(Add(offset_push, len_push)));

    Do(InstanceCall(InstanceCallDescriptor::FromToken(Token::kASSIGN_INDEX),
                    matches_push,
                    index_push,
                    value_push));
  }

  // Print the result if tracing.
  PRINT(PushLocal(result_));

  // Return true on success.
  AppendInstruction(new(I) ReturnInstr(kNoSourcePos, Bind(LoadLocal(result_))));
}


void IRRegExpMacroAssembler::GenerateExitBlock() {
  set_current_instruction(exit_block_);
  TAG();

  // Return false on failure.
  AppendInstruction(new(I) ReturnInstr(kNoSourcePos, Bind(LoadLocal(result_))));
}


void IRRegExpMacroAssembler::FinalizeRegistersArray() {
  ASSERT(registers_count_ >= saved_registers_count_);
  registers_array_ =
      TypedData::New(kTypedDataInt32ArrayCid, registers_count_, Heap::kOld);
}


#if defined(TARGET_ARCH_ARM64) ||                                              \
    defined(TARGET_ARCH_ARM) ||                                                \
    defined(TARGET_ARCH_MIPS)
// Disabling unaligned accesses forces the regexp engine to load characters one
// by one instead of up to 4 at once, along with the associated performance hit.
// TODO(zerny): Be less conservative about disabling unaligned accesses.
// For instance, ARMv6 supports unaligned accesses. Once it is enabled here,
// update LoadCodeUnitsInstr methods for the appropriate architectures.
static const bool kEnableUnalignedAccesses = false;
#else
static const bool kEnableUnalignedAccesses = true;
#endif
bool IRRegExpMacroAssembler::CanReadUnaligned() {
  return kEnableUnalignedAccesses && !slow_safe();
}


RawArray* IRRegExpMacroAssembler::Execute(
    const Function& function,
    const String& input,
    const Smi& start_offset,
    Isolate* isolate) {
  // Create the argument list.
  const Array& args = Array::Handle(Array::New(2));
  args.SetAt(0, input);
  args.SetAt(1, start_offset);

  // And finally call the generated code.

  const Object& retval =
      Object::Handle(isolate, DartEntry::InvokeFunction(function, args));
  if (retval.IsError()) {
    const Error& error = Error::Cast(retval);
    OS::Print("%s\n", error.ToErrorCString());
    // Should never happen.
    UNREACHABLE();
  }

  if (retval.IsNull()) {
    return Array::null();
  }

  ASSERT(retval.IsArray());
  return Array::Cast(retval).raw();
}


RawBool* IRRegExpMacroAssembler::CaseInsensitiveCompareUC16(
    RawString* str_raw,
    RawSmi* lhs_index_raw,
    RawSmi* rhs_index_raw,
    RawSmi* length_raw) {
  const String& str = String::Handle(str_raw);
  const Smi& lhs_index = Smi::Handle(lhs_index_raw);
  const Smi& rhs_index = Smi::Handle(rhs_index_raw);
  const Smi& length = Smi::Handle(length_raw);

  // TODO(zerny): Optimize as single instance. V8 has this as an
  // isolate member.
  unibrow::Mapping<unibrow::Ecma262Canonicalize> canonicalize;

  for (intptr_t i = 0; i < length.Value(); i++) {
    int32_t c1 = str.CharAt(lhs_index.Value() + i);
    int32_t c2 = str.CharAt(rhs_index.Value() + i);
    if (c1 != c2) {
      int32_t s1[1] = { c1 };
      canonicalize.get(c1, '\0', s1);
      if (s1[0] != c2) {
        int32_t s2[1] = { c2 };
        canonicalize.get(c2, '\0', s2);
        if (s1[0] != s2[0]) {
          return Bool::False().raw();
        }
      }
    }
  }
  return Bool::True().raw();
}


LocalVariable* IRRegExpMacroAssembler::Parameter(const String& name,
                                                 intptr_t index) const {
  const Type& local_type = Type::ZoneHandle(I, Type::DynamicType());
  LocalVariable* local =
      new(I) LocalVariable(kNoSourcePos, name, local_type);

  intptr_t param_frame_index = kParamEndSlotFromFp + kParamCount - index;
  local->set_index(param_frame_index);

  return local;
}


LocalVariable* IRRegExpMacroAssembler::Local(const String& name) {
  const Type& local_type = Type::ZoneHandle(I, Type::DynamicType());
  LocalVariable* local =
      new(I) LocalVariable(kNoSourcePos, name, local_type);
  local->set_index(GetNextLocalIndex());

  return local;
}


ConstantInstr* IRRegExpMacroAssembler::Int64Constant(int64_t value) const {
  return new(I) ConstantInstr(
        Integer::ZoneHandle(I, Integer::New(value, Heap::kOld)));
}


ConstantInstr* IRRegExpMacroAssembler::Uint64Constant(uint64_t value) const {
  return new(I) ConstantInstr(
        Integer::ZoneHandle(I, Integer::NewFromUint64(value, Heap::kOld)));
}


ConstantInstr* IRRegExpMacroAssembler::BoolConstant(bool value) const {
  return new(I) ConstantInstr(value ? Bool::True() : Bool::False());
}


ConstantInstr* IRRegExpMacroAssembler::StringConstant(const char* value) const {
  return new(I) ConstantInstr(
        String::ZoneHandle(I, String::New(value, Heap::kOld)));
}


ConstantInstr* IRRegExpMacroAssembler::WordCharacterMapConstant() const {
  const Library& lib = Library::Handle(I, Library::CoreLibrary());
  const Class& regexp_class = Class::Handle(I,
        lib.LookupClassAllowPrivate(Symbols::JSSyntaxRegExp()));
  const Field& word_character_field = Field::ZoneHandle(I,
      regexp_class.LookupStaticField(Symbols::_wordCharacterMap()));
  ASSERT(!word_character_field.IsNull());

  if (word_character_field.IsUninitialized()) {
    word_character_field.EvaluateInitializer();
  }
  ASSERT(!word_character_field.IsUninitialized());

  return new(I) ConstantInstr(
        Instance::ZoneHandle(I, word_character_field.value()));
}


ComparisonInstr* IRRegExpMacroAssembler::Comparison(
    ComparisonKind kind, PushArgumentInstr* lhs, PushArgumentInstr* rhs) {
  Token::Kind strict_comparison = Token::kEQ_STRICT;
  Token::Kind intermediate_operator = Token::kILLEGAL;
  switch (kind) {
  case kEQ:
    intermediate_operator = Token::kEQ;
    break;
  case kNE:
    intermediate_operator = Token::kEQ;
    strict_comparison = Token::kNE_STRICT;
    break;
  case kLT:
    intermediate_operator = Token::kLT;
    break;
  case kGT:
    intermediate_operator = Token::kGT;
    break;
  case kLTE:
    intermediate_operator = Token::kLTE;
    break;
  case kGTE:
    intermediate_operator = Token::kGTE;
    break;
  default:
    UNREACHABLE();
  }

  ASSERT(intermediate_operator != Token::kILLEGAL);

  Value* lhs_value =
      Bind(InstanceCall(
             InstanceCallDescriptor::FromToken(intermediate_operator),
             lhs,
             rhs));
  Value* rhs_value = Bind(BoolConstant(true));

  return new(I) StrictCompareInstr(
      kNoSourcePos, strict_comparison, lhs_value, rhs_value, true);
}

ComparisonInstr* IRRegExpMacroAssembler::Comparison(
    ComparisonKind kind, Definition* lhs, Definition* rhs) {
  PushArgumentInstr* lhs_push = PushArgument(Bind(lhs));
  PushArgumentInstr* rhs_push = PushArgument(Bind(rhs));
  return Comparison(kind, lhs_push, rhs_push);
}


StaticCallInstr* IRRegExpMacroAssembler::StaticCall(
    const Function& function) const {
  ZoneGrowableArray<PushArgumentInstr*>* arguments =
      new(I) ZoneGrowableArray<PushArgumentInstr*>(0);
  return StaticCall(function, arguments);
}


StaticCallInstr* IRRegExpMacroAssembler::StaticCall(
    const Function& function,
    PushArgumentInstr* arg1) const {
  ZoneGrowableArray<PushArgumentInstr*>* arguments =
      new(I) ZoneGrowableArray<PushArgumentInstr*>(1);
  arguments->Add(arg1);

  return StaticCall(function, arguments);
}


StaticCallInstr* IRRegExpMacroAssembler::StaticCall(
    const Function& function,
    PushArgumentInstr* arg1,
    PushArgumentInstr* arg2) const {
  ZoneGrowableArray<PushArgumentInstr*>* arguments =
      new(I) ZoneGrowableArray<PushArgumentInstr*>(2);
  arguments->Add(arg1);
  arguments->Add(arg2);

  return StaticCall(function, arguments);
}


StaticCallInstr* IRRegExpMacroAssembler::StaticCall(
    const Function& function,
    ZoneGrowableArray<PushArgumentInstr*>* arguments) const {
  return new(I) StaticCallInstr(kNoSourcePos,
                                function,
                                Object::null_array(),
                                arguments,
                                ic_data_array_);
}


InstanceCallInstr* IRRegExpMacroAssembler::InstanceCall(
    const InstanceCallDescriptor& desc,
    PushArgumentInstr* arg1) const {
  ZoneGrowableArray<PushArgumentInstr*>* arguments =
      new(I) ZoneGrowableArray<PushArgumentInstr*>(1);
  arguments->Add(arg1);

  return InstanceCall(desc, arguments);
}


InstanceCallInstr* IRRegExpMacroAssembler::InstanceCall(
    const InstanceCallDescriptor& desc,
    PushArgumentInstr* arg1,
    PushArgumentInstr* arg2) const {
  ZoneGrowableArray<PushArgumentInstr*>* arguments =
      new(I) ZoneGrowableArray<PushArgumentInstr*>(2);
  arguments->Add(arg1);
  arguments->Add(arg2);

  return InstanceCall(desc, arguments);
}


InstanceCallInstr* IRRegExpMacroAssembler::InstanceCall(
    const InstanceCallDescriptor& desc,
    PushArgumentInstr* arg1,
    PushArgumentInstr* arg2,
    PushArgumentInstr* arg3) const {
  ZoneGrowableArray<PushArgumentInstr*>* arguments =
      new(I) ZoneGrowableArray<PushArgumentInstr*>(3);
  arguments->Add(arg1);
  arguments->Add(arg2);
  arguments->Add(arg3);

  return InstanceCall(desc, arguments);
}


InstanceCallInstr* IRRegExpMacroAssembler::InstanceCall(
    const InstanceCallDescriptor& desc,
    ZoneGrowableArray<PushArgumentInstr*> *arguments) const {
  return
    new(I) InstanceCallInstr(kNoSourcePos,
                             desc.name,
                             desc.token_kind,
                             arguments,
                             Object::null_array(),
                             desc.checked_argument_count,
                             ic_data_array_);
}


LoadLocalInstr* IRRegExpMacroAssembler::LoadLocal(LocalVariable* local) const {
  return new(I) LoadLocalInstr(*local);
}


void IRRegExpMacroAssembler::StoreLocal(LocalVariable* local,
                                        Value* value) {
  Do(new(I) StoreLocalInstr(*local, value));
}


void IRRegExpMacroAssembler::set_current_instruction(Instruction* instruction) {
  current_instruction_ = instruction;
}


Value* IRRegExpMacroAssembler::Bind(Definition* definition) {
  AppendInstruction(definition);
  definition->set_temp_index(temp_id_.Alloc());

  return new(I) Value(definition);
}


void IRRegExpMacroAssembler::Do(Definition* definition) {
  AppendInstruction(definition);
}


Value* IRRegExpMacroAssembler::BindLoadLocal(const LocalVariable& local) {
  if (local.IsConst()) {
    return Bind(new(I) ConstantInstr(*local.ConstValue()));
  }
  ASSERT(!local.is_captured());
  return Bind(new(I) LoadLocalInstr(local));
}


// In some cases, the V8 irregexp engine generates unreachable code by emitting
// a jmp not followed by a bind. We cannot do the same, since it is impossible
// to append to a block following a jmp. In such cases, assume that we are doing
// the correct thing, but output a warning when tracing.
#define HANDLE_DEAD_CODE_EMISSION() \
  if (current_instruction_ == NULL) { \
    if (FLAG_trace_irregexp) { \
      OS::Print("WARNING: Attempting to append to a closed assembler. " \
                "This could be either a bug or generation of dead code " \
                "inherited from V8.\n"); \
    } \
    BlockLabel dummy; \
    BindBlock(&dummy); \
  }

void IRRegExpMacroAssembler::AppendInstruction(Instruction* instruction) {
  HANDLE_DEAD_CODE_EMISSION();

  ASSERT(current_instruction_ != NULL);
  ASSERT(current_instruction_->next() == NULL);

  temp_id_.Dealloc(instruction->InputCount());
  arg_id_.Dealloc(instruction->ArgumentCount());

  current_instruction_->LinkTo(instruction);
  set_current_instruction(instruction);
}


void IRRegExpMacroAssembler::CloseBlockWith(Instruction* instruction) {
  HANDLE_DEAD_CODE_EMISSION();

  ASSERT(current_instruction_ != NULL);
  ASSERT(current_instruction_->next() == NULL);

  temp_id_.Dealloc(instruction->InputCount());
  arg_id_.Dealloc(instruction->ArgumentCount());

  current_instruction_->LinkTo(instruction);
  set_current_instruction(NULL);
}


void IRRegExpMacroAssembler::GoTo(BlockLabel* to) {
  if (to == NULL) {
    Backtrack();
  } else {
    to->SetLinked();
    GoTo(to->block());
  }
}


// Closes the current block with a goto, and unsets current_instruction_.
// BindBlock() must be called before emission can continue.
void IRRegExpMacroAssembler::GoTo(JoinEntryInstr* to) {
  HANDLE_DEAD_CODE_EMISSION();

  ASSERT(current_instruction_ != NULL);
  ASSERT(current_instruction_->next() == NULL);
  current_instruction_->Goto(to);
  set_current_instruction(NULL);
}


PushArgumentInstr* IRRegExpMacroAssembler::PushArgument(Value* value) {
  arg_id_.Alloc();
  PushArgumentInstr* push = new(I) PushArgumentInstr(value);
  // Do *not* use Do() for push argument instructions.
  AppendInstruction(push);
  return push;
}


PushArgumentInstr* IRRegExpMacroAssembler::PushLocal(LocalVariable* local) {
  return PushArgument(Bind(LoadLocal(local)));
}


void IRRegExpMacroAssembler::Print(const char* str) {
  Print(PushArgument(
    Bind(new(I) ConstantInstr(
           String::ZoneHandle(I, String::New(str, Heap::kOld))))));
}


void IRRegExpMacroAssembler::Print(PushArgumentInstr* argument) {
  const Library& lib = Library::Handle(Library::CoreLibrary());
  const Function& print_fn = Function::ZoneHandle(
        I, lib.LookupFunctionAllowPrivate(Symbols::print()));
  Do(StaticCall(print_fn, argument));
}


void IRRegExpMacroAssembler::PrintBlocks() {
  for (intptr_t i = 0; i < blocks_.length(); i++) {
    FlowGraphPrinter::PrintBlock(blocks_[i], false);
  }
}


intptr_t IRRegExpMacroAssembler::stack_limit_slack()  {
  return 32;
}


void IRRegExpMacroAssembler::AdvanceCurrentPosition(intptr_t by) {
  TAG();
  if (by != 0) {
    PushArgumentInstr* cur_pos_push = PushLocal(current_position_);
    PushArgumentInstr* by_push = PushArgument(Bind(Int64Constant(by)));

    Value* new_pos_value = Bind(Add(cur_pos_push, by_push));
    StoreLocal(current_position_, new_pos_value);
  }
}


void IRRegExpMacroAssembler::AdvanceRegister(intptr_t reg, intptr_t by) {
  TAG();
  ASSERT(reg >= 0);
  ASSERT(reg < registers_count_);

  if (by != 0) {
    PushArgumentInstr* registers_push = PushLocal(registers_);
    PushArgumentInstr* index_push = PushRegisterIndex(reg);
    PushArgumentInstr* reg_push = PushArgument(LoadRegister(reg));
    PushArgumentInstr* by_push = PushArgument(Bind(Int64Constant(by)));
    PushArgumentInstr* value_push = PushArgument(Bind(Add(reg_push, by_push)));
    StoreRegister(registers_push, index_push, value_push);
  }
}


void IRRegExpMacroAssembler::Backtrack() {
  TAG();
  GoTo(backtrack_block_);
}


// A BindBlock is analogous to assigning a label to a basic block.
// If the BlockLabel does not yet contain a block, it is created.
// If there is a current instruction, append a goto to the bound block.
void IRRegExpMacroAssembler::BindBlock(BlockLabel* label) {
  ASSERT(!label->IsBound());
  ASSERT(label->block()->next() == NULL);

  label->SetBound(block_id_.Alloc());
  blocks_.Add(label->block());

  if (current_instruction_ != NULL) {
    GoTo(label);
  }
  set_current_instruction(label->block());

  // Print the id of the current block if tracing.
  PRINT(PushArgument(Bind(Uint64Constant(label->block()->block_id()))));
}


intptr_t IRRegExpMacroAssembler::GetNextLocalIndex() {
  intptr_t id = local_id_.Alloc();
  return kFirstLocalSlotFromFp - id;
}


Value* IRRegExpMacroAssembler::LoadRegister(intptr_t index) {
  PushArgumentInstr* registers_push = PushLocal(registers_);
  PushArgumentInstr* index_push = PushRegisterIndex(index);
  return Bind(InstanceCall(InstanceCallDescriptor::FromToken(Token::kINDEX),
                           registers_push,
                           index_push));
}

void IRRegExpMacroAssembler::StoreRegister(intptr_t index, intptr_t value) {
  PushArgumentInstr* registers_push = PushLocal(registers_);
  PushArgumentInstr* index_push = PushRegisterIndex(index);
  PushArgumentInstr* value_push = PushArgument(Bind(Uint64Constant(value)));
  StoreRegister(registers_push, index_push, value_push);
}


void IRRegExpMacroAssembler::StoreRegister(PushArgumentInstr* registers,
                                           PushArgumentInstr* index,
                                           PushArgumentInstr* value) {
  TAG();
  Do(InstanceCall(InstanceCallDescriptor::FromToken(Token::kASSIGN_INDEX),
                  registers,
                  index,
                  value));
}

PushArgumentInstr* IRRegExpMacroAssembler::PushRegisterIndex(intptr_t index) {
  if (registers_count_ <= index) {
    registers_count_ = index + 1;
  }
  return PushArgument(Bind(Uint64Constant(index)));
}


void IRRegExpMacroAssembler::CheckCharacter(uint32_t c, BlockLabel* on_equal) {
  TAG();
  Definition* cur_char_def = LoadLocal(current_character_);
  Definition* char_def = Uint64Constant(c);

  BranchOrBacktrack(Comparison(kEQ, cur_char_def, char_def), on_equal);
}


void IRRegExpMacroAssembler::CheckCharacterGT(uint16_t limit,
                                              BlockLabel* on_greater) {
  TAG();
  BranchOrBacktrack(Comparison(kGT,
                               LoadLocal(current_character_),
                               Uint64Constant(limit)),
                    on_greater);
}


void IRRegExpMacroAssembler::CheckAtStart(BlockLabel* on_at_start) {
  TAG();

  BlockLabel not_at_start;

  // Did we start the match at the start of the string at all?
  BranchOrBacktrack(Comparison(kNE,
                               LoadLocal(start_index_param_),
                               Uint64Constant(0)),
                    &not_at_start);

  // If we did, are we still at the start of the input, i.e. is
  // (offset == string_length * -1)?
  Definition* neg_len_def =
      InstanceCall(InstanceCallDescriptor::FromToken(Token::kNEGATE),
                   PushLocal(string_param_length_));
  Definition* offset_def = LoadLocal(current_position_);
  BranchOrBacktrack(Comparison(kEQ, neg_len_def, offset_def),
                    on_at_start);

  BindBlock(&not_at_start);
}


void IRRegExpMacroAssembler::CheckNotAtStart(BlockLabel* on_not_at_start) {
  TAG();

  // Did we start the match at the start of the string at all?
  BranchOrBacktrack(Comparison(kNE,
                               LoadLocal(start_index_param_),
                               Uint64Constant(0)),
                    on_not_at_start);

  // If we did, are we still at the start of the input, i.e. is
  // (offset == string_length * -1)?
  Definition* neg_len_def =
      InstanceCall(InstanceCallDescriptor::FromToken(Token::kNEGATE),
                   PushLocal(string_param_length_));
  Definition* offset_def = LoadLocal(current_position_);
  BranchOrBacktrack(Comparison(kNE, neg_len_def, offset_def),
                    on_not_at_start);
}


void IRRegExpMacroAssembler::CheckCharacterLT(uint16_t limit,
                                              BlockLabel* on_less) {
  TAG();
  BranchOrBacktrack(Comparison(kLT,
                               LoadLocal(current_character_),
                               Uint64Constant(limit)),
                    on_less);
}


void IRRegExpMacroAssembler::CheckGreedyLoop(BlockLabel* on_equal) {
  TAG();

  BlockLabel fallthrough;

  Definition* head = PeekStack();
  Definition* cur_pos_def = LoadLocal(current_position_);
  BranchOrBacktrack(Comparison(kNE, head, cur_pos_def),
                    &fallthrough);

  // Pop, throwing away the value.
  Do(PopStack());

  BranchOrBacktrack(NULL, on_equal);

  BindBlock(&fallthrough);
}


void IRRegExpMacroAssembler::CheckNotBackReferenceIgnoreCase(
    intptr_t start_reg,
    BlockLabel* on_no_match) {
  TAG();
  ASSERT(start_reg + 1 <= registers_count_);

  BlockLabel fallthrough;

  PushArgumentInstr* end_push = PushArgument(LoadRegister(start_reg + 1));
  PushArgumentInstr* start_push = PushArgument(LoadRegister(start_reg));
  StoreLocal(capture_length_, Bind(Sub(end_push, start_push)));

  // The length of a capture should not be negative. This can only happen
  // if the end of the capture is unrecorded, or at a point earlier than
  // the start of the capture.
  // BranchOrBacktrack(less, on_no_match);

  BranchOrBacktrack(Comparison(kLT,
                               LoadLocal(capture_length_),
                               Uint64Constant(0)),
                    on_no_match);

  // If length is zero, either the capture is empty or it is completely
  // uncaptured. In either case succeed immediately.
  BranchOrBacktrack(Comparison(kEQ,
                               LoadLocal(capture_length_),
                               Uint64Constant(0)),
                    &fallthrough);


  // Check that there are sufficient characters left in the input.
  PushArgumentInstr* pos_push = PushLocal(current_position_);
  PushArgumentInstr* len_push = PushLocal(capture_length_);
  BranchOrBacktrack(
        Comparison(kGT,
                   InstanceCall(InstanceCallDescriptor::FromToken(Token::kADD),
                                pos_push,
                                len_push),
                   Uint64Constant(0)),
        on_no_match);

  pos_push = PushLocal(current_position_);
  len_push = PushLocal(string_param_length_);
  StoreLocal(match_start_index_, Bind(Add(pos_push, len_push)));

  pos_push = PushArgument(LoadRegister(start_reg));
  len_push = PushLocal(string_param_length_);
  StoreLocal(capture_start_index_, Bind(Add(pos_push, len_push)));

  pos_push = PushLocal(match_start_index_);
  len_push = PushLocal(capture_length_);
  StoreLocal(match_end_index_, Bind(Add(pos_push, len_push)));

  BlockLabel success;
  if (mode_ == ASCII) {
    BlockLabel loop_increment;
    BlockLabel loop;
    BindBlock(&loop);

    StoreLocal(char_in_capture_, CharacterAt(capture_start_index_));
    StoreLocal(char_in_match_, CharacterAt(match_start_index_));

    BranchOrBacktrack(Comparison(kEQ,
                                 LoadLocal(char_in_capture_),
                                 LoadLocal(char_in_match_)),
                      &loop_increment);

    // Mismatch, try case-insensitive match (converting letters to lower-case).
    PushArgumentInstr* match_char_push = PushLocal(char_in_match_);
    PushArgumentInstr* mask_push = PushArgument(Bind(Uint64Constant(0x20)));
    StoreLocal(char_in_match_,
               Bind(InstanceCall(
                      InstanceCallDescriptor::FromToken(Token::kBIT_OR),
                      match_char_push,
                      mask_push)));

    BlockLabel convert_capture;
    BlockLabel on_not_in_range;
    BranchOrBacktrack(Comparison(kLT,
                                 LoadLocal(char_in_match_),
                                 Uint64Constant('a')),
                      &on_not_in_range);
    BranchOrBacktrack(Comparison(kGT,
                                 LoadLocal(char_in_match_),
                                 Uint64Constant('z')),
                      &on_not_in_range);
    GoTo(&convert_capture);
    BindBlock(&on_not_in_range);

    // Latin-1: Check for values in range [224,254] but not 247.
    BranchOrBacktrack(Comparison(kLT,
                                 LoadLocal(char_in_match_),
                                 Uint64Constant(224)),
                      on_no_match);
    BranchOrBacktrack(Comparison(kGT,
                                 LoadLocal(char_in_match_),
                                 Uint64Constant(254)),
                      on_no_match);

    BranchOrBacktrack(Comparison(kEQ,
                                 LoadLocal(char_in_match_),
                                 Uint64Constant(247)),
                      on_no_match);

    // Also convert capture character.
    BindBlock(&convert_capture);

    PushArgumentInstr* capture_char_push = PushLocal(char_in_capture_);
    mask_push = PushArgument(Bind(Uint64Constant(0x20)));
    StoreLocal(char_in_capture_,
               Bind(InstanceCall(
                      InstanceCallDescriptor::FromToken(Token::kBIT_OR),
                      capture_char_push,
                      mask_push)));

    BranchOrBacktrack(Comparison(kNE,
                                 LoadLocal(char_in_match_),
                                 LoadLocal(char_in_capture_)),
                      on_no_match);

    BindBlock(&loop_increment);

    // Increment indexes into capture and match strings.
    PushArgumentInstr* index_push = PushLocal(capture_start_index_);
    PushArgumentInstr* inc_push = PushArgument(Bind(Uint64Constant(1)));
    StoreLocal(capture_start_index_, Bind(Add(index_push, inc_push)));

    index_push = PushLocal(match_start_index_);
    inc_push = PushArgument(Bind(Uint64Constant(1)));
    StoreLocal(match_start_index_, Bind(Add(index_push, inc_push)));

    // Compare to end of match, and loop if not done.
    BranchOrBacktrack(Comparison(kLT,
                                 LoadLocal(match_start_index_),
                                 LoadLocal(match_end_index_)),
                      &loop);
  } else {
    ASSERT(mode_ == UC16);

    Value* string_value = Bind(LoadLocal(string_param_));
    Value* lhs_index_value = Bind(LoadLocal(match_start_index_));
    Value* rhs_index_value = Bind(LoadLocal(capture_start_index_));
    Value* length_value = Bind(LoadLocal(capture_length_));

    Definition* is_match_def =
        new(I) CaseInsensitiveCompareUC16Instr(
                            string_value,
                            lhs_index_value,
                            rhs_index_value,
                            length_value,
                            specialization_cid_);

    BranchOrBacktrack(Comparison(kNE, is_match_def, BoolConstant(true)),
                      on_no_match);
  }

  BindBlock(&success);

  // Move current character position to position after match.
  PushArgumentInstr* match_end_push = PushLocal(match_end_index_);
  len_push = PushLocal(string_param_length_);
  StoreLocal(current_position_, Bind(Sub(match_end_push, len_push)));

  BindBlock(&fallthrough);
}


void IRRegExpMacroAssembler::CheckNotBackReference(
    intptr_t start_reg,
    BlockLabel* on_no_match) {
  TAG();
  ASSERT(start_reg + 1 <= registers_count_);

  BlockLabel fallthrough;
  BlockLabel success;

  // Find length of back-referenced capture.
  PushArgumentInstr* end_push = PushArgument(LoadRegister(start_reg + 1));
  PushArgumentInstr* start_push = PushArgument(LoadRegister(start_reg));
  StoreLocal(capture_length_, Bind(Sub(end_push, start_push)));

  // Fail on partial or illegal capture (start of capture after end of capture).
  BranchOrBacktrack(Comparison(kLT,
                               LoadLocal(capture_length_),
                               Uint64Constant(0)),
                    on_no_match);

  // Succeed on empty capture (including no capture)
  BranchOrBacktrack(Comparison(kEQ,
                               LoadLocal(capture_length_),
                               Uint64Constant(0)),
                    &fallthrough);

  // Check that there are sufficient characters left in the input.
  PushArgumentInstr* pos_push = PushLocal(current_position_);
  PushArgumentInstr* len_push = PushLocal(capture_length_);
  BranchOrBacktrack(
        Comparison(kGT,
                   InstanceCall(InstanceCallDescriptor::FromToken(Token::kADD),
                                pos_push,
                                len_push),
                   Uint64Constant(0)),
        on_no_match);

  // Compute pointers to match string and capture string.
  pos_push = PushLocal(current_position_);
  len_push = PushLocal(string_param_length_);
  StoreLocal(match_start_index_, Bind(Add(pos_push, len_push)));

  pos_push = PushArgument(LoadRegister(start_reg));
  len_push = PushLocal(string_param_length_);
  StoreLocal(capture_start_index_, Bind(Add(pos_push, len_push)));

  pos_push = PushLocal(match_start_index_);
  len_push = PushLocal(capture_length_);
  StoreLocal(match_end_index_, Bind(Add(pos_push, len_push)));

  BlockLabel loop;
  BindBlock(&loop);

  StoreLocal(char_in_capture_, CharacterAt(capture_start_index_));
  StoreLocal(char_in_match_, CharacterAt(match_start_index_));

  BranchOrBacktrack(Comparison(kNE,
                               LoadLocal(char_in_capture_),
                               LoadLocal(char_in_match_)),
                    on_no_match);

  // Increment indexes into capture and match strings.
  PushArgumentInstr* index_push = PushLocal(capture_start_index_);
  PushArgumentInstr* inc_push = PushArgument(Bind(Uint64Constant(1)));
  StoreLocal(capture_start_index_, Bind(Add(index_push, inc_push)));

  index_push = PushLocal(match_start_index_);
  inc_push = PushArgument(Bind(Uint64Constant(1)));
  StoreLocal(match_start_index_, Bind(Add(index_push, inc_push)));

  // Check if we have reached end of match area.
  BranchOrBacktrack(Comparison(kLT,
                               LoadLocal(match_start_index_),
                               LoadLocal(match_end_index_)),
                    &loop);

  BindBlock(&success);

  // Move current character position to position after match.
  PushArgumentInstr* match_end_push = PushLocal(match_end_index_);
  len_push = PushLocal(string_param_length_);
  StoreLocal(current_position_, Bind(Sub(match_end_push, len_push)));

  BindBlock(&fallthrough);
}


void IRRegExpMacroAssembler::CheckNotCharacter(uint32_t c,
                                               BlockLabel* on_not_equal) {
  TAG();
  BranchOrBacktrack(Comparison(kNE,
                               LoadLocal(current_character_),
                               Uint64Constant(c)),
                    on_not_equal);
}


void IRRegExpMacroAssembler::CheckCharacterAfterAnd(uint32_t c,
                                                    uint32_t mask,
                                                    BlockLabel* on_equal) {
  TAG();

  Definition* actual_def = LoadLocal(current_character_);
  Definition* expected_def = Uint64Constant(c);

  PushArgumentInstr* actual_push = PushArgument(Bind(actual_def));
  PushArgumentInstr* mask_push = PushArgument(Bind(Uint64Constant(mask)));
  actual_def = InstanceCall(InstanceCallDescriptor::FromToken(Token::kBIT_AND),
                            actual_push,
                            mask_push);

  BranchOrBacktrack(Comparison(kEQ, actual_def, expected_def), on_equal);
}


void IRRegExpMacroAssembler::CheckNotCharacterAfterAnd(
    uint32_t c,
    uint32_t mask,
    BlockLabel* on_not_equal) {
  TAG();

  Definition* actual_def = LoadLocal(current_character_);
  Definition* expected_def = Uint64Constant(c);

  PushArgumentInstr* actual_push = PushArgument(Bind(actual_def));
  PushArgumentInstr* mask_push = PushArgument(Bind(Uint64Constant(mask)));
  actual_def = InstanceCall(InstanceCallDescriptor::FromToken(Token::kBIT_AND),
                            actual_push,
                            mask_push);

  BranchOrBacktrack(Comparison(kNE, actual_def, expected_def), on_not_equal);
}


void IRRegExpMacroAssembler::CheckNotCharacterAfterMinusAnd(
    uint16_t c,
    uint16_t minus,
    uint16_t mask,
    BlockLabel* on_not_equal) {
  TAG();
  ASSERT(minus < Utf16::kMaxCodeUnit);  // NOLINT

  Definition* actual_def = LoadLocal(current_character_);
  Definition* expected_def = Uint64Constant(c);

  PushArgumentInstr* actual_push = PushArgument(Bind(actual_def));
  PushArgumentInstr* minus_push = PushArgument(Bind(Uint64Constant(minus)));

  actual_push = PushArgument(Bind(Sub(actual_push, minus_push)));
  PushArgumentInstr* mask_push = PushArgument(Bind(Uint64Constant(mask)));
  actual_def = InstanceCall(InstanceCallDescriptor::FromToken(Token::kBIT_AND),
                            actual_push,
                            mask_push);

  BranchOrBacktrack(Comparison(kNE, actual_def, expected_def), on_not_equal);
}


void IRRegExpMacroAssembler::CheckCharacterInRange(
    uint16_t from,
    uint16_t to,
    BlockLabel* on_in_range) {
  TAG();
  ASSERT(from <= to);

  // TODO(zerny): All range comparisons could be done cheaper with unsigned
  // compares. This pattern repeats in various places.

  BlockLabel on_not_in_range;
  BranchOrBacktrack(Comparison(kLT,
                               LoadLocal(current_character_),
                               Uint64Constant(from)),
                    &on_not_in_range);
  BranchOrBacktrack(Comparison(kGT,
                               LoadLocal(current_character_),
                               Uint64Constant(to)),
                    &on_not_in_range);
  BranchOrBacktrack(NULL, on_in_range);

  BindBlock(&on_not_in_range);
}


void IRRegExpMacroAssembler::CheckCharacterNotInRange(
    uint16_t from,
    uint16_t to,
    BlockLabel* on_not_in_range) {
  TAG();
  ASSERT(from <= to);

  BranchOrBacktrack(Comparison(kLT,
                               LoadLocal(current_character_),
                               Uint64Constant(from)),
                    on_not_in_range);

  BranchOrBacktrack(Comparison(kGT,
                               LoadLocal(current_character_),
                               Uint64Constant(to)),
                    on_not_in_range);
}


void IRRegExpMacroAssembler::CheckBitInTable(
    const TypedData& table,
    BlockLabel* on_bit_set) {
  TAG();

  PushArgumentInstr* table_push =
      PushArgument(Bind(new(I) ConstantInstr(table)));
  PushArgumentInstr* index_push = PushLocal(current_character_);

  if (mode_ != ASCII || kTableMask != Symbols::kMaxOneCharCodeSymbol) {
    PushArgumentInstr* mask_push =
        PushArgument(Bind(Uint64Constant(kTableSize - 1)));
    index_push = PushArgument(
          Bind(InstanceCall(InstanceCallDescriptor::FromToken(Token::kBIT_AND),
                            index_push,
                            mask_push)));
  }

  Definition* byte_def =
      InstanceCall(InstanceCallDescriptor::FromToken(Token::kINDEX),
                   table_push,
                   index_push);
  Definition* zero_def = Int64Constant(0);

  BranchOrBacktrack(Comparison(kNE, byte_def, zero_def), on_bit_set);
}


bool IRRegExpMacroAssembler::CheckSpecialCharacterClass(
    uint16_t type,
    BlockLabel* on_no_match) {
  TAG();

  // Range checks (c in min..max) are generally implemented by an unsigned
  // (c - min) <= (max - min) check
  switch (type) {
  case 's':
    // Match space-characters
    if (mode_ == ASCII) {
      // One byte space characters are '\t'..'\r', ' ' and \u00a0.
      BlockLabel success;
      // Space (' ').
      BranchOrBacktrack(Comparison(kEQ,
                                   LoadLocal(current_character_),
                                   Uint64Constant(' ')),
                        &success);
      // Check range 0x09..0x0d.
      CheckCharacterInRange('\t', '\r', &success);
      // \u00a0 (NBSP).
      BranchOrBacktrack(Comparison(kNE,
                                   LoadLocal(current_character_),
                                   Uint64Constant(0x00a0)),
                        on_no_match);
      BindBlock(&success);
      return true;
    }
    return false;
  case 'S':
    // The emitted code for generic character classes is good enough.
    return false;
  case 'd':
    // Match ASCII digits ('0'..'9')
    CheckCharacterNotInRange('0', '9', on_no_match);
    return true;
  case 'D':
    // Match non ASCII-digits
    CheckCharacterInRange('0', '9', on_no_match);
    return true;
  case '.': {
    // Match non-newlines (not 0x0a('\n'), 0x0d('\r'), 0x2028 and 0x2029)
    BranchOrBacktrack(Comparison(kEQ,
                                 LoadLocal(current_character_),
                                 Uint64Constant('\n')),
                      on_no_match);
    BranchOrBacktrack(Comparison(kEQ,
                                 LoadLocal(current_character_),
                                 Uint64Constant('\r')),
                      on_no_match);
    if (mode_ == UC16) {
      BranchOrBacktrack(Comparison(kEQ,
                                   LoadLocal(current_character_),
                                   Uint64Constant(0x2028)),
                        on_no_match);
      BranchOrBacktrack(Comparison(kEQ,
                                   LoadLocal(current_character_),
                                   Uint64Constant(0x2029)),
                        on_no_match);
    }
    return true;
  }
  case 'w': {
    if (mode_ != ASCII) {
      // Table is 128 entries, so all ASCII characters can be tested.
      BranchOrBacktrack(Comparison(kGT,
                                   LoadLocal(current_character_),
                                   Uint64Constant('z')),
                        on_no_match);
    }

    PushArgumentInstr* table_push =
        PushArgument(Bind(WordCharacterMapConstant()));
    PushArgumentInstr* index_push = PushLocal(current_character_);

    Definition* byte_def =
        InstanceCall(InstanceCallDescriptor::FromToken(Token::kINDEX),
                     table_push,
                     index_push);
    Definition* zero_def = Int64Constant(0);

    BranchOrBacktrack(Comparison(kEQ, byte_def, zero_def), on_no_match);

    return true;
  }
  case 'W': {
    BlockLabel done;
    if (mode_ != ASCII) {
      // Table is 128 entries, so all ASCII characters can be tested.
      BranchOrBacktrack(Comparison(kGT,
                                   LoadLocal(current_character_),
                                   Uint64Constant('z')),
                        &done);
    }

    // TODO(zerny): Refactor to use CheckBitInTable if possible.

    PushArgumentInstr* table_push =
        PushArgument(Bind(WordCharacterMapConstant()));
    PushArgumentInstr* index_push = PushLocal(current_character_);

    Definition* byte_def =
        InstanceCall(InstanceCallDescriptor::FromToken(Token::kINDEX),
                     table_push,
                     index_push);
    Definition* zero_def = Int64Constant(0);

    BranchOrBacktrack(Comparison(kNE, byte_def, zero_def), on_no_match);

    if (mode_ != ASCII) {
      BindBlock(&done);
    }
    return true;
  }
  // Non-standard classes (with no syntactic shorthand) used internally.
  case '*':
    // Match any character.
    return true;
  case 'n': {
    // Match newlines (0x0a('\n'), 0x0d('\r'), 0x2028 or 0x2029).
    // The opposite of '.'.
    BlockLabel success;
    BranchOrBacktrack(Comparison(kEQ,
                                 LoadLocal(current_character_),
                                 Uint64Constant('\n')),
                      &success);
    BranchOrBacktrack(Comparison(kEQ,
                                 LoadLocal(current_character_),
                                 Uint64Constant('\r')),
                      &success);
    if (mode_ == UC16) {
      BranchOrBacktrack(Comparison(kEQ,
                                   LoadLocal(current_character_),
                                   Uint64Constant(0x2028)),
                        &success);
      BranchOrBacktrack(Comparison(kEQ,
                                   LoadLocal(current_character_),
                                   Uint64Constant(0x2029)),
                        &success);
    }
    BranchOrBacktrack(NULL, on_no_match);
    BindBlock(&success);
    return true;
  }
  // No custom implementation (yet): s(uint16_t), S(uint16_t).
  default:
    return false;
  }
}


void IRRegExpMacroAssembler::Fail() {
  TAG();
  ASSERT(FAILURE == 0);  // Return value for failure is zero.
  if (!global()) {
    UNREACHABLE();  // Dart regexps are always global.
  }
  GoTo(exit_block_);
}


void IRRegExpMacroAssembler::IfRegisterGE(intptr_t reg,
                                          intptr_t comparand,
                                          BlockLabel* if_ge) {
  TAG();
  PushArgumentInstr* reg_push = PushArgument(LoadRegister(reg));
  PushArgumentInstr* pos = PushArgument(Bind(Int64Constant(comparand)));
  BranchOrBacktrack(Comparison(kGTE, reg_push, pos), if_ge);
}


void IRRegExpMacroAssembler::IfRegisterLT(intptr_t reg,
                                          intptr_t comparand,
                                          BlockLabel* if_lt) {
  TAG();
  PushArgumentInstr* reg_push = PushArgument(LoadRegister(reg));
  PushArgumentInstr* pos = PushArgument(Bind(Int64Constant(comparand)));
  BranchOrBacktrack(Comparison(kLT, reg_push, pos), if_lt);
}


void IRRegExpMacroAssembler::IfRegisterEqPos(intptr_t reg,
                                             BlockLabel* if_eq) {
  TAG();
  PushArgumentInstr* reg_push = PushArgument(LoadRegister(reg));
  PushArgumentInstr* pos = PushArgument(Bind(LoadLocal(current_position_)));
  BranchOrBacktrack(Comparison(kEQ, reg_push, pos), if_eq);
}


RegExpMacroAssembler::IrregexpImplementation
    IRRegExpMacroAssembler::Implementation() {
  return kIRImplementation;
}


void IRRegExpMacroAssembler::LoadCurrentCharacter(intptr_t cp_offset,
                                                  BlockLabel* on_end_of_input,
                                                  bool check_bounds,
                                                  intptr_t characters) {
  TAG();
  ASSERT(cp_offset >= -1);      // ^ and \b can look behind one character.
  ASSERT(cp_offset < (1<<30));  // Be sane! (And ensure negation works)
  if (check_bounds) {
    CheckPosition(cp_offset + characters - 1, on_end_of_input);
  }
  LoadCurrentCharacterUnchecked(cp_offset, characters);
}


void IRRegExpMacroAssembler::PopCurrentPosition() {
  TAG();
  StoreLocal(current_position_, Bind(PopStack()));
}


void IRRegExpMacroAssembler::PopRegister(intptr_t reg) {
  TAG();
  ASSERT(reg < registers_count_);
  PushArgumentInstr* registers_push = PushLocal(registers_);
  PushArgumentInstr* index_push = PushRegisterIndex(reg);
  PushArgumentInstr* pop_push = PushArgument(Bind(PopStack()));
  StoreRegister(registers_push, index_push, pop_push);
}


void IRRegExpMacroAssembler::PushStack(Definition *definition) {
  PushArgumentInstr* stack_push = PushLocal(stack_);
  PushArgumentInstr* stack_pointer_push = PushLocal(stack_pointer_);
  StoreLocal(stack_pointer_,
             Bind(Add(stack_pointer_push,
                      PushArgument(Bind(Uint64Constant(1))))));
  stack_pointer_push = PushLocal(stack_pointer_);
  // TODO(zerny): bind value and push could break stack discipline.
  PushArgumentInstr* value_push = PushArgument(Bind(definition));
  Do(InstanceCall(InstanceCallDescriptor::FromToken(Token::kASSIGN_INDEX),
                  stack_push,
                  stack_pointer_push,
                  value_push));
}


Definition* IRRegExpMacroAssembler::PopStack() {
  PushArgumentInstr* stack_push = PushLocal(stack_);
  PushArgumentInstr* stack_pointer_push1 = PushLocal(stack_pointer_);
  PushArgumentInstr* stack_pointer_push2 = PushLocal(stack_pointer_);
  StoreLocal(stack_pointer_,
             Bind(Sub(stack_pointer_push2,
                      PushArgument(Bind(Uint64Constant(1))))));
  return InstanceCall(InstanceCallDescriptor::FromToken(Token::kINDEX),
                      stack_push,
                      stack_pointer_push1);
}


Definition* IRRegExpMacroAssembler::PeekStack() {
  PushArgumentInstr* stack_push = PushLocal(stack_);
  PushArgumentInstr* stack_pointer_push = PushLocal(stack_pointer_);
  return InstanceCall(InstanceCallDescriptor::FromToken(Token::kINDEX),
                      stack_push,
                      stack_pointer_push);
}


// Pushes the location corresponding to label to the backtracking stack.
void IRRegExpMacroAssembler::PushBacktrack(BlockLabel* label) {
  TAG();

  // Ensure that targets of indirect jumps are never accessed through a
  // normal control flow instructions by creating a new block for each backtrack
  // target.
  IndirectEntryInstr* indirect_target = IndirectWithJoinGoto(label->block());

  // Add a fake edge from the graph entry for data flow analysis.
  entry_block_->AddIndirectEntry(indirect_target);

  ConstantInstr* offset = Uint64Constant(indirect_target->indirect_id());
  PushStack(offset);
  CheckStackLimit();
}


void IRRegExpMacroAssembler::PushCurrentPosition() {
  TAG();
  PushStack(LoadLocal(current_position_));
}


void IRRegExpMacroAssembler::PushRegister(intptr_t reg) {
  TAG();
  // TODO(zerny): Refactor PushStack so it can be reused here.
  PushArgumentInstr* stack_push = PushLocal(stack_);
  PushArgumentInstr* stack_pointer_push = PushLocal(stack_pointer_);
  StoreLocal(stack_pointer_,
             Bind(Add(stack_pointer_push,
                      PushArgument(Bind(Uint64Constant(1))))));
  stack_pointer_push = PushLocal(stack_pointer_);
  // TODO(zerny): bind value and push could break stack discipline.
  PushArgumentInstr* value_push = PushArgument(LoadRegister(reg));
  Do(InstanceCall(InstanceCallDescriptor::FromToken(Token::kASSIGN_INDEX),
                  stack_push,
                  stack_pointer_push,
                  value_push));
  CheckStackLimit();
}


// Checks that (stack.capacity - stack_limit_slack) > stack_pointer.
// This ensures that up to stack_limit_slack stack pushes can be
// done without exhausting the stack space. If the check fails the
// stack will be grown.
void IRRegExpMacroAssembler::CheckStackLimit() {
  TAG();
  PushArgumentInstr* stack_push = PushLocal(stack_);
  PushArgumentInstr* length_push = PushArgument(Bind(InstanceCall(
      InstanceCallDescriptor(
          String::ZoneHandle(Field::GetterSymbol(Symbols::Length()))),
      stack_push)));
  PushArgumentInstr* capacity_push = PushArgument(Bind(Sub(
      length_push,
      PushArgument(Bind(Uint64Constant(stack_limit_slack()))))));
  PushArgumentInstr* stack_pointer_push = PushLocal(stack_pointer_);
  BranchInstr* branch = new(I) BranchInstr(
      Comparison(kGT, capacity_push, stack_pointer_push));
  CloseBlockWith(branch);

  BlockLabel grow_stack;
  BlockLabel fallthrough;
  *branch->true_successor_address() =
      TargetWithJoinGoto(fallthrough.block());
  *branch->false_successor_address() =
      TargetWithJoinGoto(grow_stack.block());

  BindBlock(&grow_stack);
  GrowStack();

  BindBlock(&fallthrough);
}


void IRRegExpMacroAssembler::GrowStack() {
  TAG();
  Value* cell = Bind(new(I) ConstantInstr(stack_array_cell_));
  StoreLocal(stack_, Bind(new(I) GrowRegExpStackInstr(cell)));
}


void IRRegExpMacroAssembler::ReadCurrentPositionFromRegister(intptr_t reg) {
  TAG();
  StoreLocal(current_position_, LoadRegister(reg));
}

// Resets the tip of the stack to the value stored in reg.
void IRRegExpMacroAssembler::ReadStackPointerFromRegister(intptr_t reg) {
  TAG();
  ASSERT(reg < registers_count_);
  StoreLocal(stack_pointer_, LoadRegister(reg));
}

void IRRegExpMacroAssembler::SetCurrentPositionFromEnd(intptr_t by)  {
  TAG();

  BlockLabel after_position;

  Definition* cur_pos_def = LoadLocal(current_position_);
  Definition* by_value_def = Int64Constant(-by);

  BranchOrBacktrack(Comparison(kGTE, cur_pos_def, by_value_def),
                    &after_position);

  StoreLocal(current_position_, Bind(Int64Constant(-by)));

  // On RegExp code entry (where this operation is used), the character before
  // the current position is expected to be already loaded.
  // We have advanced the position, so it's safe to read backwards.
  LoadCurrentCharacterUnchecked(-1, 1);

  BindBlock(&after_position);
}


void IRRegExpMacroAssembler::SetRegister(intptr_t reg, intptr_t to) {
  TAG();
  // Reserved for positions!
  ASSERT(reg >= saved_registers_count_);
  StoreRegister(reg, to);
}


bool IRRegExpMacroAssembler::Succeed() {
  TAG();
  GoTo(success_block_);
  return global();
}


void IRRegExpMacroAssembler::WriteCurrentPositionToRegister(
    intptr_t reg, intptr_t cp_offset) {
  TAG();

  PushArgumentInstr* registers_push = PushLocal(registers_);
  PushArgumentInstr* index_push = PushRegisterIndex(reg);
  PushArgumentInstr* pos_push = PushLocal(current_position_);
  PushArgumentInstr* off_push = PushArgument(Bind(Int64Constant(cp_offset)));
  PushArgumentInstr* neg_off_push = PushArgument(Bind(Add(pos_push, off_push)));
  // Push the negative offset; these are converted to positive string positions
  // within the success block.
  StoreRegister(registers_push, index_push, neg_off_push);
}


void IRRegExpMacroAssembler::ClearRegisters(
    intptr_t reg_from, intptr_t reg_to) {
  TAG();

  ASSERT(reg_from <= reg_to);

  // In order to clear registers to a final result value of -1, set them to
  // (-1 - string length), the offset of -1 from the end of the string.

  for (intptr_t reg = reg_from; reg <= reg_to; reg++) {
    PushArgumentInstr* registers_push = PushLocal(registers_);
    PushArgumentInstr* index_push = PushRegisterIndex(reg);
    PushArgumentInstr* minus_one_push =
        PushArgument(Bind(Int64Constant(-1)));
    PushArgumentInstr* length_push = PushLocal(string_param_length_);
    PushArgumentInstr* value_push =
        PushArgument(Bind(Sub(minus_one_push, length_push)));
    StoreRegister(registers_push, index_push, value_push);
  }
}


void IRRegExpMacroAssembler::WriteStackPointerToRegister(intptr_t reg) {
  TAG();

  PushArgumentInstr* registers_push = PushLocal(registers_);
  PushArgumentInstr* index_push = PushRegisterIndex(reg);
  PushArgumentInstr* tip_push = PushLocal(stack_pointer_);
  StoreRegister(registers_push, index_push, tip_push);
}


// Private methods:


void IRRegExpMacroAssembler::CheckPosition(intptr_t cp_offset,
                                           BlockLabel* on_outside_input) {
  TAG();
  Definition* curpos_def = LoadLocal(current_position_);
  Definition* cp_off_def = Int64Constant(-cp_offset);

  // If (current_position_ < -cp_offset), we are in bounds.
  // Remember, current_position_ is a negative offset from the string end.

  BranchOrBacktrack(Comparison(kGTE, curpos_def, cp_off_def),
                    on_outside_input);
}


void IRRegExpMacroAssembler::BranchOrBacktrack(
    ComparisonInstr* comparison,
    BlockLabel* true_successor) {
  if (comparison == NULL) {  // No condition
    if (true_successor == NULL) {
      Backtrack();
      return;
    }
    GoTo(true_successor);
    return;
  }

  // If no successor block has been passed in, backtrack.
  JoinEntryInstr* true_successor_block = backtrack_block_;
  if (true_successor != NULL) {
    true_successor->SetLinked();
    true_successor_block = true_successor->block();
  }
  ASSERT(true_successor_block != NULL);

  // If the condition is not true, fall through to a new block.
  BlockLabel fallthrough;

  BranchInstr* branch = new(I) BranchInstr(comparison);
  *branch->true_successor_address() =
      TargetWithJoinGoto(true_successor_block);
  *branch->false_successor_address() =
      TargetWithJoinGoto(fallthrough.block());

  CloseBlockWith(branch);
  BindBlock(&fallthrough);
}


TargetEntryInstr* IRRegExpMacroAssembler::TargetWithJoinGoto(
    JoinEntryInstr* dst) {
  TargetEntryInstr* target = new(I) TargetEntryInstr(
          block_id_.Alloc(), kInvalidTryIndex);
  blocks_.Add(target);

  target->AppendInstruction(new(I) GotoInstr(dst));

  return target;
}


IndirectEntryInstr* IRRegExpMacroAssembler::IndirectWithJoinGoto(
    JoinEntryInstr* dst) {
  IndirectEntryInstr* target = new(I) IndirectEntryInstr(
          block_id_.Alloc(), indirect_id_.Alloc(), kInvalidTryIndex);
  blocks_.Add(target);

  target->AppendInstruction(new(I) GotoInstr(dst));

  return target;
}


void IRRegExpMacroAssembler::CheckPreemption() {
  TAG();
  AppendInstruction(new(I) CheckStackOverflowInstr(kNoSourcePos, 0));
}


Definition* IRRegExpMacroAssembler::Add(
    PushArgumentInstr* lhs,
    PushArgumentInstr* rhs) {
  return InstanceCall(InstanceCallDescriptor::FromToken(Token::kADD), lhs, rhs);
}


Definition* IRRegExpMacroAssembler::Sub(
    PushArgumentInstr* lhs,
    PushArgumentInstr* rhs) {
  return InstanceCall(InstanceCallDescriptor::FromToken(Token::kSUB), lhs, rhs);
}


void IRRegExpMacroAssembler::LoadCurrentCharacterUnchecked(
    intptr_t cp_offset, intptr_t characters) {
  TAG();

  ASSERT(characters == 1 || CanReadUnaligned());
  if (mode_ == ASCII) {
    ASSERT(characters == 1 || characters == 2 || characters == 4);
  } else {
    ASSERT(mode_ == UC16);
    ASSERT(characters == 1 || characters == 2);
  }

  // Calculate the addressed string index as:
  //    cp_offset + current_position_ + string_param_length_
  // TODO(zerny): Avoid generating 'add' instance-calls here.
  PushArgumentInstr* off_arg =
      PushArgument(Bind(Int64Constant(cp_offset)));
  PushArgumentInstr* pos_arg =
      PushArgument(BindLoadLocal(*current_position_));
  PushArgumentInstr* off_pos_arg =
      PushArgument(Bind(Add(off_arg, pos_arg)));
  PushArgumentInstr* len_arg =
      PushArgument(BindLoadLocal(*string_param_length_));
  // Index is stored in a temporary local so that we can later load it safely.
  StoreLocal(index_temp_, Bind(Add(off_pos_arg, len_arg)));

  // Load and store the code units.
  Value* code_unit_value = LoadCodeUnitsAt(index_temp_, characters);
  StoreLocal(current_character_, code_unit_value);
  PRINT(PushLocal(current_character_));
}


Value* IRRegExpMacroAssembler::CharacterAt(LocalVariable* index) {
  return LoadCodeUnitsAt(index, 1);
}


Value* IRRegExpMacroAssembler::LoadCodeUnitsAt(LocalVariable* index,
                                               intptr_t characters) {
  // Bind the pattern as the load receiver.
  Value* pattern_val = BindLoadLocal(*string_param_);
  if (RawObject::IsExternalStringClassId(specialization_cid_)) {
    // The data of an external string is stored through two indirections.
    intptr_t external_offset = 0;
    intptr_t data_offset = 0;
    if (specialization_cid_ == kExternalOneByteStringCid) {
      external_offset = ExternalOneByteString::external_data_offset();
      data_offset = RawExternalOneByteString::ExternalData::data_offset();
    } else if (specialization_cid_ == kExternalTwoByteStringCid) {
      external_offset = ExternalTwoByteString::external_data_offset();
      data_offset = RawExternalTwoByteString::ExternalData::data_offset();
    } else {
      UNREACHABLE();
    }
    // This pushes untagged values on the stack which are immediately consumed:
    // the first value is consumed to obtain the second value which is consumed
    // by LoadCodeUnitsAtInstr below.
    Value* external_val =
        Bind(new(I) LoadUntaggedInstr(pattern_val, external_offset));
    pattern_val =
        Bind(new(I) LoadUntaggedInstr(external_val, data_offset));
  }

  // Here pattern_val might be untagged so this must not trigger a GC.
  Value* index_val = BindLoadLocal(*index);

  return Bind(new(I) LoadCodeUnitsInstr(
      pattern_val,
      index_val,
      characters,
      specialization_cid_,
      Scanner::kNoSourcePos));
}


#undef __

}  // namespace dart
