| Index: src/jsregexp.cc
|
| diff --git a/src/jsregexp.cc b/src/jsregexp.cc
|
| index 8928d4e2b643cf1d4def309051ced0f74f598d49..d66777efc27101113dd2fed17cf498b00efa718e 100644
|
| --- a/src/jsregexp.cc
|
| +++ b/src/jsregexp.cc
|
| @@ -2298,35 +2298,33 @@ RegExpNode::LimitResult RegExpNode::LimitVersions(RegExpCompiler* compiler,
|
|
|
|
|
| int ActionNode::EatsAtLeast(int still_to_find,
|
| - int recursion_depth,
|
| + int budget,
|
| bool not_at_start) {
|
| - if (recursion_depth > RegExpCompiler::kMaxRecursion) return 0;
|
| + if (budget <= 0) return 0;
|
| if (type_ == POSITIVE_SUBMATCH_SUCCESS) return 0; // Rewinds input!
|
| return on_success()->EatsAtLeast(still_to_find,
|
| - recursion_depth + 1,
|
| + budget - 1,
|
| not_at_start);
|
| }
|
|
|
|
|
| void ActionNode::FillInBMInfo(int offset,
|
| - int recursion_depth,
|
| int budget,
|
| BoyerMooreLookahead* bm,
|
| bool not_at_start) {
|
| if (type_ == BEGIN_SUBMATCH) {
|
| bm->SetRest(offset);
|
| } else if (type_ != POSITIVE_SUBMATCH_SUCCESS) {
|
| - on_success()->FillInBMInfo(
|
| - offset, recursion_depth + 1, budget - 1, bm, not_at_start);
|
| + on_success()->FillInBMInfo(offset, budget - 1, bm, not_at_start);
|
| }
|
| SaveBMInfo(bm, not_at_start, offset);
|
| }
|
|
|
|
|
| int AssertionNode::EatsAtLeast(int still_to_find,
|
| - int recursion_depth,
|
| + int budget,
|
| bool not_at_start) {
|
| - if (recursion_depth > RegExpCompiler::kMaxRecursion) return 0;
|
| + 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
|
| @@ -2334,55 +2332,53 @@ int AssertionNode::EatsAtLeast(int still_to_find,
|
| // branches in the node graph.
|
| if (type() == AT_START && not_at_start) return still_to_find;
|
| return on_success()->EatsAtLeast(still_to_find,
|
| - recursion_depth + 1,
|
| + budget - 1,
|
| not_at_start);
|
| }
|
|
|
|
|
| void AssertionNode::FillInBMInfo(int offset,
|
| - int recursion_depth,
|
| int budget,
|
| BoyerMooreLookahead* bm,
|
| bool not_at_start) {
|
| // Match the behaviour of EatsAtLeast on this node.
|
| if (type() == AT_START && not_at_start) return;
|
| - on_success()->FillInBMInfo(
|
| - offset, recursion_depth + 1, budget - 1, bm, not_at_start);
|
| + on_success()->FillInBMInfo(offset, budget - 1, bm, not_at_start);
|
| SaveBMInfo(bm, not_at_start, offset);
|
| }
|
|
|
|
|
| int BackReferenceNode::EatsAtLeast(int still_to_find,
|
| - int recursion_depth,
|
| + int budget,
|
| bool not_at_start) {
|
| - if (recursion_depth > RegExpCompiler::kMaxRecursion) return 0;
|
| + if (budget <= 0) return 0;
|
| return on_success()->EatsAtLeast(still_to_find,
|
| - recursion_depth + 1,
|
| + budget - 1,
|
| not_at_start);
|
| }
|
|
|
|
|
| int TextNode::EatsAtLeast(int still_to_find,
|
| - int recursion_depth,
|
| + int budget,
|
| bool not_at_start) {
|
| int answer = Length();
|
| if (answer >= still_to_find) return answer;
|
| - if (recursion_depth > RegExpCompiler::kMaxRecursion) 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,
|
| - recursion_depth + 1,
|
| + budget - 1,
|
| true);
|
| }
|
|
|
|
|
| int NegativeLookaheadChoiceNode::EatsAtLeast(int still_to_find,
|
| - int recursion_depth,
|
| + int budget,
|
| bool not_at_start) {
|
| - if (recursion_depth > RegExpCompiler::kMaxRecursion) return 0;
|
| + if (budget <= 0) return 0;
|
| // Alternative 0 is the negative lookahead, alternative 1 is what comes
|
| // afterwards.
|
| RegExpNode* node = alternatives_->at(1).node();
|
| - return node->EatsAtLeast(still_to_find, recursion_depth + 1, not_at_start);
|
| + return node->EatsAtLeast(still_to_find, budget - 1, not_at_start);
|
| }
|
|
|
|
|
| @@ -2399,39 +2395,40 @@ void NegativeLookaheadChoiceNode::GetQuickCheckDetails(
|
|
|
|
|
| int ChoiceNode::EatsAtLeastHelper(int still_to_find,
|
| - int recursion_depth,
|
| + int budget,
|
| RegExpNode* ignore_this_node,
|
| bool not_at_start) {
|
| - if (recursion_depth > RegExpCompiler::kMaxRecursion) return 0;
|
| + if (budget <= 0) return 0;
|
| int min = 100;
|
| int choice_count = alternatives_->length();
|
| + budget = (budget - 1) / choice_count;
|
| for (int i = 0; i < choice_count; i++) {
|
| RegExpNode* node = alternatives_->at(i).node();
|
| if (node == ignore_this_node) continue;
|
| - int node_eats_at_least = node->EatsAtLeast(still_to_find,
|
| - recursion_depth + 1,
|
| - not_at_start);
|
| + 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 LoopChoiceNode::EatsAtLeast(int still_to_find,
|
| - int recursion_depth,
|
| + int budget,
|
| bool not_at_start) {
|
| return EatsAtLeastHelper(still_to_find,
|
| - recursion_depth,
|
| + budget - 1,
|
| loop_node_,
|
| not_at_start);
|
| }
|
|
|
|
|
| int ChoiceNode::EatsAtLeast(int still_to_find,
|
| - int recursion_depth,
|
| + int budget,
|
| bool not_at_start) {
|
| return EatsAtLeastHelper(still_to_find,
|
| - recursion_depth,
|
| + budget,
|
| NULL,
|
| not_at_start);
|
| }
|
| @@ -2987,19 +2984,15 @@ void LoopChoiceNode::GetQuickCheckDetails(QuickCheckDetails* details,
|
|
|
|
|
| void LoopChoiceNode::FillInBMInfo(int offset,
|
| - int recursion_depth,
|
| int budget,
|
| BoyerMooreLookahead* bm,
|
| bool not_at_start) {
|
| - if (body_can_be_zero_length_ ||
|
| - recursion_depth > RegExpCompiler::kMaxRecursion ||
|
| - budget <= 0) {
|
| + if (body_can_be_zero_length_ || budget <= 0) {
|
| bm->SetRest(offset);
|
| SaveBMInfo(bm, not_at_start, offset);
|
| return;
|
| }
|
| - ChoiceNode::FillInBMInfo(
|
| - offset, recursion_depth + 1, budget - 1, bm, not_at_start);
|
| + ChoiceNode::FillInBMInfo(offset, budget - 1, bm, not_at_start);
|
| SaveBMInfo(bm, not_at_start, offset);
|
| }
|
|
|
| @@ -3096,12 +3089,13 @@ void AssertionNode::EmitBoundaryCheck(RegExpCompiler* compiler, Trace* trace) {
|
| BoyerMooreLookahead* lookahead = bm_info(not_at_start);
|
| if (lookahead == NULL) {
|
| int eats_at_least =
|
| - Min(kMaxLookaheadForBoyerMoore,
|
| - EatsAtLeast(kMaxLookaheadForBoyerMoore, 0, not_at_start));
|
| + Min(kMaxLookaheadForBoyerMoore, EatsAtLeast(kMaxLookaheadForBoyerMoore,
|
| + kRecursionBudget,
|
| + not_at_start));
|
| if (eats_at_least >= 1) {
|
| BoyerMooreLookahead* bm =
|
| new(zone()) BoyerMooreLookahead(eats_at_least, compiler, zone());
|
| - FillInBMInfo(0, 0, kFillInBMBudget, bm, not_at_start);
|
| + FillInBMInfo(0, kRecursionBudget, bm, not_at_start);
|
| if (bm->at(0)->is_non_word()) next_is_word_character = Trace::FALSE;
|
| if (bm->at(0)->is_word()) next_is_word_character = Trace::TRUE;
|
| }
|
| @@ -4033,16 +4027,17 @@ void ChoiceNode::Emit(RegExpCompiler* compiler, Trace* trace) {
|
| ASSERT(trace->is_trivial()); // This is the case on LoopChoiceNodes.
|
| BoyerMooreLookahead* lookahead = bm_info(not_at_start);
|
| if (lookahead == NULL) {
|
| - eats_at_least =
|
| - Min(kMaxLookaheadForBoyerMoore,
|
| - EatsAtLeast(kMaxLookaheadForBoyerMoore, 0, not_at_start));
|
| + eats_at_least = Min(kMaxLookaheadForBoyerMoore,
|
| + EatsAtLeast(kMaxLookaheadForBoyerMoore,
|
| + kRecursionBudget,
|
| + not_at_start));
|
| if (eats_at_least >= 1) {
|
| BoyerMooreLookahead* bm =
|
| new(zone()) BoyerMooreLookahead(eats_at_least,
|
| compiler,
|
| zone());
|
| GuardedAlternative alt0 = alternatives_->at(0);
|
| - alt0.node()->FillInBMInfo(0, 0, kFillInBMBudget, bm, not_at_start);
|
| + alt0.node()->FillInBMInfo(0, kRecursionBudget, bm, not_at_start);
|
| skip_was_emitted = bm->EmitSkipInstructions(macro_assembler);
|
| }
|
| } else {
|
| @@ -4054,7 +4049,8 @@ void ChoiceNode::Emit(RegExpCompiler* compiler, Trace* trace) {
|
|
|
| if (eats_at_least == kEatsAtLeastNotYetInitialized) {
|
| // Save some time by looking at most one machine word ahead.
|
| - eats_at_least = EatsAtLeast(compiler->ascii() ? 4 : 2, 0, not_at_start);
|
| + eats_at_least =
|
| + EatsAtLeast(compiler->ascii() ? 4 : 2, kRecursionBudget, not_at_start);
|
| }
|
| int preload_characters = CalculatePreloadCharacters(compiler, eats_at_least);
|
|
|
| @@ -5810,7 +5806,6 @@ void Analysis::VisitAssertion(AssertionNode* that) {
|
|
|
|
|
| void BackReferenceNode::FillInBMInfo(int offset,
|
| - int recursion_depth,
|
| int budget,
|
| BoyerMooreLookahead* bm,
|
| bool not_at_start) {
|
| @@ -5826,7 +5821,6 @@ STATIC_ASSERT(BoyerMoorePositionInfo::kMapSize ==
|
|
|
|
|
| void ChoiceNode::FillInBMInfo(int offset,
|
| - int recursion_depth,
|
| int budget,
|
| BoyerMooreLookahead* bm,
|
| bool not_at_start) {
|
| @@ -5839,15 +5833,13 @@ void ChoiceNode::FillInBMInfo(int offset,
|
| SaveBMInfo(bm, not_at_start, offset);
|
| return;
|
| }
|
| - alt.node()->FillInBMInfo(
|
| - offset, recursion_depth + 1, budget, bm, not_at_start);
|
| + alt.node()->FillInBMInfo(offset, budget, bm, not_at_start);
|
| }
|
| SaveBMInfo(bm, not_at_start, offset);
|
| }
|
|
|
|
|
| void TextNode::FillInBMInfo(int initial_offset,
|
| - int recursion_depth,
|
| int budget,
|
| BoyerMooreLookahead* bm,
|
| bool not_at_start) {
|
| @@ -5904,7 +5896,6 @@ void TextNode::FillInBMInfo(int initial_offset,
|
| return;
|
| }
|
| on_success()->FillInBMInfo(offset,
|
| - recursion_depth + 1,
|
| budget - 1,
|
| bm,
|
| true); // Not at start after a text node.
|
|
|