Index: src/jsregexp.cc |
diff --git a/src/jsregexp.cc b/src/jsregexp.cc |
index 9b82da131cf44ffae8334a54e8a0ee50df157cae..a82a6c107e5e5525f54f79c8c92d47b302755de2 100644 |
--- a/src/jsregexp.cc |
+++ b/src/jsregexp.cc |
@@ -2299,35 +2299,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 |
@@ -2335,55 +2333,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); |
} |
@@ -2400,39 +2396,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); |
} |
@@ -2988,19 +2985,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); |
} |
@@ -3097,12 +3090,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, |
+ kFillInBMBudget, |
+ 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, kFillInBMBudget, 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; |
} |
@@ -4034,16 +4028,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, |
+ kFillInBMBudget, |
+ 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, kFillInBMBudget, bm, not_at_start); |
skip_was_emitted = bm->EmitSkipInstructions(macro_assembler); |
} |
} else { |
@@ -4055,7 +4050,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, kFillInBMBudget, not_at_start); |
} |
int preload_characters = CalculatePreloadCharacters(compiler, eats_at_least); |
@@ -5811,7 +5807,6 @@ void Analysis::VisitAssertion(AssertionNode* that) { |
void BackReferenceNode::FillInBMInfo(int offset, |
- int recursion_depth, |
int budget, |
BoyerMooreLookahead* bm, |
bool not_at_start) { |
@@ -5827,7 +5822,6 @@ STATIC_ASSERT(BoyerMoorePositionInfo::kMapSize == |
void ChoiceNode::FillInBMInfo(int offset, |
- int recursion_depth, |
int budget, |
BoyerMooreLookahead* bm, |
bool not_at_start) { |
@@ -5840,15 +5834,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) { |
@@ -5905,7 +5897,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. |