/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
 * vim: set ts=8 sts=4 et sw=4 tw=99: */

// Copyright 2012 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
//       copyright notice, this list of conditions and the following
//       disclaimer in the documentation and/or other materials provided
//       with the distribution.
//     * Neither the name of Google Inc. nor the names of its
//       contributors may be used to endorse or promote products derived
//       from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include "irregexp/RegExpEngine.h"

#include "irregexp/NativeRegExpMacroAssembler.h"
#include "irregexp/RegExpMacroAssembler.h"
#include "jit/JitCommon.h"

using namespace js;
using namespace js::irregexp;

using mozilla::ArrayLength;
using mozilla::DebugOnly;
using mozilla::Maybe;

#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);
}

static const int kMaxLookaheadForBoyerMoore = 8;

RegExpNode::RegExpNode(LifoAlloc* alloc)
  : replacement_(nullptr), trace_count_(0), alloc_(alloc)
{
    bm_info_[0] = bm_info_[1] = nullptr;
}

// -------------------------------------------------------------------
// CharacterRange

// The '2' variant has 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.
static const int kSpaceRanges[] = { '\t', '\r' + 1, ' ', ' ' + 1,
    0x00A0, 0x00A1, 0x1680, 0x1681, 0x180E, 0x180F, 0x2000, 0x200B,
    0x2028, 0x202A, 0x202F, 0x2030, 0x205F, 0x2060, 0x3000, 0x3001,
    0xFEFF, 0xFF00, 0x10000 };
static const int kSpaceRangeCount = ArrayLength(kSpaceRanges);

static const int kWordRanges[] = {
    '0', '9' + 1, 'A', 'Z' + 1, '_', '_' + 1, 'a', 'z' + 1, 0x10000 };
static const int kWordRangeCount = ArrayLength(kWordRanges);
static const int kDigitRanges[] = { '0', '9' + 1, 0x10000 };
static const int kDigitRangeCount = ArrayLength(kDigitRanges);
static const int kSurrogateRanges[] = { 0xd800, 0xe000, 0x10000 };
static const int kSurrogateRangeCount = ArrayLength(kSurrogateRanges);
static const int kLineTerminatorRanges[] = { 0x000A, 0x000B, 0x000D, 0x000E,
    0x2028, 0x202A, 0x10000 };
static const int kLineTerminatorRangeCount = ArrayLength(kLineTerminatorRanges);
static const int kMaxOneByteCharCode = 0xff;
static const int kMaxUtf16CodeUnit = 0xffff;

static char16_t
MaximumCharacter(bool ascii)
{
    return ascii ? kMaxOneByteCharCode : kMaxUtf16CodeUnit;
}

static void
AddClass(const int* elmv, int elmc,
         CharacterRangeVector* ranges)
{
    elmc--;
    MOZ_ASSERT(elmv[elmc] == 0x10000);
    for (int i = 0; i < elmc; i += 2) {
        MOZ_ASSERT(elmv[i] < elmv[i + 1]);
        ranges->append(CharacterRange(elmv[i], elmv[i + 1] - 1));
    }
}

static void
AddClassNegated(const int* elmv,
                int elmc,
                CharacterRangeVector* ranges)
{
    elmc--;
    MOZ_ASSERT(elmv[elmc] == 0x10000);
    MOZ_ASSERT(elmv[0] != 0x0000);
    MOZ_ASSERT(elmv[elmc-1] != kMaxUtf16CodeUnit);
    char16_t last = 0x0000;
    for (int i = 0; i < elmc; i += 2) {
        MOZ_ASSERT(last <= elmv[i] - 1);
        MOZ_ASSERT(elmv[i] < elmv[i + 1]);
        ranges->append(CharacterRange(last, elmv[i] - 1));
        last = elmv[i + 1];
    }
    ranges->append(CharacterRange(last, kMaxUtf16CodeUnit));
}

void
CharacterRange::AddClassEscape(LifoAlloc* alloc, char16_t type,
			       CharacterRangeVector* 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->append(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:
        MOZ_CRASH("Bad character class escape");
    }
}

// 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(const CharacterRangeVector& ranges)
{
    for (size_t i = 0; i < ranges.length(); i++) {
        // TODO(dcarney): this could be a lot more efficient.
        if (RangeContainsLatin1Equivalents(ranges[i]))
            return true;
    }
    return false;
}

static const size_t kEcma262UnCanonicalizeMaxWidth = 4;

// Returns the number of characters in the equivalence class, omitting those
// that cannot occur in the source string if it is a one byte string.
static int
GetCaseIndependentLetters(char16_t character,
                          bool ascii_subject,
                          char16_t* letters)
{
    const char16_t choices[] = {
        character,
        unicode::ToLowerCase(character),
        unicode::ToUpperCase(character)
    };

    size_t count = 0;
    for (size_t i = 0; i < ArrayLength(choices); i++) {
        char16_t c = choices[i];

        // The standard requires that non-ASCII characters cannot have ASCII
        // character codes in their equivalence class, even though this
        // situation occurs multiple times in the unicode tables.
        static const unsigned kMaxAsciiCharCode = 127;
        if (character > kMaxAsciiCharCode && c <= kMaxAsciiCharCode)
            continue;

        // Skip characters that can't appear in one byte strings.
        if (ascii_subject && c > kMaxOneByteCharCode)
            continue;

        // Watch for duplicates.
        bool found = false;
        for (size_t j = 0; j < count; j++) {
            if (letters[j] == c) {
                found = true;
                break;
            }
        }
        if (found)
            continue;

        letters[count++] = c;
    }

    return count;
}

static char16_t
ConvertNonLatin1ToLatin1(char16_t c)
{
    MOZ_ASSERT(c > kMaxOneByteCharCode);
    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;
}

void
CharacterRange::AddCaseEquivalents(bool is_ascii, CharacterRangeVector* ranges)
{
    char16_t bottom = from();
    char16_t top = to();

    if (is_ascii && !RangeContainsLatin1Equivalents(*this)) {
        if (bottom > kMaxOneByteCharCode)
            return;
        if (top > kMaxOneByteCharCode)
            top = kMaxOneByteCharCode;
    }

    for (char16_t c = bottom;; c++) {
        char16_t chars[kEcma262UnCanonicalizeMaxWidth];
        size_t length = GetCaseIndependentLetters(c, is_ascii, chars);

        for (size_t i = 0; i < length; i++) {
            char16_t other = chars[i];
            if (other == c)
                continue;

            // Try to combine with an existing range.
            bool found = false;
            for (size_t i = 0; i < ranges->length(); i++) {
                CharacterRange& range = (*ranges)[i];
                if (range.Contains(other)) {
                    found = true;
                    break;
                } else if (other == range.from() - 1) {
                    range.set_from(other);
                    found = true;
                    break;
                } else if (other == range.to() + 1) {
                    range.set_to(other);
                    found = true;
                    break;
                }
            }

            if (!found)
                ranges->append(CharacterRange::Singleton(other));
        }

        if (c == top)
            break;
    }
}

static bool
CompareInverseRanges(const CharacterRangeVector& ranges, const int* special_class, size_t length)
{
    length--;  // Remove final 0x10000.
    MOZ_ASSERT(special_class[length] == 0x10000);
    MOZ_ASSERT(ranges.length() != 0);
    MOZ_ASSERT(length != 0);
    MOZ_ASSERT(special_class[0] != 0);
    if (ranges.length() != (length >> 1) + 1)
        return false;
    CharacterRange range = ranges[0];
    if (range.from() != 0)
        return false;
    for (size_t i = 0; i < length; i += 2) {
        if (special_class[i] != (range.to() + 1))
            return false;
        range = ranges[(i >> 1) + 1];
        if (special_class[i+1] != range.from())
            return false;
    }
    if (range.to() != 0xffff)
        return false;
    return true;
}

static bool
CompareRanges(const CharacterRangeVector& ranges, const int* special_class, size_t length)
{
    length--;  // Remove final 0x10000.
    MOZ_ASSERT(special_class[length] == 0x10000);
    if (ranges.length() * 2 != length)
        return false;
    for (size_t i = 0; i < length; i += 2) {
        CharacterRange range = ranges[i >> 1];
        if (range.from() != special_class[i] || range.to() != special_class[i + 1] - 1)
            return false;
    }
    return true;
}

bool
RegExpCharacterClass::is_standard(LifoAlloc* alloc)
{
    // 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(alloc), kSpaceRanges, kSpaceRangeCount)) {
        set_.set_standard_set_type('s');
        return true;
    }
    if (CompareInverseRanges(set_.ranges(alloc), kSpaceRanges, kSpaceRangeCount)) {
        set_.set_standard_set_type('S');
        return true;
    }
    if (CompareInverseRanges(set_.ranges(alloc),
                             kLineTerminatorRanges,
                             kLineTerminatorRangeCount)) {
        set_.set_standard_set_type('.');
        return true;
    }
    if (CompareRanges(set_.ranges(alloc),
                      kLineTerminatorRanges,
                      kLineTerminatorRangeCount)) {
        set_.set_standard_set_type('n');
        return true;
    }
    if (CompareRanges(set_.ranges(alloc), kWordRanges, kWordRangeCount)) {
        set_.set_standard_set_type('w');
        return true;
    }
    if (CompareInverseRanges(set_.ranges(alloc), kWordRanges, kWordRangeCount)) {
        set_.set_standard_set_type('W');
        return true;
    }
    return false;
}

bool
CharacterRange::IsCanonical(const CharacterRangeVector& ranges)
{
    int n = ranges.length();
    if (n <= 1)
        return true;

    int max = ranges[0].to();
    for (int i = 1; i < n; i++) {
        CharacterRange next_range = ranges[i];
        if (next_range.from() <= max + 1)
            return false;
        max = next_range.to();
    }
    return true;
}

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

static int
InsertRangeInCanonicalList(CharacterRangeVector& list,
                           int 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.
    char16_t from = insert.from();
    char16_t to = insert.to();
    int start_pos = 0;
    int end_pos = count;
    for (int i = count - 1; i >= 0; i--) {
        CharacterRange current = list[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[start_pos];
        int new_from = Min(to_replace.from(), from);
        int new_to = Max(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.

    int new_from = Min(list[start_pos].from(), from);
    int new_to = Max(list[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
CharacterRange::Canonicalize(CharacterRangeVector& character_ranges)
{
    if (character_ranges.length() <= 1) return;
    // Check whether ranges are already canonical (increasing, non-overlapping,
    // non-adjacent).
    int n = character_ranges.length();
    int max = character_ranges[0].to();
    int i = 1;
    while (i < n) {
        CharacterRange current = character_ranges[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.
    int read = i;  // Range to insert.
    size_t num_canonical = i;  // Length of canonicalized part of list.
    do {
        num_canonical = InsertRangeInCanonicalList(character_ranges,
                                                   num_canonical,
                                                   character_ranges[read]);
        read++;
    } while (read < n);

    while (character_ranges.length() > num_canonical)
        character_ranges.popBack();

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

// -------------------------------------------------------------------
// SeqRegExpNode

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

bool
SeqRegExpNode::FillInBMInfo(int offset,
                            int budget,
                            BoyerMooreLookahead* bm,
                            bool not_at_start)
{
    if (!bm->CheckOverRecursed())
        return false;
    if (!on_success_->FillInBMInfo(offset, budget - 1, bm, not_at_start))
        return false;
    if (offset == 0)
        set_bm_info(not_at_start, bm);
    return true;
}

RegExpNode*
SeqRegExpNode::FilterASCII(int depth, bool ignore_case)
{
    if (info()->replacement_calculated)
        return replacement();

    if (depth < 0)
        return this;

    MOZ_ASSERT(!info()->visited);
    VisitMarker marker(info());
    return FilterSuccessor(depth - 1, ignore_case);
}

RegExpNode*
SeqRegExpNode::FilterSuccessor(int depth, bool ignore_case)
{
    RegExpNode* next = on_success_->FilterASCII(depth - 1, ignore_case);
    if (next == nullptr)
        return set_replacement(nullptr);

    on_success_ = next;
    return set_replacement(this);
}

// -------------------------------------------------------------------
// ActionNode

int
ActionNode::EatsAtLeast(int still_to_find, int 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);
}

bool
ActionNode::FillInBMInfo(int offset,
                         int budget,
                         BoyerMooreLookahead* bm,
                         bool not_at_start)
{
    if (!bm->CheckOverRecursed())
        return false;

    if (action_type_ == BEGIN_SUBMATCH) {
        bm->SetRest(offset);
    } else if (action_type_ != POSITIVE_SUBMATCH_SUCCESS) {
        if (!on_success()->FillInBMInfo(offset, budget - 1, bm, not_at_start))
            return false;
    }
    SaveBMInfo(bm, not_at_start, offset);

    return true;
}

/* static */ ActionNode*
ActionNode::SetRegister(int reg,
                        int val,
                        RegExpNode* on_success)
{
    ActionNode* result = on_success->alloc()->newInfallible<ActionNode>(SET_REGISTER, on_success);
    result->data_.u_store_register.reg = reg;
    result->data_.u_store_register.value = val;
    return result;
}

/* static */ ActionNode*
ActionNode::IncrementRegister(int reg, RegExpNode* on_success)
{
    ActionNode* result = on_success->alloc()->newInfallible<ActionNode>(INCREMENT_REGISTER, on_success);
    result->data_.u_increment_register.reg = reg;
    return result;
}

/* static */ ActionNode*
ActionNode::StorePosition(int reg, bool is_capture, RegExpNode* on_success)
{
    ActionNode* result = on_success->alloc()->newInfallible<ActionNode>(STORE_POSITION, on_success);
    result->data_.u_position_register.reg = reg;
    result->data_.u_position_register.is_capture = is_capture;
    return result;
}

/* static */ ActionNode*
ActionNode::ClearCaptures(Interval range, RegExpNode* on_success)
{
    ActionNode* result = on_success->alloc()->newInfallible<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;
}

/* static */ ActionNode*
ActionNode::BeginSubmatch(int stack_pointer_reg, int position_reg, RegExpNode* on_success)
{
    ActionNode* result = on_success->alloc()->newInfallible<ActionNode>(BEGIN_SUBMATCH, on_success);
    result->data_.u_submatch.stack_pointer_register = stack_pointer_reg;
    result->data_.u_submatch.current_position_register = position_reg;
    return result;
}

/* static */ ActionNode*
ActionNode::PositiveSubmatchSuccess(int stack_pointer_reg,
                                    int restore_reg,
                                    int clear_capture_count,
                                    int clear_capture_from,
                                    RegExpNode* on_success)
{
    ActionNode* result = on_success->alloc()->newInfallible<ActionNode>(POSITIVE_SUBMATCH_SUCCESS, on_success);
    result->data_.u_submatch.stack_pointer_register = stack_pointer_reg;
    result->data_.u_submatch.current_position_register = restore_reg;
    result->data_.u_submatch.clear_register_count = clear_capture_count;
    result->data_.u_submatch.clear_register_from = clear_capture_from;
    return result;
}

/* static */ ActionNode*
ActionNode::EmptyMatchCheck(int start_register,
                            int repetition_register,
                            int repetition_limit,
                            RegExpNode* on_success)
{
    ActionNode* result = on_success->alloc()->newInfallible<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;
}

// -------------------------------------------------------------------
// TextNode

int
TextNode::EatsAtLeast(int still_to_find, int budget, bool not_at_start)
{
    int 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);
}

int
TextNode::GreedyLoopTextLength()
{
    TextElement elm = elements()[elements().length() - 1];
    return elm.cp_offset() + elm.length();
}

RegExpNode*
TextNode::FilterASCII(int depth, bool ignore_case)
{
    if (info()->replacement_calculated)
        return replacement();

    if (depth < 0)
        return this;

    MOZ_ASSERT(!info()->visited);
    VisitMarker marker(info());
    int element_count = elements().length();
    for (int i = 0; i < element_count; i++) {
        TextElement elm = elements()[i];
        if (elm.text_type() == TextElement::ATOM) {
            CharacterVector& quarks = const_cast<CharacterVector&>(elm.atom()->data());
            for (size_t j = 0; j < quarks.length(); j++) {
                uint16_t c = quarks[j];
                if (c <= kMaxOneByteCharCode)
                    continue;
                if (!ignore_case)
                    return set_replacement(nullptr);

                // Here, we need to check for characters whose upper and lower cases
                // are outside the Latin-1 range.
                char16_t converted = ConvertNonLatin1ToLatin1(c);
                if (converted == 0) {
                    // Character is outside Latin-1 completely
                    return set_replacement(nullptr);
                }

                // Convert quark to Latin-1 in place.
                quarks[j] = converted;
            }
        } else {
            MOZ_ASSERT(elm.text_type() == TextElement::CHAR_CLASS);
            RegExpCharacterClass* cc = elm.char_class();

            CharacterRangeVector& ranges = cc->ranges(alloc());
            if (!CharacterRange::IsCanonical(ranges))
                CharacterRange::Canonicalize(ranges);

            // Now they are in order so we only need to look at the first.
            int range_count = ranges.length();
            if (cc->is_negated()) {
                if (range_count != 0 &&
                    ranges[0].from() == 0 &&
                    ranges[0].to() >= kMaxOneByteCharCode)
                {
                    // This will be handled in a later filter.
                    if (ignore_case && RangesContainLatin1Equivalents(ranges))
                        continue;
                    return set_replacement(nullptr);
                }
            } else {
                if (range_count == 0 ||
                    ranges[0].from() > kMaxOneByteCharCode)
                {
                    // This will be handled in a later filter.
                    if (ignore_case && RangesContainLatin1Equivalents(ranges))
                        continue;
                    return set_replacement(nullptr);
                }
            }
        }
    }
    return FilterSuccessor(depth - 1, ignore_case);
}

void
TextNode::CalculateOffsets()
{
    int 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.
    int cp_offset = 0;
    for (int i = 0; i < element_count; i++) {
        TextElement& elm = elements()[i];
        elm.set_cp_offset(cp_offset);
        cp_offset += elm.length();
    }
}

void TextNode::MakeCaseIndependent(bool is_ascii)
{
    int element_count = elements().length();
    for (int i = 0; i < element_count; i++) {
        TextElement elm = elements()[i];
        if (elm.text_type() == TextElement::CHAR_CLASS) {
            RegExpCharacterClass* cc = elm.char_class();

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

            CharacterRangeVector& ranges = cc->ranges(alloc());
            int range_count = ranges.length();
            for (int j = 0; j < range_count; j++)
                ranges[j].AddCaseEquivalents(is_ascii, &ranges);
        }
    }
}

// -------------------------------------------------------------------
// AssertionNode

int
AssertionNode::EatsAtLeast(int still_to_find, int 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);
}

bool
AssertionNode::FillInBMInfo(int offset, int budget, BoyerMooreLookahead* bm, bool not_at_start)
{
    if (!bm->CheckOverRecursed())
        return false;

    // Match the behaviour of EatsAtLeast on this node.
    if (assertion_type() == AT_START && not_at_start)
        return true;

    if (!on_success()->FillInBMInfo(offset, budget - 1, bm, not_at_start))
        return false;
    SaveBMInfo(bm, not_at_start, offset);
    return true;
}

// -------------------------------------------------------------------
// BackReferenceNode

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

bool
BackReferenceNode::FillInBMInfo(int offset, int 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);
    return true;
}

// -------------------------------------------------------------------
// ChoiceNode

int
ChoiceNode::EatsAtLeastHelper(int still_to_find,
                              int budget,
                              RegExpNode* ignore_this_node,
                              bool not_at_start)
{
    if (budget <= 0)
        return 0;

    int min = 100;
    size_t choice_count = alternatives().length();
    budget = (budget - 1) / choice_count;
    for (size_t i = 0; i < choice_count; i++) {
        RegExpNode* node = alternatives()[i].node();
        if (node == ignore_this_node) continue;
        int 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;
}

int
ChoiceNode::EatsAtLeast(int still_to_find, int budget, bool not_at_start)
{
    return EatsAtLeastHelper(still_to_find,
                             budget,
                             nullptr,
                             not_at_start);
}

void
ChoiceNode::GetQuickCheckDetails(QuickCheckDetails* details,
                                 RegExpCompiler* compiler,
                                 int characters_filled_in,
                                 bool not_at_start)
{
    not_at_start = (not_at_start || not_at_start_);
    int choice_count = alternatives().length();
    MOZ_ASSERT(choice_count > 0);
    alternatives()[0].node()->GetQuickCheckDetails(details,
                                                   compiler,
                                                   characters_filled_in,
                                                   not_at_start);
    for (int 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);
    }
}

bool
ChoiceNode::FillInBMInfo(int offset,
                         int budget,
                         BoyerMooreLookahead* bm,
                         bool not_at_start)
{
    if (!bm->CheckOverRecursed())
        return false;

    const GuardedAlternativeVector& alts = alternatives();
    budget = (budget - 1) / alts.length();
    for (size_t i = 0; i < alts.length(); i++) {
        const GuardedAlternative& alt = alts[i];
        if (alt.guards() != nullptr && alt.guards()->length() != 0) {
            bm->SetRest(offset);  // Give up trying to fill in info.
            SaveBMInfo(bm, not_at_start, offset);
            return true;
        }
        if (!alt.node()->FillInBMInfo(offset, budget, bm, not_at_start))
            return false;
    }
    SaveBMInfo(bm, not_at_start, offset);
    return true;
}

RegExpNode*
ChoiceNode::FilterASCII(int depth, bool ignore_case)
{
    if (info()->replacement_calculated)
        return replacement();
    if (depth < 0)
        return this;
    if (info()->visited)
        return this;
    VisitMarker marker(info());
    int choice_count = alternatives().length();

    for (int i = 0; i < choice_count; i++) {
        const GuardedAlternative alternative = alternatives()[i];
        if (alternative.guards() != nullptr && alternative.guards()->length() != 0) {
            set_replacement(this);
            return this;
        }
    }

    int surviving = 0;
    RegExpNode* survivor = nullptr;
    for (int i = 0; i < choice_count; i++) {
        GuardedAlternative alternative = alternatives()[i];
        RegExpNode* replacement =
            alternative.node()->FilterASCII(depth - 1, ignore_case);
        MOZ_ASSERT(replacement != this);  // No missing EMPTY_MATCH_CHECK.
        if (replacement != nullptr) {
            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.
    GuardedAlternativeVector new_alternatives(*alloc());
    new_alternatives.reserve(surviving);
    for (int i = 0; i < choice_count; i++) {
        RegExpNode* replacement =
            alternatives()[i].node()->FilterASCII(depth - 1, ignore_case);
        if (replacement != nullptr) {
            alternatives()[i].set_node(replacement);
            AutoEnterOOMUnsafeRegion oomUnsafe;
            if (!new_alternatives.append(alternatives()[i]))
                oomUnsafe.crash("ChoiceNode::FilterASCII");
        }
    }

    alternatives_ = Move(new_alternatives);
    return this;
}

// -------------------------------------------------------------------
// NegativeLookaheadChoiceNode

bool
NegativeLookaheadChoiceNode::FillInBMInfo(int offset,
                                          int budget,
                                          BoyerMooreLookahead* bm,
                                          bool not_at_start)
{
    if (!bm->CheckOverRecursed())
        return false;

    if (!alternatives()[1].node()->FillInBMInfo(offset, budget - 1, bm, not_at_start))
        return false;
    if (offset == 0)
        set_bm_info(not_at_start, bm);
    return true;
}

int
NegativeLookaheadChoiceNode::EatsAtLeast(int still_to_find, int 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
NegativeLookaheadChoiceNode::GetQuickCheckDetails(QuickCheckDetails* details,
                                                  RegExpCompiler* compiler,
                                                  int 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);
}

RegExpNode*
NegativeLookaheadChoiceNode::FilterASCII(int depth, bool ignore_case)
{
    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->FilterASCII(depth - 1, ignore_case);

    if (replacement == nullptr)
        return set_replacement(nullptr);
    alternatives()[1].set_node(replacement);

    RegExpNode* neg_node = alternatives()[0].node();
    RegExpNode* neg_replacement = neg_node->FilterASCII(depth - 1, ignore_case);

    // If the negative lookahead is always going to fail then
    // we don't need to check it.
    if (neg_replacement == nullptr)
        return set_replacement(replacement);

    alternatives()[0].set_node(neg_replacement);
    return set_replacement(this);
}

// -------------------------------------------------------------------
// LoopChoiceNode

void
GuardedAlternative::AddGuard(LifoAlloc* alloc, Guard* guard)
{
    if (guards_ == nullptr)
        guards_ = alloc->newInfallible<GuardVector>(*alloc);
    guards_->append(guard);
}

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


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

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

void
LoopChoiceNode::GetQuickCheckDetails(QuickCheckDetails* details,
                                     RegExpCompiler* compiler,
                                     int 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);
}

bool
LoopChoiceNode::FillInBMInfo(int offset,
                             int 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 true;
    }
    if (!ChoiceNode::FillInBMInfo(offset, budget - 1, bm, not_at_start))
        return false;
    SaveBMInfo(bm, not_at_start, offset);
    return true;
}

RegExpNode*
LoopChoiceNode::FilterASCII(int depth, bool ignore_case)
{
    if (info()->replacement_calculated)
        return replacement();
    if (depth < 0)
        return this;
    if (info()->visited)
        return this;

    {
        VisitMarker marker(info());

        RegExpNode* continue_replacement =
            continue_node_->FilterASCII(depth - 1, ignore_case);

        // If we can't continue after the loop then there is no sense in doing the
        // loop.
        if (continue_replacement == nullptr)
            return set_replacement(nullptr);
    }

    return ChoiceNode::FilterASCII(depth - 1, ignore_case);
}

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

void
Analysis::EnsureAnalyzed(RegExpNode* that)
{
    JS_CHECK_RECURSION(cx, fail("Stack overflow"); return);

    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
Analysis::VisitText(TextNode* that)
{
    if (ignore_case_)
        that->MakeCaseIndependent(is_ascii_);
    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 (size_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 (size_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());
}

// -------------------------------------------------------------------
// 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 either
// bytecodes or native code.

//   The Irregexp regexp engine is structured in three steps.
//   1) The parser generates an abstract syntax tree.  See RegExpAST.cpp.
//   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 either byte codes or native code
//      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 (whether as byte codes or native code) 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.

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

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

int
TextElement::length() const
{
    switch (text_type()) {
      case ATOM:
        return atom()->length();
      case CHAR_CLASS:
        return 1;
    }
    MOZ_CRASH("Bad text type");
}

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

    void CountCharacter(int character) {
        int 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).
    int Frequency(int in_character) {
        MOZ_ASSERT((in_character & RegExpMacroAssembler::kTableMask) == in_character);
        if (total_samples_ < 1) return 1;  // Division by zero.
        int 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(int character)
          : counter_(0), character_(character)
        {}

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

     private:
        int counter_;
        int character_;
    };

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

class irregexp::RegExpCompiler
{
  public:
    RegExpCompiler(JSContext* cx, LifoAlloc* alloc, int capture_count,
                   bool ignore_case, bool is_ascii, bool match_only);

    int AllocateRegister() {
        if (next_register_ >= RegExpMacroAssembler::kMaxRegister) {
            reg_exp_too_big_ = true;
            return next_register_;
        }
        return next_register_++;
    }

    RegExpCode Assemble(JSContext* cx,
                        RegExpMacroAssembler* assembler,
                        RegExpNode* start,
                        int capture_count);

    inline void AddWork(RegExpNode* node) {
        AutoEnterOOMUnsafeRegion oomUnsafe;
        if (!work_list_.append(node))
            oomUnsafe.crash("AddWork");
    }

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

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

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

    void SetRegExpTooBig() { reg_exp_too_big_ = true; }

    inline bool ignore_case() { return ignore_case_; }
    inline bool ascii() { return ascii_; }
    FrequencyCollator* frequency_collator() { return &frequency_collator_; }

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

    JSContext* cx() const { return cx_; }
    LifoAlloc* alloc() const { return alloc_; }

    static const int kNoRegister = -1;

  private:
    EndNode* accept_;
    int next_register_;
    Vector<RegExpNode*, 4, SystemAllocPolicy> work_list_;
    int recursion_depth_;
    RegExpMacroAssembler* macro_assembler_;
    bool ignore_case_;
    bool ascii_;
    bool match_only_;
    bool reg_exp_too_big_;
    int current_expansion_factor_;
    FrequencyCollator frequency_collator_;
    JSContext* cx_;
    LifoAlloc* alloc_;
};

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

  private:
    RegExpCompiler* compiler_;
};

// 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(JSContext* cx, LifoAlloc* alloc, int capture_count,
                               bool ignore_case, bool ascii, bool match_only)
  : next_register_(2 * (capture_count + 1)),
    recursion_depth_(0),
    ignore_case_(ignore_case),
    ascii_(ascii),
    match_only_(match_only),
    reg_exp_too_big_(false),
    current_expansion_factor_(1),
    frequency_collator_(),
    cx_(cx),
    alloc_(alloc)
{
    accept_ = alloc->newInfallible<EndNode>(alloc, EndNode::ACCEPT);
    MOZ_ASSERT(next_register_ - 1 <= RegExpMacroAssembler::kMaxRegister);
}

RegExpCode
RegExpCompiler::Assemble(JSContext* cx,
                         RegExpMacroAssembler* assembler,
                         RegExpNode* start,
                         int capture_count)
{
    macro_assembler_ = assembler;
    macro_assembler_->set_slow_safe(false);

    jit::Label fail;
    macro_assembler_->PushBacktrack(&fail);
    Trace new_trace;
    start->Emit(this, &new_trace);
    macro_assembler_->BindBacktrack(&fail);
    macro_assembler_->Fail();

    while (!work_list_.empty())
        work_list_.popCopy()->Emit(this, &new_trace);

    RegExpCode code = macro_assembler_->GenerateCode(cx, match_only_);
    if (code.empty())
        return RegExpCode();

    if (reg_exp_too_big_) {
        code.destroy();
        JS_ReportError(cx, "regexp too big");
        return RegExpCode();
    }

    return code;
}

template <typename CharT>
static void
SampleChars(FrequencyCollator* collator, const CharT* chars, size_t length)
{
    // Sample some characters from the middle of the string.
    static const int kSampleSize = 128;

    int chars_sampled = 0;
    int half_way = (int(length) - kSampleSize) / 2;
    for (size_t i = Max(0, half_way);
         i < length && chars_sampled < kSampleSize;
         i++, chars_sampled++)
    {
        collator->CountCharacter(chars[i]);
    }
}

static bool
IsNativeRegExpEnabled(JSContext* cx)
{
#if defined(JS_CODEGEN_NONE) || defined(COBALT_DISABLE_JIT)
    return false;
#else
    return cx->runtime()->options().nativeRegExp();
#endif
}

RegExpCode
irregexp::CompilePattern(JSContext* cx, RegExpShared* shared, RegExpCompileData* data,
                         HandleLinearString sample, bool is_global, bool ignore_case,
                         bool is_ascii, bool match_only, bool force_bytecode, bool sticky)
{
    if ((data->capture_count + 1) * 2 - 1 > RegExpMacroAssembler::kMaxRegister) {
        JS_ReportError(cx, "regexp too big");
        return RegExpCode();
    }

    LifoAlloc& alloc = cx->tempLifoAlloc();
    RegExpCompiler compiler(cx, &alloc, data->capture_count, ignore_case, is_ascii, match_only);

    // Sample some characters from the middle of the string.
    if (sample->hasLatin1Chars()) {
        JS::AutoCheckCannotGC nogc;
        SampleChars(compiler.frequency_collator(), sample->latin1Chars(nogc), sample->length());
    } else {
        JS::AutoCheckCannotGC nogc;
        SampleChars(compiler.frequency_collator(), sample->twoByteChars(nogc), sample->length());
    }

    // 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 = sticky || data->tree->IsAnchoredAtStart();
    int max_length = data->tree->max_match();
    if (!is_start_anchored) {
        // 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,
                                     alloc.newInfallible<RegExpCharacterClass>('*'),
                                     &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 = alloc.newInfallible<ChoiceNode>(&alloc, 2);
            RegExpNode* char_class =
                alloc.newInfallible<TextNode>(alloc.newInfallible<RegExpCharacterClass>('*'), loop_node);
            first_step_node->AddAlternative(GuardedAlternative(captured_body));
            first_step_node->AddAlternative(GuardedAlternative(char_class));
            node = first_step_node;
        } else {
            node = loop_node;
        }
    }
    if (is_ascii) {
        node = node->FilterASCII(RegExpCompiler::kMaxRecursion, ignore_case);
        // Do it again to propagate the new nodes to places where they were not
        // put because they had not been calculated yet.
        if (node != nullptr) {
            node = node->FilterASCII(RegExpCompiler::kMaxRecursion, ignore_case);
        }
    }

    if (node == nullptr)
        node = alloc.newInfallible<EndNode>(&alloc, EndNode::BACKTRACK);

    Analysis analysis(cx, ignore_case, is_ascii);
    analysis.EnsureAnalyzed(node);
    if (analysis.has_failed()) {
        JS_ReportError(cx, analysis.errorMessage());
        return RegExpCode();
    }

    Maybe<jit::JitContext> ctx;
    Maybe<NativeRegExpMacroAssembler> native_assembler;
    Maybe<InterpretedRegExpMacroAssembler> interpreted_assembler;

    RegExpMacroAssembler* assembler;
    if (IsNativeRegExpEnabled(cx) && !force_bytecode) {
        NativeRegExpMacroAssembler::Mode mode =
            is_ascii ? NativeRegExpMacroAssembler::ASCII
                     : NativeRegExpMacroAssembler::CHAR16;

        ctx.emplace(cx, (jit::TempAllocator*) nullptr);
        native_assembler.emplace(&alloc, shared, cx->runtime(), mode, (data->capture_count + 1) * 2);
        assembler = native_assembler.ptr();
    } else {
        interpreted_assembler.emplace(&alloc, shared, (data->capture_count + 1) * 2);
        assembler = interpreted_assembler.ptr();
    }

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

    if (is_global) {
        assembler->set_global_mode((data->tree->min_match() > 0)
                                   ? RegExpMacroAssembler::GLOBAL_NO_ZERO_LENGTH_CHECK
                                   : RegExpMacroAssembler::GLOBAL);
    }

    return compiler.Assemble(cx, assembler, node, data->capture_count);
}

template <typename CharT>
RegExpRunStatus
irregexp::ExecuteCode(JSContext* cx, jit::JitCode* codeBlock, const CharT* chars, size_t start,
                      size_t length, MatchPairs* matches)
{
    typedef void (*RegExpCodeSignature)(InputOutputData*);

    InputOutputData data(chars, chars + length, start, matches);

    RegExpCodeSignature function = reinterpret_cast<RegExpCodeSignature>(codeBlock->raw());

    {
        JS::AutoSuppressGCAnalysis nogc;
        CALL_GENERATED_1(function, &data);
    }

    return (RegExpRunStatus) data.result;
}

template RegExpRunStatus
irregexp::ExecuteCode(JSContext* cx, jit::JitCode* codeBlock, const Latin1Char* chars, size_t start,
                      size_t length, MatchPairs* matches);

template RegExpRunStatus
irregexp::ExecuteCode(JSContext* cx, jit::JitCode* codeBlock, const char16_t* chars, size_t start,
                      size_t length, MatchPairs* matches);

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

RegExpNode*
RegExpAtom::ToNode(RegExpCompiler* compiler, RegExpNode* on_success)
{
    TextElementVector* elms =
        compiler->alloc()->newInfallible<TextElementVector>(*compiler->alloc());
    elms->append(TextElement::Atom(this));
    return compiler->alloc()->newInfallible<TextNode>(elms, on_success);
}

RegExpNode*
RegExpText::ToNode(RegExpCompiler* compiler, RegExpNode* on_success)
{
    return compiler->alloc()->newInfallible<TextNode>(&elements_, on_success);
}

RegExpNode*
RegExpCharacterClass::ToNode(RegExpCompiler* compiler, RegExpNode* on_success)
{
    return compiler->alloc()->newInfallible<TextNode>(this, on_success);
}

RegExpNode*
RegExpDisjunction::ToNode(RegExpCompiler* compiler, RegExpNode* on_success)
{
    const RegExpTreeVector& alternatives = this->alternatives();
    size_t length = alternatives.length();
    ChoiceNode* result = compiler->alloc()->newInfallible<ChoiceNode>(compiler->alloc(), length);
    for (size_t i = 0; i < length; i++) {
        GuardedAlternative alternative(alternatives[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:
    static const int kMaxExpansionFactor = 6;
    RegExpExpansionLimiter(RegExpCompiler* compiler, int factor)
      : compiler_(compiler),
        saved_expansion_factor_(compiler->current_expansion_factor()),
        ok_to_expand_(saved_expansion_factor_ <= kMaxExpansionFactor)
    {
        MOZ_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 {
                int 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_;
    int saved_expansion_factor_;
    bool ok_to_expand_;
};

/* static */ RegExpNode*
RegExpQuantifier::ToNode(int min,
                         int max,
                         bool is_greedy,
                         RegExpTree* body,
                         RegExpCompiler* compiler,
                         RegExpNode* on_success,
                         bool not_at_start /* = false */)
{
    // 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.
    static const int kMaxUnrolledMinMatches = 3;  // Unroll (foo)+ and (foo){3,}
    static const int kMaxUnrolledMaxMatches = 3;  // Unroll (foo)? and (foo){x,3}

    if (max == 0)
        return on_success;  // This can happen due to recursion.

    bool body_can_be_empty = (body->min_match() == 0);
    int body_start_reg = RegExpCompiler::kNoRegister;
    Interval capture_registers = body->CaptureRegisters();
    bool needs_capture_clearing = !capture_registers.is_empty();
    LifoAlloc* alloc = compiler->alloc();

    if (body_can_be_empty) {
        body_start_reg = compiler->AllocateRegister();
    } else if (!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()) {
                int 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 (int i = 0; i < min; i++)
                    answer = body->ToNode(compiler, answer);
                return answer;
            }
        }
        if (max <= kMaxUnrolledMaxMatches && min == 0) {
            MOZ_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 (int i = 0; i < max; i++) {
                    ChoiceNode* alternation = alloc->newInfallible<ChoiceNode>(alloc, 2);
                    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) 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;
    int reg_ctr = needs_counter
        ? compiler->AllocateRegister()
        : RegExpCompiler::kNoRegister;
    LoopChoiceNode* center = alloc->newInfallible<LoopChoiceNode>(alloc, body->min_match() == 0);
    if (not_at_start)
        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 = alloc->newInfallible<Guard>(reg_ctr, Guard::LT, max);
        body_alt.AddGuard(alloc, body_guard);
    }
    GuardedAlternative rest_alt(on_success);
    if (has_min) {
        Guard* rest_guard = alloc->newInfallible<Guard>(reg_ctr, Guard::GEQ, min);
        rest_alt.AddGuard(alloc, rest_guard);
    }
    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);
    return center;
}

RegExpNode*
RegExpAssertion::ToNode(RegExpCompiler* compiler,
                        RegExpNode* on_success)
{
    NodeInfo info;
    LifoAlloc* alloc = compiler->alloc();

    switch (assertion_type()) {
      case START_OF_LINE:
        return AssertionNode::AfterNewline(on_success);
      case START_OF_INPUT:
        return AssertionNode::AtStart(on_success);
      case BOUNDARY:
        return AssertionNode::AtBoundary(on_success);
      case NON_BOUNDARY:
        return 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.
        int stack_pointer_register = compiler->AllocateRegister();
        int position_register = compiler->AllocateRegister();
        // The ChoiceNode to distinguish between a newline and end-of-input.
        ChoiceNode* result = alloc->newInfallible<ChoiceNode>(alloc, 2);
        // Create a newline atom.
        CharacterRangeVector* newline_ranges = alloc->newInfallible<CharacterRangeVector>(*alloc);
        CharacterRange::AddClassEscape(alloc, 'n', newline_ranges);
        RegExpCharacterClass* newline_atom = alloc->newInfallible<RegExpCharacterClass>('n');
        TextNode* newline_matcher =
            alloc->newInfallible<TextNode>(newline_atom,
                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:
        MOZ_CRASH("Bad assertion type");
    }
    return on_success;
}

RegExpNode*
RegExpBackReference::ToNode(RegExpCompiler* compiler, RegExpNode* on_success)
{
    return compiler->alloc()->newInfallible<BackReferenceNode>(RegExpCapture::StartRegister(index()),
                                                               RegExpCapture::EndRegister(index()),
                                                               on_success);
}

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

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

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

    if (is_positive()) {
        RegExpNode* bodyNode =
            body()->ToNode(compiler,
                           ActionNode::PositiveSubmatchSuccess(stack_pointer_register,
                                                               position_register,
                                                               register_count,
                                                               register_start,
                                                               on_success));
        return ActionNode::BeginSubmatch(stack_pointer_register,
                                         position_register,
                                         bodyNode);
    }

    // We use a ChoiceNode for a negative lookahead because it has most of
    // the characteristics we need.  It has the body of the lookahead as its
    // first alternative and the expression after the lookahead of the second
    // alternative.  If the first alternative succeeds then the
    // NegativeSubmatchSuccess will unwind the stack including everything the
    // choice node set up and backtrack.  If the first alternative fails then
    // the second alternative is tried, which is exactly the desired result
    // for a negative lookahead.  The NegativeLookaheadChoiceNode is a special
    // ChoiceNode that knows to ignore the first exit when calculating quick
    // checks.
    LifoAlloc* alloc = compiler->alloc();

    RegExpNode* success =
        alloc->newInfallible<NegativeSubmatchSuccess>(alloc,
                                                      stack_pointer_register,
                                                      position_register,
                                                      register_count,
                                                      register_start);
    GuardedAlternative body_alt(body()->ToNode(compiler, success));

    ChoiceNode* choice_node =
        alloc->newInfallible<NegativeLookaheadChoiceNode>(alloc, body_alt, GuardedAlternative(on_success));

    return ActionNode::BeginSubmatch(stack_pointer_register,
                                     position_register,
                                     choice_node);
}

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

/* static */ RegExpNode*
RegExpCapture::ToNode(RegExpTree* body,
                      int index,
                      RegExpCompiler* compiler,
                      RegExpNode* on_success)
{
    int start_reg = RegExpCapture::StartRegister(index);
    int end_reg = RegExpCapture::EndRegister(index);
    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)
{
    const RegExpTreeVector& children = nodes();
    RegExpNode* current = on_success;
    for (int i = children.length() - 1; i >= 0; i--)
        current = children[i]->ToNode(compiler, current);
    return current;
}

// -------------------------------------------------------------------
// BoyerMooreLookahead

ContainedInLattice
irregexp::AddRange(ContainedInLattice containment,
                   const int* ranges,
                   int ranges_length,
                   Interval new_range)
{
    MOZ_ASSERT((ranges_length & 1) == 1);
    MOZ_ASSERT(ranges[ranges_length - 1] == kMaxUtf16CodeUnit + 1);
    if (containment == kLatticeUnknown) return containment;
    bool inside = false;
    int last = 0;
    for (int 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;
}

void
BoyerMoorePositionInfo::Set(int 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 (int i = 0; i < kMapSize; i++)
                map_[i] = true;
        }
        return;
    }
    for (int i = interval.from(); i <= interval.to(); i++) {
        int mod_character = (i & kMask);
        if (!map_[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 (int i = 0; i < kMapSize; i++)
            map_[i] = true;
    }
}

BoyerMooreLookahead::BoyerMooreLookahead(LifoAlloc* alloc, size_t length, RegExpCompiler* compiler)
  : length_(length), compiler_(compiler), bitmaps_(*alloc)
{
    max_char_ = MaximumCharacter(compiler->ascii());

    bitmaps_.reserve(length);
    for (size_t i = 0; i < length; i++)
        bitmaps_.append(alloc->newInfallible<BoyerMoorePositionInfo>(alloc));
}

// 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(int* from, int* to) {
  int 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 int kMaxMax = 32;
  for (int 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.
int
BoyerMooreLookahead::FindBestInterval(int max_number_of_chars, int old_biggest_points,
                                      int* from, int* to)
{
    int biggest_points = old_biggest_points;
    static const int kSize = RegExpMacroAssembler::kTableSize;
    for (int i = 0; i < length_; ) {
        while (i < length_ && Count(i) > max_number_of_chars) i++;
        if (i == length_) break;
        int remembered_from = i;
        bool union_map[kSize];
        for (int j = 0; j < kSize; j++) union_map[j] = false;
        while (i < length_ && Count(i) <= max_number_of_chars) {
            BoyerMoorePositionInfo* map = bitmaps_[i];
            for (int j = 0; j < kSize; j++) union_map[j] |= map->at(j);
            i++;
        }
        int frequency = 0;
        for (int 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_->ascii() ? remembered_from <= 4 : remembered_from <= 2));
        // Called 'probability' but it is only a rough estimate and can actually
        // be outside the 0-kSize range.
        int probability = (in_quickcheck_range ? kSize / 2 : kSize) - frequency;
        int 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.
int BoyerMooreLookahead::GetSkipTable(int min_lookahead,
                                      int max_lookahead,
                                      uint8_t* boolean_skip_table)
{
    const int kSize = RegExpMacroAssembler::kTableSize;

    const int kSkipArrayEntry = 0;
    const int kDontSkipArrayEntry = 1;

    for (int i = 0; i < kSize; i++)
        boolean_skip_table[i] = kSkipArrayEntry;
    int skip = max_lookahead + 1 - min_lookahead;

    for (int i = max_lookahead; i >= min_lookahead; i--) {
        BoyerMoorePositionInfo* map = bitmaps_[i];
        for (int j = 0; j < kSize; j++) {
            if (map->at(j))
                boolean_skip_table[j] = kDontSkipArrayEntry;
        }
    }

    return skip;
}

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

    int min_lookahead = 0;
    int max_lookahead = 0;

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

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

    int 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 false;
    }

    if (found_single_character) {
        jit::Label cont, again;
        masm->Bind(&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->JumpOrBacktrack(&again);
        masm->Bind(&cont);
        return true;
    }

    uint8_t* boolean_skip_table;
    {
        AutoEnterOOMUnsafeRegion oomUnsafe;
        boolean_skip_table = static_cast<uint8_t*>(js_malloc(kSize));
        if (!boolean_skip_table || !masm->shared->addTable(boolean_skip_table))
            oomUnsafe.crash("Table malloc");
    }

    int skip_distance = GetSkipTable(min_lookahead, max_lookahead, boolean_skip_table);
    MOZ_ASSERT(skip_distance != 0);

    jit::Label cont, again;
    masm->Bind(&again);
    masm->LoadCurrentCharacter(max_lookahead, &cont, true);
    masm->CheckBitInTable(boolean_skip_table, &cont);
    masm->AdvanceCurrentPosition(skip_distance);
    masm->JumpOrBacktrack(&again);
    masm->Bind(&cont);

    return true;
}

bool
BoyerMooreLookahead::CheckOverRecursed()
{
    JS_CHECK_RECURSION(compiler()->cx(), compiler()->SetRegExpTooBig(); return false);
    return true;
}

// -------------------------------------------------------------------
// Trace

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

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

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

int
Trace::FindAffectedRegisters(LifoAlloc* alloc, OutSet* affected_registers)
{
    int max_register = RegExpCompiler::kNoRegister;
    for (DeferredAction* action = actions_; action != nullptr; action = action->next()) {
        if (action->action_type() == ActionNode::CLEAR_CAPTURES) {
            Interval range = static_cast<DeferredClearCaptures*>(action)->range();
            for (int i = range.from(); i <= range.to(); i++)
                affected_registers->Set(alloc, i);
            if (range.to() > max_register) max_register = range.to();
        } else {
            affected_registers->Set(alloc, action->reg());
            if (action->reg() > max_register) max_register = action->reg();
        }
    }
    return max_register;
}

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

enum DeferredActionUndoType {
    DEFER_IGNORE,
    DEFER_RESTORE,
    DEFER_CLEAR
};

void
Trace::PerformDeferredActions(LifoAlloc* alloc,
                              RegExpMacroAssembler* assembler,
                              int max_register,
                              OutSet& affected_registers,
                              OutSet* registers_to_pop,
                              OutSet* registers_to_clear)
{
    // The "+1" is to avoid a push_limit of zero if stack_limit_slack() is 1.
    const int push_limit = (assembler->stack_limit_slack() + 1) / 2;

    // Count pushes performed to force a stack limit check occasionally.
    int pushes = 0;

    for (int 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).
        DeferredActionUndoType undo_action = DEFER_IGNORE;

        int value = 0;
        bool absolute = false;
        bool clear = false;
        int store_position = -1;
        // This is a little tricky because we are scanning the actions in reverse
        // historical order (newest first).
        for (DeferredAction* action = actions_;
             action != nullptr;
             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 IGNORE if we know there is no value to
                    // restore.
                    undo_action = DEFER_RESTORE;
                    MOZ_ASSERT(store_position == -1);
                    MOZ_ASSERT(!clear);
                    break;
                  }
                  case ActionNode::INCREMENT_REGISTER:
                    if (!absolute) {
                        value++;
                    }
                    MOZ_ASSERT(store_position == -1);
                    MOZ_ASSERT(!clear);
                    undo_action = DEFER_RESTORE;
                    break;
                  case ActionNode::STORE_POSITION: {
                    Trace::DeferredCapture* pc =
                        static_cast<Trace::DeferredCapture*>(action);
                    if (!clear && store_position == -1) {
                        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 = DEFER_IGNORE;
                    } else {
                        undo_action = pc->is_capture() ? DEFER_CLEAR : DEFER_RESTORE;
                    }
                    MOZ_ASSERT(!absolute);
                    MOZ_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 == -1) {
                        clear = true;
                    }
                    undo_action = DEFER_RESTORE;
                    MOZ_ASSERT(!absolute);
                    MOZ_ASSERT(value == 0);
                    break;
                  }
                  default:
                    MOZ_CRASH("Bad action");
                }
            }
        }
        // Prepare for the undo-action (e.g., push if it's going to be popped).
        if (undo_action == DEFER_RESTORE) {
            pushes++;
            RegExpMacroAssembler::StackCheckFlag stack_check =
                RegExpMacroAssembler::kNoStackLimitCheck;
            if (pushes == push_limit) {
                stack_check = RegExpMacroAssembler::kCheckStackLimit;
                pushes = 0;
            }

            assembler->PushRegister(reg, stack_check);
            registers_to_pop->Set(alloc, reg);
        } else if (undo_action == DEFER_CLEAR) {
            registers_to_clear->Set(alloc, reg);
        }
        // Perform the chronologically last action (or accumulated increment)
        // for the register.
        if (store_position != -1) {
            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();

    MOZ_ASSERT(!is_trivial());

    if (actions_ == nullptr && backtrack() == nullptr) {
        // 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() != nullptr) {
        // 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();
    }

    int max_register = FindAffectedRegisters(compiler->alloc(), &affected_registers);
    OutSet registers_to_pop;
    OutSet registers_to_clear;
    PerformDeferredActions(compiler->alloc(),
                           assembler,
                           max_register,
                           affected_registers,
                           &registers_to_pop,
                           &registers_to_clear);
    if (cp_offset_ != 0)
        assembler->AdvanceCurrentPosition(cp_offset_);

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

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

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

void
Trace::AdvanceCurrentPositionInTrace(int by, RegExpCompiler* compiler)
{
    MOZ_ASSERT(by > 0);
    // 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->ascii());
    cp_offset_ += by;
    if (cp_offset_ > RegExpMacroAssembler::kMaxCPOffset) {
        compiler->SetRegExpTooBig();
        cp_offset_ = 0;
    }
    bound_checked_up_to_ = Max(0, bound_checked_up_to_ - by);
}

void
OutSet::Set(LifoAlloc* alloc, unsigned value)
{
    if (value < kFirstLimit) {
        first_ |= (1 << value);
    } else {
        if (remaining_ == nullptr)
            remaining_ = alloc->newInfallible<RemainingVector>(*alloc);

        for (size_t i = 0; i < remaining().length(); i++) {
            if (remaining()[i] == value)
                return;
        }
        remaining().append(value);
    }
}

bool
OutSet::Get(unsigned value)
{
    if (value < kFirstLimit)
        return (first_ & (1 << value)) != 0;
    if (remaining_ == nullptr)
        return false;
    for (size_t i = 0; i < remaining().length(); i++) {
        if (remaining()[i] == value)
            return true;
    }
    return false;
}

// -------------------------------------------------------------------
// Graph emitting

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()->bound()) {
        // We are completely independent of the trace, since we ignore it,
        // so this code can be used as the generic version.
        assembler->Bind(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->ReadBacktrackStackPointerFromRegister(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()->bound()) {
        assembler->Bind(label());
    }
    switch (action_) {
    case ACCEPT:
        assembler->Succeed();
        return;
    case BACKTRACK:
        assembler->JumpOrBacktrack(trace->backtrack());
        return;
    case NEGATIVE_SUBMATCH_SUCCESS:
        // This case is handled in a different virtual method.
        MOZ_CRASH("Bad action: NEGATIVE_SUBMATCH_SUCCESS");
    }
    MOZ_CRASH("Bad action");
}

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

    jit::Label 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->ascii())
            assembler->CheckCharacterAfterAnd(0x2028, 0xfffe, &ok);
        assembler->CheckCharacter('\n', &ok);
        assembler->CheckNotCharacter('\r', new_trace.backtrack());
    }
    assembler->Bind(&ok);
    on_success->Emit(compiler, &new_trace);
}

// Check for [0-9A-Z_a-z].
static void
EmitWordCheck(RegExpMacroAssembler* assembler,
              jit::Label* word, jit::Label* 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 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 == nullptr) {
        int eats_at_least =
            Min(kMaxLookaheadForBoyerMoore, EatsAtLeast(kMaxLookaheadForBoyerMoore,
                                                        kRecursionBudget,
                                                        not_at_start));
        if (eats_at_least >= 1) {
            BoyerMooreLookahead* bm =
                alloc()->newInfallible<BoyerMooreLookahead>(alloc(), eats_at_least, compiler);
            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) {
        jit::Label before_non_word;
        jit::Label 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->Bind(&before_non_word);
        jit::Label ok;
        BacktrackIfPrevious(compiler, trace, at_boundary ? kIsNonWord : kIsWord);
        assembler->JumpOrBacktrack(&ok);

        assembler->Bind(&before_word);
        BacktrackIfPrevious(compiler, trace, at_boundary ? kIsWord : kIsNonWord);
        assembler->Bind(&ok);
    } else if (next_is_word_character == Trace::TRUE_VALUE) {
        BacktrackIfPrevious(compiler, trace, at_boundary ? kIsWord : kIsNonWord);
    } else {
        MOZ_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();

    jit::Label fall_through, dummy;

    jit::Label* non_word = backtrack_if_previous == kIsNonWord ? new_trace.backtrack() : &fall_through;
    jit::Label* 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->Bind(&fall_through);
    on_success()->Emit(compiler, &new_trace);
}

void
AssertionNode::GetQuickCheckDetails(QuickCheckDetails* details,
                                    RegExpCompiler* compiler,
                                    int 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: {
        jit::Label ok;
        assembler->CheckPosition(trace->cp_offset(), &ok);
        assembler->JumpOrBacktrack(trace->backtrack());
        assembler->Bind(&ok);
        break;
      }
      case AT_START: {
        if (trace->at_start() == Trace::FALSE_VALUE) {
            assembler->JumpOrBacktrack(trace->backtrack());
            return;
        }
        if (trace->at_start() == Trace::UNKNOWN) {
            assembler->CheckNotAtStart(trace->backtrack());
            Trace at_start_trace = *trace;
            at_start_trace.set_at_start(true);
            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, int offset)
{
    if (quick_check == nullptr)
        return false;
    if (offset >= quick_check->characters())
        return false;
    return quick_check->positions(offset)->determines_perfectly;
}

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

static void
EmitBoundaryTest(RegExpMacroAssembler* masm,
                 int border,
                 jit::Label* fall_through,
                 jit::Label* above_or_equal,
                 jit::Label* below)
{
    if (below != fall_through) {
        masm->CheckCharacterLT(border, below);
        if (above_or_equal != fall_through)
            masm->JumpOrBacktrack(above_or_equal);
    } else {
        masm->CheckCharacterGT(border - 1, above_or_equal);
    }
}

static void
EmitDoubleBoundaryTest(RegExpMacroAssembler* masm,
                       int first,
                       int last,
                       jit::Label* fall_through,
                       jit::Label* in_range,
                       jit::Label* 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->JumpOrBacktrack(out_of_range);
    }
}

typedef Vector<int, 4, LifoAllocPolicy<Infallible> > RangeBoundaryVector;

// 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,
                   RangeBoundaryVector& ranges,
                   int start_index,
                   int end_index,
                   int min_char,
                   jit::Label* fall_through,
                   jit::Label* even_label,
                   jit::Label* odd_label)
{
    static const int kSize = RegExpMacroAssembler::kTableSize;
    static const int kMask = RegExpMacroAssembler::kTableMask;

    DebugOnly<int> base = (min_char & ~kMask);

    // Assert that everything is on one kTableSize page.
    for (int i = start_index; i <= end_index; i++)
        MOZ_ASSERT((ranges[i] & ~kMask) == base);
    MOZ_ASSERT(start_index == 0 || (ranges[start_index - 1] & ~kMask) <= base);

    char templ[kSize];
    jit::Label* on_bit_set;
    jit::Label* on_bit_clear;
    int 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 (int i = 0; i < (ranges[start_index] & kMask) && i < kSize; i++)
        templ[i] = bit;
    int j = 0;
    bit ^= 1;
    for (int i = start_index; i < end_index; i++) {
        for (j = (ranges[i] & kMask); j < (ranges[i + 1] & kMask); j++) {
            templ[j] = bit;
        }
        bit ^= 1;
    }
    for (int i = j; i < kSize; i++) {
        templ[i] = bit;
    }

    // TODO(erikcorry): Cache these.
    uint8_t* ba;
    {
        AutoEnterOOMUnsafeRegion oomUnsafe;
        ba = static_cast<uint8_t*>(js_malloc(kSize));
        if (!ba || !masm->shared->addTable(ba))
            oomUnsafe.crash("Table malloc");
    }

    for (int i = 0; i < kSize; i++)
        ba[i] = templ[i];

    masm->CheckBitInTable(ba, on_bit_set);
    if (on_bit_clear != fall_through)
        masm->JumpOrBacktrack(on_bit_clear);
}

static void
CutOutRange(RegExpMacroAssembler* masm,
            RangeBoundaryVector& ranges,
            int start_index,
            int end_index,
            int cut_index,
            jit::Label* even_label,
            jit::Label* odd_label)
{
    bool odd = (((cut_index - start_index) & 1) == 1);
    jit::Label* in_range_label = odd ? odd_label : even_label;
    jit::Label dummy;
    EmitDoubleBoundaryTest(masm,
                           ranges[cut_index],
                           ranges[cut_index + 1] - 1,
                           &dummy,
                           in_range_label,
                           &dummy);
    MOZ_ASSERT(!dummy.used());
    // 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 (int j = cut_index; j > start_index; j--)
        ranges[j] = ranges[j - 1];
    for (int j = cut_index + 1; j < end_index; j++)
        ranges[j] = ranges[j + 1];
}

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

    int first = ranges[start_index];
    int last = ranges[end_index] - 1;

    *new_start_index = start_index;
    *border = (ranges[start_index] & ~kMask) + kSize;
    while (*new_start_index < end_index) {
        if (ranges[*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-ASCII
    // 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).
    int binary_chop_index = (end_index + start_index) / 2;
    // The first test ensures that we get to the code that handles the ASCII
    // range with a single not-taken branch, speeding up this important
    // character range (even non-ASCII charset-based text has spaces and
    // punctuation).
    if (*border - 1 > kMaxOneByteCharCode &&  // ASCII case.
        end_index - start_index > (*new_start_index - start_index) * 2 &&
        last - first > kSize * 2 &&
        binary_chop_index > *new_start_index &&
        ranges[binary_chop_index] >= first + 2 * kSize)
    {
        int scan_forward_for_section_border = binary_chop_index;;
        int new_border = (ranges[binary_chop_index] | kMask) + 1;

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

    MOZ_ASSERT(*new_start_index > start_index);
    *new_end_index = *new_start_index - 1;
    if (ranges[*new_end_index] == *border)
        (*new_end_index)--;
    if (*border >= ranges[end_index]) {
        *border = ranges[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 nullptr indicating backtracking.  Either label can also be
// equal to the fall_through label.
static void
GenerateBranches(RegExpMacroAssembler* masm,
                 RangeBoundaryVector& ranges,
                 int start_index,
                 int end_index,
                 char16_t min_char,
                 char16_t max_char,
                 jit::Label* fall_through,
                 jit::Label* even_label,
                 jit::Label* odd_label)
{
    int first = ranges[start_index];
    int last = ranges[end_index] - 1;

    MOZ_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 int kNoCutIndex = -1;
        int cut = kNoCutIndex;
        for (int i = start_index; i < end_index; i++) {
            if (ranges[i] == ranges[i + 1] - 1) {
                cut = i;
                break;
            }
        }
        if (cut == kNoCutIndex) cut = start_index;
        CutOutRange(masm, ranges, start_index, end_index, cut, even_label, odd_label);
        MOZ_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 int 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;
    }

    int new_start_index = 0;
    int new_end_index = 0;
    int border = 0;

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

    jit::Label handle_rest;
    jit::Label* 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;
        MOZ_ASSERT(new_end_index == end_index - 1);
    }

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

    masm->CheckCharacterGT(border - 1, above);
    jit::Label dummy;
    GenerateBranches(masm,
                     ranges,
                     start_index,
                     new_end_index,
                     min_char,
                     border - 1,
                     &dummy,
                     even_label,
                     odd_label);
    if (handle_rest.used()) {
        masm->Bind(&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(LifoAlloc* alloc,
              RegExpMacroAssembler* macro_assembler,
              RegExpCharacterClass* cc,
              bool ascii,
              jit::Label* on_failure,
              int cp_offset,
              bool check_offset,
              bool preloaded)
{
    CharacterRangeVector& ranges = cc->ranges(alloc);
    if (!CharacterRange::IsCanonical(ranges)) {
        CharacterRange::Canonicalize(ranges);
    }

    int max_char = MaximumCharacter(ascii);
    int range_count = ranges.length();

    int last_valid_range = range_count - 1;
    while (last_valid_range >= 0) {
        CharacterRange& range = ranges[last_valid_range];
        if (range.from() <= max_char) {
            break;
        }
        last_valid_range--;
    }

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

    if (last_valid_range == 0 &&
        ranges[0].IsEverything(max_char)) {
        if (cc->is_negated()) {
            macro_assembler->JumpOrBacktrack(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 (last_valid_range == 0 &&
        !cc->is_negated() &&
        ranges[0].IsEverything(max_char)) {
        // 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(alloc) &&
        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).
    RangeBoundaryVector* range_boundaries =
        alloc->newInfallible<RangeBoundaryVector>(*alloc);

    bool zeroth_entry_is_failure = !cc->is_negated();

    range_boundaries->reserve(last_valid_range);
    for (int i = 0; i <= last_valid_range; i++) {
        CharacterRange& range = ranges[i];
        if (range.from() == 0) {
            MOZ_ASSERT(i == 0);
            zeroth_entry_is_failure = !zeroth_entry_is_failure;
        } else {
            range_boundaries->append(range.from());
        }
        range_boundaries->append(range.to() + 1);
    }
    int end_index = range_boundaries->length() - 1;
    if ((*range_boundaries)[end_index] > max_char)
        end_index--;

    jit::Label 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->Bind(&fall_through);
}

typedef bool EmitCharacterFunction(RegExpCompiler* compiler,
                                   char16_t c,
                                   jit::Label* on_failure,
                                   int cp_offset,
                                   bool check,
                                   bool preloaded);

static inline bool
EmitSimpleCharacter(RegExpCompiler* compiler,
                    char16_t c,
                    jit::Label* on_failure,
                    int 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(RegExpCompiler* compiler,
                  char16_t c,
                  jit::Label* on_failure,
                  int cp_offset,
                  bool check,
                  bool preloaded)
{
    RegExpMacroAssembler* macro_assembler = compiler->macro_assembler();
    bool ascii = compiler->ascii();
    char16_t chars[kEcma262UnCanonicalizeMaxWidth];
    int length = GetCaseIndependentLetters(c, ascii, chars);
    if (length < 1) {
        // This can't match.  Must be an ASCII subject and a non-ASCII character.
        // We do not need to do anything since the ASCII 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 (ascii && c > kMaxOneByteCharCode) {
            // 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 ascii,
                          char16_t c1,
                          char16_t c2,
                          jit::Label* on_failure)
{
    char16_t char_mask = MaximumCharacter(ascii);

    MOZ_ASSERT(c1 != c2);
    if (c1 > c2) {
        char16_t tmp = c1;
        c1 = c2;
        c2 = tmp;
    }

    char16_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.
        char16_t mask = char_mask ^ exor;
        macro_assembler->CheckNotCharacterAfterAnd(c1, mask, on_failure);
        return true;
    }

    char16_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.
        char16_t mask = char_mask ^ diff;
        macro_assembler->CheckNotCharacterAfterMinusAnd(c1 - diff,
                                                        diff,
                                                        mask,
                                                        on_failure);
        return true;
    }
    return false;
}

// Only emits letters (things that have case).  Only used for case independent
// matches.
static inline bool
EmitAtomLetter(RegExpCompiler* compiler,
               char16_t c,
               jit::Label* on_failure,
               int cp_offset,
               bool check,
               bool preloaded)
{
    RegExpMacroAssembler* macro_assembler = compiler->macro_assembler();
    bool ascii = compiler->ascii();
    char16_t chars[kEcma262UnCanonicalizeMaxWidth];
    int length = GetCaseIndependentLetters(c, ascii, 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);
    jit::Label ok;
    MOZ_ASSERT(kEcma262UnCanonicalizeMaxWidth == 4);
    switch (length) {
      case 2: {
        if (ShortCutEmitCharacterPair(macro_assembler,
                                      ascii,
                                      chars[0],
                                      chars[1],
                                      on_failure)) {
        } else {
            macro_assembler->CheckCharacter(chars[0], &ok);
            macro_assembler->CheckNotCharacter(chars[1], on_failure);
            macro_assembler->Bind(&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->Bind(&ok);
        break;
      default:
        MOZ_CRASH("Bad length");
    }
    return true;
}

// 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,
                       int* checked_up_to)
{
    RegExpMacroAssembler* assembler = compiler->macro_assembler();
    bool ascii = compiler->ascii();
    jit::Label* backtrack = trace->backtrack();
    QuickCheckDetails* quick_check = trace->quick_check_performed();
    int element_count = elements().length();
    for (int i = preloaded ? 0 : element_count - 1; i >= 0; i--) {
        TextElement elm = elements()[i];
        int cp_offset = trace->cp_offset() + elm.cp_offset();
        if (elm.text_type() == TextElement::ATOM) {
            const CharacterVector& quarks = elm.atom()->data();
            for (int j = preloaded ? 0 : quarks.length() - 1; j >= 0; j--) {
                if (first_element_checked && i == 0 && j == 0) continue;
                if (DeterminedAlready(quick_check, elm.cp_offset() + j)) continue;
                EmitCharacterFunction* emit_function = nullptr;
                switch (pass) {
                  case NON_ASCII_MATCH:
                    MOZ_ASSERT(ascii);
                    if (quarks[j] > kMaxOneByteCharCode) {
                        assembler->JumpOrBacktrack(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 != nullptr) {
                    bool bound_checked = emit_function(compiler,
                                                       quarks[j],
                                                       backtrack,
                                                       cp_offset + j,
                                                       *checked_up_to < cp_offset + j,
                                                       preloaded);
                    if (bound_checked) UpdateBoundsCheck(cp_offset + j, checked_up_to);
                }
            }
        } else {
            MOZ_ASSERT(TextElement::CHAR_CLASS == elm.text_type());
            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();
                EmitCharClass(alloc(),
                              assembler,
                              cc,
                              ascii,
                              backtrack,
                              cp_offset,
                              *checked_up_to < cp_offset,
                              preloaded);
                UpdateBoundsCheck(cp_offset, checked_up_to);
            }
        }
    }
}

int
TextNode::Length()
{
    TextElement elm = elements()[elements().length() - 1];
    MOZ_ASSERT(elm.cp_offset() >= 0);
    return elm.cp_offset() + elm.length();
}

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

// 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;
    MOZ_ASSERT(limit_result == CONTINUE);

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

    if (compiler->ascii()) {
        int dummy = 0;
        TextEmitPass(compiler, NON_ASCII_MATCH, false, trace, false, &dummy);
    }

    bool first_elt_done = false;
    int 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 (int pass = kFirstRealPass; pass <= kLastPass; pass++) {
            if (!SkipPass(pass, compiler->ignore_case())) {
                TextEmitPass(compiler,
                             static_cast<TextEmitPassType>(pass),
                             true,
                             trace,
                             false,
                             &bound_checked_to);
            }
        }
        first_elt_done = true;
    }

    for (int pass = kFirstRealPass; pass <= kLastPass; pass++) {
        if (!SkipPass(pass, compiler->ignore_case())) {
            TextEmitPass(compiler,
                         static_cast<TextEmitPassType>(pass),
                         false,
                         trace,
                         first_elt_done,
                         &bound_checked_to);
        }
    }

    Trace successor_trace(*trace);
    successor_trace.set_at_start(false);
    successor_trace.AdvanceCurrentPositionInTrace(Length(), compiler);
    RecursionCheck rc(compiler);
    on_success()->Emit(compiler, &successor_trace);
}

void
LoopChoiceNode::Emit(RegExpCompiler* compiler, Trace* trace)
{
    RegExpMacroAssembler* macro_assembler = compiler->macro_assembler();
    if (trace->stop_node() == this) {
        int text_length =
            GreedyLoopTextLengthForAlternative(&alternatives()[0]);
        MOZ_ASSERT(text_length != kNodeIsTooComplexForGreedyLoops);
        // Update the counter-based backtracking info on the stack.  This is an
        // optimization for greedy loops (see below).
        MOZ_ASSERT(trace->cp_offset() == text_length);
        macro_assembler->AdvanceCurrentPosition(text_length);
        macro_assembler->JumpOrBacktrack(trace->loop_label());
        return;
    }
    MOZ_ASSERT(trace->stop_node() == nullptr);
    if (!trace->is_trivial()) {
        trace->Flush(compiler, this);
        return;
    }
    ChoiceNode::Emit(compiler, trace);
}

/* 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 JumpOrBacktrack 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 reverse our expectation and expect to match rather
 * than fail. Therefore we want the loop code to look like this (U is the
 * unwind code that steps back in the greedy loop).  The following alternatives
 * look the same as above.
 *              _____
 *             /     \
 *             V     |
 * ----------> S1    |
 *            /|     |
 *           / |S    |
 *         F/  \_____/
 *         /
 *        |<-----------
 *        |            \
 *        V             \
 *        Q2 ---> S2     \
 *        |  S   /       |
 *       F|     /        |
 *        |   F/         |
 *        |   /          |
 *        |  R           |
 *        | /            |
 *   F    VL             |
 * <------U              |
 * back   |S             |
 *        \______________/
 */

// This class is used when generating the alternatives in a choice node.  It
// records the way the alternative is being code generated.
class irregexp::AlternativeGeneration
{
  public:
    AlternativeGeneration()
      : possible_success(),
        expects_preload(false),
        after(),
        quick_check_details()
    {}

    jit::Label possible_success;
    bool expects_preload;
    jit::Label after;
    QuickCheckDetails quick_check_details;
};

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

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

RegExpNode*
TextNode::GetSuccessorOfOmnivorousTextNode(RegExpCompiler* compiler)
{
    if (elements().length() != 1)
        return nullptr;

    TextElement elm = elements()[0];
    if (elm.text_type() != TextElement::CHAR_CLASS)
        return nullptr;

    RegExpCharacterClass* node = elm.char_class();
    CharacterRangeVector& ranges = node->ranges(alloc());

    if (!CharacterRange::IsCanonical(ranges))
        CharacterRange::Canonicalize(ranges);

    if (node->is_negated())
        return ranges.length() == 0 ? on_success() : nullptr;

    if (ranges.length() != 1)
        return nullptr;

    uint32_t max_char = MaximumCharacter(compiler->ascii());
    return ranges[0].IsEverything(max_char) ? on_success() : nullptr;
}

// 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.
int
ChoiceNode::GreedyLoopTextLengthForAlternative(GuardedAlternative* alternative)
{
    int 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.
    int recursion_depth = 0;
    while (node != this) {
        if (recursion_depth++ > RegExpCompiler::kMaxRecursion) {
            return kNodeIsTooComplexForGreedyLoops;
        }
        int 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 length;
}

// 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:
    AlternativeGenerationList(LifoAlloc* alloc, size_t count)
      : alt_gens_(*alloc)
    {
        alt_gens_.reserve(count);
        for (size_t i = 0; i < count && i < kAFew; i++)
            alt_gens_.append(a_few_alt_gens_ + i);
        for (size_t i = kAFew; i < count; i++)
            alt_gens_.append(js_new<AlternativeGeneration>());
    }

    ~AlternativeGenerationList() {
        for (size_t i = kAFew; i < alt_gens_.length(); i++) {
            js_delete(alt_gens_[i]);
            alt_gens_[i] = nullptr;
        }
    }

    AlternativeGeneration* at(int i) {
        return alt_gens_[i];
    }

  private:
    static const size_t kAFew = 10;
    Vector<AlternativeGeneration*, 1, LifoAllocPolicy<Infallible> > alt_gens_;
    AlternativeGeneration a_few_alt_gens_[kAFew];
};

void
ChoiceNode::Emit(RegExpCompiler* compiler, Trace* trace)
{
    RegExpMacroAssembler* macro_assembler = compiler->macro_assembler();
    size_t choice_count = alternatives().length();
#ifdef DEBUG
    for (size_t i = 0; i < choice_count - 1; i++) {
        const GuardedAlternative& alternative = alternatives()[i];
        const GuardVector* guards = alternative.guards();
        if (guards) {
            for (size_t j = 0; j < guards->length(); j++)
                MOZ_ASSERT(!trace->mentions_reg((*guards)[j]->reg()));
        }
    }
#endif

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

    int new_flush_budget = trace->flush_budget() / choice_count;
    if (trace->flush_budget() == 0 && trace->actions() != nullptr) {
        trace->Flush(compiler, this);
        return;
    }

    RecursionCheck rc(compiler);

    Trace* current_trace = trace;

    int text_length = GreedyLoopTextLengthForAlternative(&alternatives()[0]);
    bool greedy_loop = false;
    jit::Label greedy_loop_label;
    Trace counter_backtrack_trace;
    counter_backtrack_trace.set_backtrack(&greedy_loop_label);
    if (not_at_start()) counter_backtrack_trace.set_at_start(false);

    if (choice_count > 1 && text_length != kNodeIsTooComplexForGreedyLoops) {
        // 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.
        greedy_loop = true;
        MOZ_ASSERT(trace->stop_node() == nullptr);
        macro_assembler->PushCurrentPosition();
        current_trace = &counter_backtrack_trace;
        jit::Label greedy_match_failed;
        Trace greedy_match_trace;
        if (not_at_start()) greedy_match_trace.set_at_start(false);
        greedy_match_trace.set_backtrack(&greedy_match_failed);
        jit::Label loop_label;
        macro_assembler->Bind(&loop_label);
        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->Bind(&greedy_match_failed);
    }

    jit::Label second_choice;  // For use in greedy matches.
    macro_assembler->Bind(&second_choice);

    size_t first_normal_choice = greedy_loop ? 1 : 0;

    bool not_at_start = current_trace->at_start() == Trace::FALSE_VALUE;
    const int kEatsAtLeastNotYetInitialized = -1;
    int eats_at_least = kEatsAtLeastNotYetInitialized;

    bool skip_was_emitted = false;

    if (!greedy_loop && choice_count == 2) {
        GuardedAlternative alt1 = alternatives()[1];
        if (!alt1.guards() || alt1.guards()->length() == 0) {
            RegExpNode* eats_anything_node = alt1.node();
            if (eats_anything_node->GetSuccessorOfOmnivorousTextNode(compiler) == this) {
                // 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.
                MOZ_ASSERT(trace->is_trivial());  // This is the case on LoopChoiceNodes.
                BoyerMooreLookahead* lookahead = bm_info(not_at_start);
                if (lookahead == nullptr) {
                    eats_at_least = Min(kMaxLookaheadForBoyerMoore,
                                        EatsAtLeast(kMaxLookaheadForBoyerMoore,
                                                    kRecursionBudget,
                                                    not_at_start));
                    if (eats_at_least >= 1) {
                        BoyerMooreLookahead* bm =
                            alloc()->newInfallible<BoyerMooreLookahead>(alloc(), eats_at_least, compiler);
                        GuardedAlternative alt0 = alternatives()[0];
                        alt0.node()->FillInBMInfo(0, kRecursionBudget, bm, not_at_start);
                        skip_was_emitted = bm->EmitSkipInstructions(macro_assembler);
                    }
                } else {
                    skip_was_emitted = lookahead->EmitSkipInstructions(macro_assembler);
                }
            }
        }
    }

    if (eats_at_least == kEatsAtLeastNotYetInitialized) {
        // Save some time by looking at most one machine word ahead.
        eats_at_least =
            EatsAtLeast(compiler->ascii() ? 4 : 2, kRecursionBudget, not_at_start);
    }
    int preload_characters = CalculatePreloadCharacters(compiler, eats_at_least);

    bool preload_is_current = !skip_was_emitted &&
        (current_trace->characters_preloaded() == preload_characters);
    bool preload_has_checked_bounds = preload_is_current;

    AlternativeGenerationList alt_gens(alloc(), choice_count);

    // 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.
    for (size_t i = first_normal_choice; i < choice_count; i++) {
        GuardedAlternative alternative = alternatives()[i];
        AlternativeGeneration* alt_gen = alt_gens.at(i);
        alt_gen->quick_check_details.set_characters(preload_characters);
        const GuardVector* guards = alternative.guards();
        Trace new_trace(*current_trace);
        new_trace.set_characters_preloaded(preload_is_current ?
                                           preload_characters :
                                           0);
        if (preload_has_checked_bounds) {
            new_trace.set_bound_checked_up_to(preload_characters);
        }
        new_trace.quick_check_performed()->Clear();
        if (not_at_start_) new_trace.set_at_start(Trace::FALSE_VALUE);
        alt_gen->expects_preload = preload_is_current;
        bool generate_full_check_inline = false;
        if (try_to_emit_quick_check_for_alternative(i) &&
            alternative.node()->EmitQuickCheck(compiler,
                                               &new_trace,
                                               preload_has_checked_bounds,
                                               &alt_gen->possible_success,
                                               &alt_gen->quick_check_details,
                                               i < choice_count - 1)) {
            // Quick check was generated for this choice.
            preload_is_current = true;
            preload_has_checked_bounds = true;
            // On the last choice in the ChoiceNode we generated the quick
            // check to fall through on possible success.  So now we need to
            // generate the full check inline.
            if (i == choice_count - 1) {
                macro_assembler->Bind(&alt_gen->possible_success);
                new_trace.set_quick_check_performed(&alt_gen->quick_check_details);
                new_trace.set_characters_preloaded(preload_characters);
                new_trace.set_bound_checked_up_to(preload_characters);
                generate_full_check_inline = true;
            }
        } else if (alt_gen->quick_check_details.cannot_match()) {
            if (i == choice_count - 1 && !greedy_loop) {
                macro_assembler->JumpOrBacktrack(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_normal_choice) {
                alt_gen->expects_preload = false;
                new_trace.InvalidateCurrentCharacter();
            }
            if (i < choice_count - 1) {
                new_trace.set_backtrack(&alt_gen->after);
            }
            generate_full_check_inline = true;
        }
        if (generate_full_check_inline) {
            if (new_trace.actions() != nullptr)
                new_trace.set_flush_budget(new_flush_budget);
            if (guards) {
                for (size_t j = 0; j < guards->length(); j++)
                    GenerateGuard(macro_assembler, (*guards)[j], &new_trace);
            }
            alternative.node()->Emit(compiler, &new_trace);
            preload_is_current = false;
        }
        macro_assembler->Bind(&alt_gen->after);
    }
    if (greedy_loop) {
        macro_assembler->Bind(&greedy_loop_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->JumpOrBacktrack(&second_choice);
    }

    // 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.
    for (size_t i = first_normal_choice; i < choice_count - 1; i++) {
        AlternativeGeneration* alt_gen = alt_gens.at(i);
        Trace new_trace(*current_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() != nullptr) {
            new_trace.set_flush_budget(new_flush_budget);
        }
        EmitOutOfLineContinuation(compiler,
                                  &new_trace,
                                  alternatives()[i],
                                  alt_gen,
                                  preload_characters,
                                  alt_gens.at(i + 1)->expects_preload);
    }
}

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

    RegExpMacroAssembler* macro_assembler = compiler->macro_assembler();
    macro_assembler->Bind(&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);
    const GuardVector* guards = alternative.guards();
    if (next_expects_preload) {
        jit::Label reload_current_char;
        out_of_line_trace.set_backtrack(&reload_current_char);
        if (guards) {
            for (size_t j = 0; j < guards->length(); j++)
                GenerateGuard(macro_assembler, (*guards)[j], &out_of_line_trace);
        }
        alternative.node()->Emit(compiler, &out_of_line_trace);
        macro_assembler->Bind(&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(),
                                              nullptr,
                                              false,
                                              preload_characters);
        macro_assembler->JumpOrBacktrack(&(alt_gen->after));
    } else {
        out_of_line_trace.set_backtrack(&(alt_gen->after));
        if (guards) {
            for (size_t j = 0; j < guards->length(); j++)
                GenerateGuard(macro_assembler, (*guards)[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;
    MOZ_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->WriteBacktrackStackPointerToRegister(data_.u_submatch.stack_pointer_register);
            on_success()->Emit(compiler, trace);
        }
        break;
      case EMPTY_MATCH_CHECK: {
        int start_pos_reg = data_.u_empty_match_check.start_register;
        int stored_pos = 0;
        int 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->JumpOrBacktrack(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 {
            jit::Label 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) {
                int 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->Bind(&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->ReadBacktrackStackPointerFromRegister(data_.u_submatch.stack_pointer_register);
        int clear_register_count = data_.u_submatch.clear_register_count;
        if (clear_register_count == 0) {
            on_success()->Emit(compiler, trace);
            return;
        }
        int clear_registers_from = data_.u_submatch.clear_register_from;
        jit::Label clear_registers_backtrack;
        Trace new_trace = *trace;
        new_trace.set_backtrack(&clear_registers_backtrack);
        on_success()->Emit(compiler, &new_trace);

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

        MOZ_ASSERT(trace->backtrack() == nullptr);
        assembler->Backtrack();
        return;
      }
      default:
        MOZ_CRASH("Bad action");
    }
}

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;
    MOZ_ASSERT(limit_result == CONTINUE);

    RecursionCheck rc(compiler);

    MOZ_ASSERT(start_reg_ + 1 == end_reg_);
    if (compiler->ignore_case()) {
        assembler->CheckNotBackReferenceIgnoreCase(start_reg_,
                                                   trace->backtrack());
    } else {
        assembler->CheckNotBackReference(start_reg_, trace->backtrack());
    }
    on_success()->Emit(compiler, trace);
}

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() != nullptr)
        return CONTINUE;

    RegExpMacroAssembler* macro_assembler = compiler->macro_assembler();
    if (trace->is_trivial()) {
        if (label()->bound()) {
            // We are being asked to generate a generic version, but that's already
            // been done so just go to it.
            macro_assembler->JumpOrBacktrack(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->JumpOrBacktrack(label());
            return DONE;
        }
        // Generate generic version of the node and bind the label for later use.
        macro_assembler->Bind(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 (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;
}

bool
RegExpNode::EmitQuickCheck(RegExpCompiler* compiler,
                           Trace* trace,
                           bool preload_has_checked_bounds,
                           jit::Label* 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->ascii())) return false;
    MOZ_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()) {
        assembler->LoadCurrentCharacter(trace->cp_offset(),
                                        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 = MaximumCharacter(compiler->ascii());
        if ((mask & char_mask) == char_mask) need_mask = false;
        mask &= char_mask;
    } else {
        // For 2-character preloads in ASCII mode or 1-character preloads in
        // TWO_BYTE mode we also use a 16 bit load with zero extend.
        if (details->characters() == 2 && compiler->ascii()) {
            if ((mask & 0xffff) == 0xffff) need_mask = false;
        } else if (details->characters() == 1 && !compiler->ascii()) {
            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;
}

bool
TextNode::FillInBMInfo(int initial_offset,
                       int budget,
                       BoyerMooreLookahead* bm,
                       bool not_at_start)
{
    if (!bm->CheckOverRecursed())
        return false;

    if (initial_offset >= bm->length())
        return true;

    int offset = initial_offset;
    int max_char = bm->max_char();
    for (size_t i = 0; i < elements().length(); i++) {
        if (offset >= bm->length()) {
            if (initial_offset == 0)
                set_bm_info(not_at_start, bm);
            return true;
        }
        TextElement text = elements()[i];
        if (text.text_type() == TextElement::ATOM) {
            RegExpAtom* atom = text.atom();
            for (int j = 0; j < atom->length(); j++, offset++) {
                if (offset >= bm->length()) {
                    if (initial_offset == 0)
                        set_bm_info(not_at_start, bm);
                    return true;
                }
                char16_t character = atom->data()[j];
                if (bm->compiler()->ignore_case()) {
                    char16_t chars[kEcma262UnCanonicalizeMaxWidth];
                    int length = GetCaseIndependentLetters(character,
                                                           bm->max_char() == kMaxOneByteCharCode,
                                                           chars);
                    for (int j = 0; j < length; j++)
                        bm->Set(offset, chars[j]);
                } else {
                    if (character <= max_char) bm->Set(offset, character);
                }
            }
        } else {
            MOZ_ASSERT(TextElement::CHAR_CLASS == text.text_type());
            RegExpCharacterClass* char_class = text.char_class();
            const CharacterRangeVector& ranges = char_class->ranges(alloc());
            if (char_class->is_negated()) {
                bm->SetAll(offset);
            } else {
                for (size_t k = 0; k < ranges.length(); k++) {
                    const CharacterRange& range = ranges[k];
                    if (range.from() > max_char)
                        continue;
                    int to = Min(max_char, static_cast<int>(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 true;
    }
    if (!on_success()->FillInBMInfo(offset,
                                    budget - 1,
                                    bm,
                                    true))   // Not at start after a text node.
        return false;
    if (initial_offset == 0)
        set_bm_info(not_at_start, bm);
    return true;
}

// -------------------------------------------------------------------
// QuickCheckDetails

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

// 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,
                               int characters_filled_in,
                               bool not_at_start)
{
    MOZ_ASSERT(characters_filled_in < details->characters());
    int characters = details->characters();
    int char_mask = MaximumCharacter(compiler->ascii());

    for (size_t k = 0; k < elements().length(); k++) {
        TextElement elm = elements()[k];
        if (elm.text_type() == TextElement::ATOM) {
            const CharacterVector& quarks = elm.atom()->data();
            for (size_t i = 0; i < (size_t) characters && i < quarks.length(); i++) {
                QuickCheckDetails::Position* pos =
                    details->positions(characters_filled_in);
                char16_t c = quarks[i];
                if (c > char_mask) {
                    // If we expect a non-ASCII character from an ASCII string,
                    // there is no way we can match. Not even case independent
                    // matching can turn an ASCII character into non-ASCII or
                    // vice versa.
                    details->set_cannot_match();
                    pos->determines_perfectly = false;
                    return;
                }
                if (compiler->ignore_case()) {
                    char16_t chars[kEcma262UnCanonicalizeMaxWidth];
                    size_t length = GetCaseIndependentLetters(c, compiler->ascii(), chars);
                    MOZ_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 (size_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++;
                MOZ_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();
            const CharacterRangeVector& ranges = tree->ranges(alloc());
            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 {
                size_t first_range = 0;
                while (ranges[first_range].from() > char_mask) {
                    first_range++;
                    if (first_range == ranges.length()) {
                        details->set_cannot_match();
                        pos->determines_perfectly = false;
                        return;
                    }
                }
                CharacterRange range = ranges[first_range];
                char16_t from = range.from();
                char16_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 (size_t i = first_range + 1; i < ranges.length(); i++) {
                    CharacterRange range = ranges[i];
                    char16_t from = range.from();
                    char16_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++;
            MOZ_ASSERT(characters_filled_in <= details->characters());
            if (characters_filled_in == details->characters()) {
                return;
            }
        }
    }
    MOZ_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(int by, bool ascii)
{
    MOZ_ASSERT(by >= 0);
    if (by >= characters_) {
        Clear();
        return;
    }
    for (int i = 0; i < characters_ - by; i++) {
        positions_[i] = positions_[by + i];
    }
    for (int 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.
}

bool
QuickCheckDetails::Rationalize(bool is_ascii)
{
    bool found_useful_op = false;
    uint32_t char_mask = MaximumCharacter(is_ascii);

    mask_ = 0;
    value_ = 0;
    int char_shift = 0;
    for (int i = 0; i < characters_; i++) {
        Position* pos = &positions_[i];
        if ((pos->mask & kMaxOneByteCharCode) != 0)
            found_useful_op = true;
        mask_ |= (pos->mask & char_mask) << char_shift;
        value_ |= (pos->value & char_mask) << char_shift;
        char_shift += is_ascii ? 8 : 16;
    }
    return found_useful_op;
}

void QuickCheckDetails::Merge(QuickCheckDetails* other, int from_index)
{
    MOZ_ASSERT(characters_ == other->characters_);
    if (other->cannot_match_)
        return;
    if (cannot_match_) {
        *this = *other;
        return;
    }
    for (int 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;
        char16_t differing_bits = (pos->value ^ other_pos->value);
        pos->mask &= ~differing_bits;
        pos->value &= pos->mask;
    }
}
