| Index: src/regexp/jsregexp.cc
 | 
| diff --git a/src/regexp/jsregexp.cc b/src/regexp/jsregexp.cc
 | 
| index 7b510b072b0bba0d6e66726397213c52ead70a9f..654afa9a89e06495f4a070c439004c074f6f12e0 100644
 | 
| --- a/src/regexp/jsregexp.cc
 | 
| +++ b/src/regexp/jsregexp.cc
 | 
| @@ -1598,19 +1598,34 @@ void ChoiceNode::GenerateGuard(RegExpMacroAssembler* macro_assembler,
 | 
|  
 | 
|  // Returns the number of characters in the equivalence class, omitting those
 | 
|  // that cannot occur in the source string because it is Latin1.
 | 
| -static int GetCaseIndependentLetters(Isolate* isolate, uc16 character,
 | 
| -                                     bool one_byte_subject,
 | 
| -                                     unibrow::uchar* letters) {
 | 
| -  int length =
 | 
| -      isolate->jsregexp_uncanonicalize()->get(character, '\0', letters);
 | 
| -  // Unibrow returns 0 or 1 for characters where case independence is
 | 
| -  // trivial.
 | 
| -  if (length == 0) {
 | 
| -    letters[0] = character;
 | 
| -    length = 1;
 | 
| -  }
 | 
| -
 | 
| -  if (one_byte_subject) {
 | 
| +static int GetCaseIndependentLetters(RegExpCompiler* compiler, uc16 character,
 | 
| +                                     uc32* letters) {
 | 
| +  int length;
 | 
| +#ifdef V8_I18N_SUPPORT
 | 
| +  if (compiler->unicode()) {
 | 
| +    USet* set = uset_open(character, character);
 | 
| +    uset_closeOver(set, USET_CASE_INSENSITIVE);
 | 
| +    uset_removeAllStrings(set);
 | 
| +    length = uset_size(set);
 | 
| +    for (int i = 0; i < length; i++) {
 | 
| +      letters[i] = uset_charAt(set, i);
 | 
| +    }
 | 
| +    uset_close(set);
 | 
| +  } else  // NOLINT
 | 
| +// Fallback in case ICU is not included.
 | 
| +#endif  // V8_I18N_SUPPORT
 | 
| +  {
 | 
| +    length = compiler->isolate()->jsregexp_uncanonicalize()->get(character,
 | 
| +                                                                 '\0', letters);
 | 
| +    // Unibrow returns 0 or 1 for characters where case independence is
 | 
| +    // trivial.
 | 
| +    if (length == 0) {
 | 
| +      letters[0] = character;
 | 
| +      length = 1;
 | 
| +    }
 | 
| +  }
 | 
| +
 | 
| +  if (compiler->one_byte()) {
 | 
|      int new_length = 0;
 | 
|      for (int i = 0; i < length; i++) {
 | 
|        if (letters[i] <= String::kMaxOneByteCharCode) {
 | 
| @@ -1623,14 +1638,9 @@ static int GetCaseIndependentLetters(Isolate* isolate, uc16 character,
 | 
|    return length;
 | 
|  }
 | 
|  
 | 
| -
 | 
| -static inline bool EmitSimpleCharacter(Isolate* isolate,
 | 
| -                                       RegExpCompiler* compiler,
 | 
| -                                       uc16 c,
 | 
| -                                       Label* on_failure,
 | 
| -                                       int cp_offset,
 | 
| -                                       bool check,
 | 
| -                                       bool preloaded) {
 | 
| +static inline bool EmitSimpleCharacter(RegExpCompiler* compiler, uc16 c,
 | 
| +                                       Label* on_failure, int cp_offset,
 | 
| +                                       bool check, bool preloaded) {
 | 
|    RegExpMacroAssembler* assembler = compiler->macro_assembler();
 | 
|    bool bound_checked = false;
 | 
|    if (!preloaded) {
 | 
| @@ -1647,17 +1657,12 @@ static inline bool EmitSimpleCharacter(Isolate* isolate,
 | 
|  
 | 
|  // Only emits non-letters (things that don't have case).  Only used for case
 | 
|  // independent matches.
 | 
| -static inline bool EmitAtomNonLetter(Isolate* isolate,
 | 
| -                                     RegExpCompiler* compiler,
 | 
| -                                     uc16 c,
 | 
| -                                     Label* on_failure,
 | 
| -                                     int cp_offset,
 | 
| -                                     bool check,
 | 
| -                                     bool preloaded) {
 | 
| +static inline bool EmitAtomNonLetter(RegExpCompiler* compiler, uc16 c,
 | 
| +                                     Label* on_failure, int cp_offset,
 | 
| +                                     bool check, bool preloaded) {
 | 
|    RegExpMacroAssembler* macro_assembler = compiler->macro_assembler();
 | 
| -  bool one_byte = compiler->one_byte();
 | 
|    unibrow::uchar chars[unibrow::Ecma262UnCanonicalize::kMaxWidth];
 | 
| -  int length = GetCaseIndependentLetters(isolate, c, one_byte, chars);
 | 
| +  int length = GetCaseIndependentLetters(compiler, c, chars);
 | 
|    if (length < 1) {
 | 
|      // This can't match.  Must be an one-byte subject and a non-one-byte
 | 
|      // character.  We do not need to do anything since the one-byte pass
 | 
| @@ -1667,8 +1672,8 @@ static inline bool EmitAtomNonLetter(Isolate* isolate,
 | 
|    bool checked = false;
 | 
|    // We handle the length > 1 case in a later pass.
 | 
|    if (length == 1) {
 | 
| -    if (one_byte && c > String::kMaxOneByteCharCodeU) {
 | 
| -      // Can't match - see above.
 | 
| +    if (compiler->one_byte() && c > String::kMaxOneByteCharCodeU) {
 | 
| +      // This cannot match.
 | 
|        return false;  // Bounds not checked.
 | 
|      }
 | 
|      if (!preloaded) {
 | 
| @@ -1717,28 +1722,18 @@ static bool ShortCutEmitCharacterPair(RegExpMacroAssembler* macro_assembler,
 | 
|    return false;
 | 
|  }
 | 
|  
 | 
| -
 | 
| -typedef bool EmitCharacterFunction(Isolate* isolate,
 | 
| -                                   RegExpCompiler* compiler,
 | 
| -                                   uc16 c,
 | 
| -                                   Label* on_failure,
 | 
| -                                   int cp_offset,
 | 
| -                                   bool check,
 | 
| +typedef bool EmitCharacterFunction(RegExpCompiler* compiler, uc16 c,
 | 
| +                                   Label* on_failure, int cp_offset, bool check,
 | 
|                                     bool preloaded);
 | 
|  
 | 
|  // Only emits letters (things that have case).  Only used for case independent
 | 
|  // matches.
 | 
| -static inline bool EmitAtomLetter(Isolate* isolate,
 | 
| -                                  RegExpCompiler* compiler,
 | 
| -                                  uc16 c,
 | 
| -                                  Label* on_failure,
 | 
| -                                  int cp_offset,
 | 
| -                                  bool check,
 | 
| +static inline bool EmitAtomLetter(RegExpCompiler* compiler, uc16 c,
 | 
| +                                  Label* on_failure, int cp_offset, bool check,
 | 
|                                    bool preloaded) {
 | 
|    RegExpMacroAssembler* macro_assembler = compiler->macro_assembler();
 | 
| -  bool one_byte = compiler->one_byte();
 | 
|    unibrow::uchar chars[unibrow::Ecma262UnCanonicalize::kMaxWidth];
 | 
| -  int length = GetCaseIndependentLetters(isolate, c, one_byte, chars);
 | 
| +  int length = GetCaseIndependentLetters(compiler, c, 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.
 | 
| @@ -1749,8 +1744,8 @@ static inline bool EmitAtomLetter(Isolate* isolate,
 | 
|    DCHECK(unibrow::Ecma262UnCanonicalize::kMaxWidth == 4);
 | 
|    switch (length) {
 | 
|      case 2: {
 | 
| -      if (ShortCutEmitCharacterPair(macro_assembler, one_byte, chars[0],
 | 
| -                                    chars[1], on_failure)) {
 | 
| +      if (ShortCutEmitCharacterPair(macro_assembler, compiler->one_byte(),
 | 
| +                                    chars[0], chars[1], on_failure)) {
 | 
|        } else {
 | 
|          macro_assembler->CheckCharacter(chars[0], &ok);
 | 
|          macro_assembler->CheckNotCharacter(chars[1], on_failure);
 | 
| @@ -2287,13 +2282,12 @@ int ActionNode::EatsAtLeast(int still_to_find,
 | 
|                                     not_at_start);
 | 
|  }
 | 
|  
 | 
| -
 | 
| -void ActionNode::FillInBMInfo(Isolate* isolate, int offset, int budget,
 | 
| +void ActionNode::FillInBMInfo(RegExpCompiler* compiler, int offset, int budget,
 | 
|                                BoyerMooreLookahead* bm, bool not_at_start) {
 | 
|    if (action_type_ == BEGIN_SUBMATCH) {
 | 
|      bm->SetRest(offset);
 | 
|    } else if (action_type_ != POSITIVE_SUBMATCH_SUCCESS) {
 | 
| -    on_success()->FillInBMInfo(isolate, offset, budget - 1, bm, not_at_start);
 | 
| +    on_success()->FillInBMInfo(compiler, offset, budget - 1, bm, not_at_start);
 | 
|    }
 | 
|    SaveBMInfo(bm, not_at_start, offset);
 | 
|  }
 | 
| @@ -2314,12 +2308,12 @@ int AssertionNode::EatsAtLeast(int still_to_find,
 | 
|                                     not_at_start);
 | 
|  }
 | 
|  
 | 
| -
 | 
| -void AssertionNode::FillInBMInfo(Isolate* isolate, int offset, int budget,
 | 
| -                                 BoyerMooreLookahead* bm, bool not_at_start) {
 | 
| +void AssertionNode::FillInBMInfo(RegExpCompiler* compiler, int offset,
 | 
| +                                 int budget, BoyerMooreLookahead* bm,
 | 
| +                                 bool not_at_start) {
 | 
|    // Match the behaviour of EatsAtLeast on this node.
 | 
|    if (assertion_type() == AT_START && not_at_start) return;
 | 
| -  on_success()->FillInBMInfo(isolate, offset, budget - 1, bm, not_at_start);
 | 
| +  on_success()->FillInBMInfo(compiler, offset, budget - 1, bm, not_at_start);
 | 
|    SaveBMInfo(bm, not_at_start, offset);
 | 
|  }
 | 
|  
 | 
| @@ -2533,7 +2527,6 @@ void TextNode::GetQuickCheckDetails(QuickCheckDetails* details,
 | 
|    // Do not collect any quick check details if the text node reads backward,
 | 
|    // since it reads in the opposite direction than we use for quick checks.
 | 
|    if (read_backward()) return;
 | 
| -  Isolate* isolate = compiler->macro_assembler()->isolate();
 | 
|    DCHECK(characters_filled_in < details->characters());
 | 
|    int characters = details->characters();
 | 
|    int char_mask;
 | 
| @@ -2552,8 +2545,7 @@ void TextNode::GetQuickCheckDetails(QuickCheckDetails* details,
 | 
|          uc16 c = quarks[i];
 | 
|          if (compiler->ignore_case()) {
 | 
|            unibrow::uchar chars[unibrow::Ecma262UnCanonicalize::kMaxWidth];
 | 
| -          int length = GetCaseIndependentLetters(isolate, c,
 | 
| -                                                 compiler->one_byte(), chars);
 | 
| +          int length = GetCaseIndependentLetters(compiler, c, chars);
 | 
|            if (length == 0) {
 | 
|              // This can happen because all case variants are non-Latin1, but we
 | 
|              // know the input is Latin1.
 | 
| @@ -2758,18 +2750,17 @@ class VisitMarker {
 | 
|    NodeInfo* info_;
 | 
|  };
 | 
|  
 | 
| -
 | 
| -RegExpNode* SeqRegExpNode::FilterOneByte(int depth, bool ignore_case) {
 | 
| +RegExpNode* SeqRegExpNode::FilterOneByte(int depth, RegExpCompiler* compiler) {
 | 
|    if (info()->replacement_calculated) return replacement();
 | 
|    if (depth < 0) return this;
 | 
|    DCHECK(!info()->visited);
 | 
|    VisitMarker marker(info());
 | 
| -  return FilterSuccessor(depth - 1, ignore_case);
 | 
| +  return FilterSuccessor(depth - 1, compiler);
 | 
|  }
 | 
|  
 | 
| -
 | 
| -RegExpNode* SeqRegExpNode::FilterSuccessor(int depth, bool ignore_case) {
 | 
| -  RegExpNode* next = on_success_->FilterOneByte(depth - 1, ignore_case);
 | 
| +RegExpNode* SeqRegExpNode::FilterSuccessor(int depth,
 | 
| +                                           RegExpCompiler* compiler) {
 | 
| +  RegExpNode* next = on_success_->FilterOneByte(depth - 1, compiler);
 | 
|    if (next == NULL) return set_replacement(NULL);
 | 
|    on_success_ = next;
 | 
|    return set_replacement(this);
 | 
| @@ -2792,8 +2783,30 @@ static bool RangesContainLatin1Equivalents(ZoneList<CharacterRange>* ranges) {
 | 
|    return false;
 | 
|  }
 | 
|  
 | 
| +static uc16 ConvertNonLatin1ToEquivalentLatin1(bool unicode, uc16 c) {
 | 
| +#ifdef V8_I18N_SUPPORT
 | 
| +  if (unicode) {
 | 
| +    USet* set = uset_open(c, c);
 | 
| +    uset_closeOver(set, USET_CASE_INSENSITIVE);
 | 
| +    uset_removeAllStrings(set);
 | 
| +    int length = uset_size(set);
 | 
| +    uc16 result = 0;
 | 
| +    for (int i = 0; i < length; i++) {
 | 
| +      uc32 c = uset_charAt(set, i);
 | 
| +      if (c <= String::kMaxOneByteCharCode) {
 | 
| +        result = static_cast<uc16>(c);
 | 
| +        break;
 | 
| +      }
 | 
| +    }
 | 
| +    uset_close(set);
 | 
| +    return result;
 | 
| +  }
 | 
| +// Fallback to unibrow if ICU is not included.
 | 
| +#endif  // V8_I18N_SUPPORT
 | 
| +  return unibrow::Latin1::ConvertNonLatin1ToLatin1(c);
 | 
| +}
 | 
|  
 | 
| -RegExpNode* TextNode::FilterOneByte(int depth, bool ignore_case) {
 | 
| +RegExpNode* TextNode::FilterOneByte(int depth, RegExpCompiler* compiler) {
 | 
|    if (info()->replacement_calculated) return replacement();
 | 
|    if (depth < 0) return this;
 | 
|    DCHECK(!info()->visited);
 | 
| @@ -2804,16 +2817,17 @@ RegExpNode* TextNode::FilterOneByte(int depth, bool ignore_case) {
 | 
|      if (elm.text_type() == TextElement::ATOM) {
 | 
|        Vector<const uc16> quarks = elm.atom()->data();
 | 
|        for (int j = 0; j < quarks.length(); j++) {
 | 
| -        uint16_t c = quarks[j];
 | 
| +        uc16 c = quarks[j];
 | 
|          if (c <= String::kMaxOneByteCharCode) continue;
 | 
| -        if (!ignore_case) return set_replacement(NULL);
 | 
| +        if (!compiler->ignore_case()) return set_replacement(NULL);
 | 
|          // Here, we need to check for characters whose upper and lower cases
 | 
|          // are outside the Latin-1 range.
 | 
| -        uint16_t converted = unibrow::Latin1::ConvertNonLatin1ToLatin1(c);
 | 
| +        uc16 converted =
 | 
| +            ConvertNonLatin1ToEquivalentLatin1(compiler->unicode(), c);
 | 
|          // Character is outside Latin-1 completely
 | 
|          if (converted == 0) return set_replacement(NULL);
 | 
|          // Convert quark to Latin-1 in place.
 | 
| -        uint16_t* copy = const_cast<uint16_t*>(quarks.start());
 | 
| +        uc16* copy = const_cast<uc16*>(quarks.start());
 | 
|          copy[j] = converted;
 | 
|        }
 | 
|      } else {
 | 
| @@ -2828,24 +2842,25 @@ RegExpNode* TextNode::FilterOneByte(int depth, bool ignore_case) {
 | 
|              ranges->at(0).from() == 0 &&
 | 
|              ranges->at(0).to() >= String::kMaxOneByteCharCode) {
 | 
|            // This will be handled in a later filter.
 | 
| -          if (ignore_case && RangesContainLatin1Equivalents(ranges)) continue;
 | 
| +          if (compiler->ignore_case() && RangesContainLatin1Equivalents(ranges))
 | 
| +            continue;
 | 
|            return set_replacement(NULL);
 | 
|          }
 | 
|        } else {
 | 
|          if (range_count == 0 ||
 | 
|              ranges->at(0).from() > String::kMaxOneByteCharCode) {
 | 
|            // This will be handled in a later filter.
 | 
| -          if (ignore_case && RangesContainLatin1Equivalents(ranges)) continue;
 | 
| +          if (compiler->ignore_case() && RangesContainLatin1Equivalents(ranges))
 | 
| +            continue;
 | 
|            return set_replacement(NULL);
 | 
|          }
 | 
|        }
 | 
|      }
 | 
|    }
 | 
| -  return FilterSuccessor(depth - 1, ignore_case);
 | 
| +  return FilterSuccessor(depth - 1, compiler);
 | 
|  }
 | 
|  
 | 
| -
 | 
| -RegExpNode* LoopChoiceNode::FilterOneByte(int depth, bool ignore_case) {
 | 
| +RegExpNode* LoopChoiceNode::FilterOneByte(int depth, RegExpCompiler* compiler) {
 | 
|    if (info()->replacement_calculated) return replacement();
 | 
|    if (depth < 0) return this;
 | 
|    if (info()->visited) return this;
 | 
| @@ -2853,17 +2868,16 @@ RegExpNode* LoopChoiceNode::FilterOneByte(int depth, bool ignore_case) {
 | 
|      VisitMarker marker(info());
 | 
|  
 | 
|      RegExpNode* continue_replacement =
 | 
| -        continue_node_->FilterOneByte(depth - 1, ignore_case);
 | 
| +        continue_node_->FilterOneByte(depth - 1, compiler);
 | 
|      // If we can't continue after the loop then there is no sense in doing the
 | 
|      // loop.
 | 
|      if (continue_replacement == NULL) return set_replacement(NULL);
 | 
|    }
 | 
|  
 | 
| -  return ChoiceNode::FilterOneByte(depth - 1, ignore_case);
 | 
| +  return ChoiceNode::FilterOneByte(depth - 1, compiler);
 | 
|  }
 | 
|  
 | 
| -
 | 
| -RegExpNode* ChoiceNode::FilterOneByte(int depth, bool ignore_case) {
 | 
| +RegExpNode* ChoiceNode::FilterOneByte(int depth, RegExpCompiler* compiler) {
 | 
|    if (info()->replacement_calculated) return replacement();
 | 
|    if (depth < 0) return this;
 | 
|    if (info()->visited) return this;
 | 
| @@ -2883,7 +2897,7 @@ RegExpNode* ChoiceNode::FilterOneByte(int depth, bool ignore_case) {
 | 
|    for (int i = 0; i < choice_count; i++) {
 | 
|      GuardedAlternative alternative = alternatives_->at(i);
 | 
|      RegExpNode* replacement =
 | 
| -        alternative.node()->FilterOneByte(depth - 1, ignore_case);
 | 
| +        alternative.node()->FilterOneByte(depth - 1, compiler);
 | 
|      DCHECK(replacement != this);  // No missing EMPTY_MATCH_CHECK.
 | 
|      if (replacement != NULL) {
 | 
|        alternatives_->at(i).set_node(replacement);
 | 
| @@ -2903,7 +2917,7 @@ RegExpNode* ChoiceNode::FilterOneByte(int depth, bool ignore_case) {
 | 
|        new(zone()) ZoneList<GuardedAlternative>(surviving, zone());
 | 
|    for (int i = 0; i < choice_count; i++) {
 | 
|      RegExpNode* replacement =
 | 
| -        alternatives_->at(i).node()->FilterOneByte(depth - 1, ignore_case);
 | 
| +        alternatives_->at(i).node()->FilterOneByte(depth - 1, compiler);
 | 
|      if (replacement != NULL) {
 | 
|        alternatives_->at(i).set_node(replacement);
 | 
|        new_alternatives->Add(alternatives_->at(i), zone());
 | 
| @@ -2913,9 +2927,8 @@ RegExpNode* ChoiceNode::FilterOneByte(int depth, bool ignore_case) {
 | 
|    return this;
 | 
|  }
 | 
|  
 | 
| -
 | 
| -RegExpNode* NegativeLookaroundChoiceNode::FilterOneByte(int depth,
 | 
| -                                                        bool ignore_case) {
 | 
| +RegExpNode* NegativeLookaroundChoiceNode::FilterOneByte(
 | 
| +    int depth, RegExpCompiler* compiler) {
 | 
|    if (info()->replacement_calculated) return replacement();
 | 
|    if (depth < 0) return this;
 | 
|    if (info()->visited) return this;
 | 
| @@ -2923,12 +2936,12 @@ RegExpNode* NegativeLookaroundChoiceNode::FilterOneByte(int depth,
 | 
|    // Alternative 0 is the negative lookahead, alternative 1 is what comes
 | 
|    // afterwards.
 | 
|    RegExpNode* node = alternatives_->at(1).node();
 | 
| -  RegExpNode* replacement = node->FilterOneByte(depth - 1, ignore_case);
 | 
| +  RegExpNode* replacement = node->FilterOneByte(depth - 1, compiler);
 | 
|    if (replacement == NULL) return set_replacement(NULL);
 | 
|    alternatives_->at(1).set_node(replacement);
 | 
|  
 | 
|    RegExpNode* neg_node = alternatives_->at(0).node();
 | 
| -  RegExpNode* neg_replacement = neg_node->FilterOneByte(depth - 1, ignore_case);
 | 
| +  RegExpNode* neg_replacement = neg_node->FilterOneByte(depth - 1, compiler);
 | 
|    // If the negative lookahead is always going to fail then
 | 
|    // we don't need to check it.
 | 
|    if (neg_replacement == NULL) return set_replacement(replacement);
 | 
| @@ -2949,15 +2962,15 @@ void LoopChoiceNode::GetQuickCheckDetails(QuickCheckDetails* details,
 | 
|                                            not_at_start);
 | 
|  }
 | 
|  
 | 
| -
 | 
| -void LoopChoiceNode::FillInBMInfo(Isolate* isolate, int offset, int budget,
 | 
| -                                  BoyerMooreLookahead* bm, bool not_at_start) {
 | 
| +void LoopChoiceNode::FillInBMInfo(RegExpCompiler* compiler, 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;
 | 
|    }
 | 
| -  ChoiceNode::FillInBMInfo(isolate, offset, budget - 1, bm, not_at_start);
 | 
| +  ChoiceNode::FillInBMInfo(compiler, offset, budget - 1, bm, not_at_start);
 | 
|    SaveBMInfo(bm, not_at_start, offset);
 | 
|  }
 | 
|  
 | 
| @@ -3049,7 +3062,6 @@ static void EmitHat(RegExpCompiler* compiler,
 | 
|  // 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();
 | 
| -  Isolate* isolate = assembler->isolate();
 | 
|    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);
 | 
| @@ -3061,7 +3073,7 @@ void AssertionNode::EmitBoundaryCheck(RegExpCompiler* compiler, Trace* trace) {
 | 
|      if (eats_at_least >= 1) {
 | 
|        BoyerMooreLookahead* bm =
 | 
|            new(zone()) BoyerMooreLookahead(eats_at_least, compiler, zone());
 | 
| -      FillInBMInfo(isolate, 0, kRecursionBudget, bm, not_at_start);
 | 
| +      FillInBMInfo(compiler, 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;
 | 
| @@ -3233,7 +3245,6 @@ void TextNode::TextEmitPass(RegExpCompiler* compiler,
 | 
|                              bool first_element_checked,
 | 
|                              int* checked_up_to) {
 | 
|    RegExpMacroAssembler* assembler = compiler->macro_assembler();
 | 
| -  Isolate* isolate = assembler->isolate();
 | 
|    bool one_byte = compiler->one_byte();
 | 
|    Label* backtrack = trace->backtrack();
 | 
|    QuickCheckDetails* quick_check = trace->quick_check_performed();
 | 
| @@ -3251,6 +3262,7 @@ void TextNode::TextEmitPass(RegExpCompiler* compiler,
 | 
|          switch (pass) {
 | 
|            case NON_LATIN1_MATCH:
 | 
|              DCHECK(one_byte);
 | 
| +            DCHECK(!(compiler->unicode() && compiler->ignore_case()));
 | 
|              if (quarks[j] > String::kMaxOneByteCharCode) {
 | 
|                assembler->GoTo(backtrack);
 | 
|                return;
 | 
| @@ -3271,8 +3283,8 @@ void TextNode::TextEmitPass(RegExpCompiler* compiler,
 | 
|          if (emit_function != NULL) {
 | 
|            bool bounds_check = *checked_up_to < cp_offset + j || read_backward();
 | 
|            bool bound_checked =
 | 
| -              emit_function(isolate, compiler, quarks[j], backtrack,
 | 
| -                            cp_offset + j, bounds_check, preloaded);
 | 
| +              emit_function(compiler, quarks[j], backtrack, cp_offset + j,
 | 
| +                            bounds_check, preloaded);
 | 
|            if (bound_checked) UpdateBoundsCheck(cp_offset + j, checked_up_to);
 | 
|          }
 | 
|        }
 | 
| @@ -3355,7 +3367,13 @@ void TextNode::Emit(RegExpCompiler* compiler, Trace* trace) {
 | 
|      return;
 | 
|    }
 | 
|  
 | 
| -  if (compiler->one_byte()) {
 | 
| +  if (compiler->one_byte() &&
 | 
| +      !(compiler->unicode() && compiler->ignore_case())) {
 | 
| +    // If any character within the text node is outside the Latin1 range, it
 | 
| +    // cannot possibly match anything in a one-byte string. This still holds
 | 
| +    // for case-insensitive non-unicode regexp patterns. However, for
 | 
| +    // case-insensitive unicode regexp patterns, this is no longer true, e.g.
 | 
| +    // /\u212b/ui matches "\u00c5".
 | 
|      int dummy = 0;
 | 
|      TextEmitPass(compiler, NON_LATIN1_MATCH, false, trace, false, &dummy);
 | 
|    }
 | 
| @@ -4107,7 +4125,6 @@ int ChoiceNode::EmitOptimizedUnanchoredSearch(RegExpCompiler* compiler,
 | 
|    DCHECK(trace->is_trivial());
 | 
|  
 | 
|    RegExpMacroAssembler* macro_assembler = compiler->macro_assembler();
 | 
| -  Isolate* isolate = macro_assembler->isolate();
 | 
|    // 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
 | 
| @@ -4126,7 +4143,7 @@ int ChoiceNode::EmitOptimizedUnanchoredSearch(RegExpCompiler* compiler,
 | 
|                                             compiler,
 | 
|                                             zone());
 | 
|        GuardedAlternative alt0 = alternatives_->at(0);
 | 
| -      alt0.node()->FillInBMInfo(isolate, 0, kRecursionBudget, bm, false);
 | 
| +      alt0.node()->FillInBMInfo(compiler, 0, kRecursionBudget, bm, false);
 | 
|      }
 | 
|    }
 | 
|    if (bm != NULL) {
 | 
| @@ -6388,9 +6405,8 @@ void Analysis::VisitAssertion(AssertionNode* that) {
 | 
|    EnsureAnalyzed(that->on_success());
 | 
|  }
 | 
|  
 | 
| -
 | 
| -void BackReferenceNode::FillInBMInfo(Isolate* isolate, int offset, int budget,
 | 
| -                                     BoyerMooreLookahead* bm,
 | 
| +void BackReferenceNode::FillInBMInfo(RegExpCompiler* compiler, 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.
 | 
| @@ -6402,8 +6418,7 @@ void BackReferenceNode::FillInBMInfo(Isolate* isolate, int offset, int budget,
 | 
|  STATIC_ASSERT(BoyerMoorePositionInfo::kMapSize ==
 | 
|                RegExpMacroAssembler::kTableSize);
 | 
|  
 | 
| -
 | 
| -void ChoiceNode::FillInBMInfo(Isolate* isolate, int offset, int budget,
 | 
| +void ChoiceNode::FillInBMInfo(RegExpCompiler* compiler, int offset, int budget,
 | 
|                                BoyerMooreLookahead* bm, bool not_at_start) {
 | 
|    ZoneList<GuardedAlternative>* alts = alternatives();
 | 
|    budget = (budget - 1) / alts->length();
 | 
| @@ -6414,14 +6429,14 @@ void ChoiceNode::FillInBMInfo(Isolate* isolate, int offset, int budget,
 | 
|        SaveBMInfo(bm, not_at_start, offset);
 | 
|        return;
 | 
|      }
 | 
| -    alt.node()->FillInBMInfo(isolate, offset, budget, bm, not_at_start);
 | 
| +    alt.node()->FillInBMInfo(compiler, offset, budget, bm, not_at_start);
 | 
|    }
 | 
|    SaveBMInfo(bm, not_at_start, offset);
 | 
|  }
 | 
|  
 | 
| -
 | 
| -void TextNode::FillInBMInfo(Isolate* isolate, int initial_offset, int budget,
 | 
| -                            BoyerMooreLookahead* bm, bool not_at_start) {
 | 
| +void TextNode::FillInBMInfo(RegExpCompiler* compiler, int initial_offset,
 | 
| +                            int budget, BoyerMooreLookahead* bm,
 | 
| +                            bool not_at_start) {
 | 
|    if (initial_offset >= bm->length()) return;
 | 
|    int offset = initial_offset;
 | 
|    int max_char = bm->max_char();
 | 
| @@ -6441,9 +6456,7 @@ void TextNode::FillInBMInfo(Isolate* isolate, int initial_offset, int budget,
 | 
|          uc16 character = atom->data()[j];
 | 
|          if (bm->compiler()->ignore_case()) {
 | 
|            unibrow::uchar chars[unibrow::Ecma262UnCanonicalize::kMaxWidth];
 | 
| -          int length = GetCaseIndependentLetters(
 | 
| -              isolate, character, bm->max_char() == String::kMaxOneByteCharCode,
 | 
| -              chars);
 | 
| +          int length = GetCaseIndependentLetters(compiler, character, chars);
 | 
|            for (int j = 0; j < length; j++) {
 | 
|              bm->Set(offset, chars[j]);
 | 
|            }
 | 
| @@ -6472,7 +6485,7 @@ void TextNode::FillInBMInfo(Isolate* isolate, int initial_offset, int budget,
 | 
|      if (initial_offset == 0) set_bm_info(not_at_start, bm);
 | 
|      return;
 | 
|    }
 | 
| -  on_success()->FillInBMInfo(isolate, offset, budget - 1, bm,
 | 
| +  on_success()->FillInBMInfo(compiler, offset, budget - 1, bm,
 | 
|                               true);  // Not at start after a text node.
 | 
|    if (initial_offset == 0) set_bm_info(not_at_start, bm);
 | 
|  }
 | 
| @@ -6630,7 +6643,6 @@ RegExpEngine::CompilationResult RegExpEngine::Compile(
 | 
|    if ((data->capture_count + 1) * 2 - 1 > RegExpMacroAssembler::kMaxRegister) {
 | 
|      return IrregexpRegExpTooBig(isolate);
 | 
|    }
 | 
| -  bool ignore_case = flags & JSRegExp::kIgnoreCase;
 | 
|    bool is_sticky = flags & JSRegExp::kSticky;
 | 
|    bool is_global = flags & JSRegExp::kGlobal;
 | 
|    bool is_unicode = flags & JSRegExp::kUnicode;
 | 
| @@ -6680,11 +6692,11 @@ RegExpEngine::CompilationResult RegExpEngine::Compile(
 | 
|      }
 | 
|    }
 | 
|    if (is_one_byte) {
 | 
| -    node = node->FilterOneByte(RegExpCompiler::kMaxRecursion, ignore_case);
 | 
| +    node = node->FilterOneByte(RegExpCompiler::kMaxRecursion, &compiler);
 | 
|      // Do it again to propagate the new nodes to places where they were not
 | 
|      // put because they had not been calculated yet.
 | 
|      if (node != NULL) {
 | 
| -      node = node->FilterOneByte(RegExpCompiler::kMaxRecursion, ignore_case);
 | 
| +      node = node->FilterOneByte(RegExpCompiler::kMaxRecursion, &compiler);
 | 
|      }
 | 
|    } else if (compiler.unicode() && (is_global || is_sticky)) {
 | 
|      node = OptionallyStepBackToLeadSurrogate(&compiler, node);
 | 
| 
 |