| Index: src/jsregexp.cc
|
| ===================================================================
|
| --- src/jsregexp.cc (revision 1104)
|
| +++ src/jsregexp.cc (working copy)
|
| @@ -1980,7 +1980,6 @@
|
| }
|
|
|
|
|
| -
|
| int TextNode::EatsAtLeast(int recursion_depth) {
|
| int answer = Length();
|
| if (answer >= 4) return answer;
|
| @@ -1989,6 +1988,26 @@
|
| }
|
|
|
|
|
| +int NegativeLookaheadChoiceNode:: EatsAtLeast(int recursion_depth) {
|
| + if (recursion_depth > RegExpCompiler::kMaxRecursion) return 0;
|
| + // Alternative 0 is the negative lookahead, alternative 1 is what comes
|
| + // afterwards.
|
| + RegExpNode* node = alternatives_->at(1).node();
|
| + return node->EatsAtLeast(recursion_depth + 1);
|
| +}
|
| +
|
| +
|
| +void NegativeLookaheadChoiceNode::GetQuickCheckDetails(
|
| + QuickCheckDetails* details,
|
| + RegExpCompiler* compiler,
|
| + int filled_in) {
|
| + // Alternative 0 is the negative lookahead, alternative 1 is what comes
|
| + // afterwards.
|
| + RegExpNode* node = alternatives_->at(1).node();
|
| + return node->GetQuickCheckDetails(details, compiler, filled_in);
|
| +}
|
| +
|
| +
|
| int ChoiceNode::EatsAtLeastHelper(int recursion_depth,
|
| RegExpNode* ignore_this_node) {
|
| if (recursion_depth > RegExpCompiler::kMaxRecursion) return 0;
|
| @@ -3024,7 +3043,8 @@
|
| new_trace.quick_check_performed()->Clear();
|
| alt_gen->expects_preload = preload_is_current;
|
| bool generate_full_check_inline = false;
|
| - if (alternative.node()->EmitQuickCheck(compiler,
|
| + if (try_to_emit_quick_check_for_alternative(i) &&
|
| + alternative.node()->EmitQuickCheck(compiler,
|
| &new_trace,
|
| preload_has_checked_bounds,
|
| &alt_gen->possible_success,
|
| @@ -3957,19 +3977,17 @@
|
| // 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. In the case where the dispatch table
|
| - // determines that the first alternative cannot match we will save time
|
| - // by not trying it. Things are not quite so well-optimized if the
|
| - // dispatch table determines that the second alternative cannot match.
|
| - // In this case we could optimize by immediately backtracking.
|
| - ChoiceNode* choice_node = new ChoiceNode(2);
|
| + // for a negative lookahead. The NegativeLookaheadChoiceNode is a special
|
| + // ChoiceNode that knows to ignore the first exit when calculating quick
|
| + // checks.
|
| GuardedAlternative body_alt(
|
| body()->ToNode(
|
| compiler,
|
| success = new NegativeSubmatchSuccess(stack_pointer_register,
|
| position_register)));
|
| - choice_node->AddAlternative(body_alt);
|
| - choice_node->AddAlternative(GuardedAlternative(on_success));
|
| + ChoiceNode* choice_node =
|
| + new NegativeLookaheadChoiceNode(body_alt,
|
| + GuardedAlternative(on_success));
|
| return ActionNode::BeginSubmatch(stack_pointer_register,
|
| position_register,
|
| choice_node);
|
|
|