| Index: src/jsregexp.cc
|
| ===================================================================
|
| --- src/jsregexp.cc (revision 5911)
|
| +++ src/jsregexp.cc (working copy)
|
| @@ -1650,41 +1650,64 @@
|
| }
|
|
|
|
|
| -int ActionNode::EatsAtLeast(int still_to_find, int recursion_depth) {
|
| +int ActionNode::EatsAtLeast(int still_to_find,
|
| + int recursion_depth,
|
| + bool not_at_start) {
|
| if (recursion_depth > RegExpCompiler::kMaxRecursion) return 0;
|
| if (type_ == POSITIVE_SUBMATCH_SUCCESS) return 0; // Rewinds input!
|
| - return on_success()->EatsAtLeast(still_to_find, recursion_depth + 1);
|
| + return on_success()->EatsAtLeast(still_to_find,
|
| + recursion_depth + 1,
|
| + not_at_start);
|
| }
|
|
|
|
|
| -int AssertionNode::EatsAtLeast(int still_to_find, int recursion_depth) {
|
| +int AssertionNode::EatsAtLeast(int still_to_find,
|
| + int recursion_depth,
|
| + bool not_at_start) {
|
| if (recursion_depth > RegExpCompiler::kMaxRecursion) return 0;
|
| - return on_success()->EatsAtLeast(still_to_find, recursion_depth + 1);
|
| + // 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 (type() == AT_START && not_at_start) return still_to_find;
|
| + return on_success()->EatsAtLeast(still_to_find,
|
| + recursion_depth + 1,
|
| + not_at_start);
|
| }
|
|
|
|
|
| -int BackReferenceNode::EatsAtLeast(int still_to_find, int recursion_depth) {
|
| +int BackReferenceNode::EatsAtLeast(int still_to_find,
|
| + int recursion_depth,
|
| + bool not_at_start) {
|
| if (recursion_depth > RegExpCompiler::kMaxRecursion) return 0;
|
| - return on_success()->EatsAtLeast(still_to_find, recursion_depth + 1);
|
| + return on_success()->EatsAtLeast(still_to_find,
|
| + recursion_depth + 1,
|
| + not_at_start);
|
| }
|
|
|
|
|
| -int TextNode::EatsAtLeast(int still_to_find, int recursion_depth) {
|
| +int TextNode::EatsAtLeast(int still_to_find,
|
| + int recursion_depth,
|
| + bool not_at_start) {
|
| int answer = Length();
|
| if (answer >= still_to_find) return answer;
|
| if (recursion_depth > RegExpCompiler::kMaxRecursion) 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);
|
| + recursion_depth + 1,
|
| + true);
|
| }
|
|
|
|
|
| int NegativeLookaheadChoiceNode::EatsAtLeast(int still_to_find,
|
| - int recursion_depth) {
|
| + int recursion_depth,
|
| + bool not_at_start) {
|
| 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(still_to_find, recursion_depth + 1);
|
| + return node->EatsAtLeast(still_to_find, recursion_depth + 1, not_at_start);
|
| }
|
|
|
|
|
| @@ -1702,7 +1725,8 @@
|
|
|
| int ChoiceNode::EatsAtLeastHelper(int still_to_find,
|
| int recursion_depth,
|
| - RegExpNode* ignore_this_node) {
|
| + RegExpNode* ignore_this_node,
|
| + bool not_at_start) {
|
| if (recursion_depth > RegExpCompiler::kMaxRecursion) return 0;
|
| int min = 100;
|
| int choice_count = alternatives_->length();
|
| @@ -1710,20 +1734,31 @@
|
| 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);
|
| + recursion_depth + 1,
|
| + not_at_start);
|
| if (node_eats_at_least < min) min = node_eats_at_least;
|
| }
|
| return min;
|
| }
|
|
|
|
|
| -int LoopChoiceNode::EatsAtLeast(int still_to_find, int recursion_depth) {
|
| - return EatsAtLeastHelper(still_to_find, recursion_depth, loop_node_);
|
| +int LoopChoiceNode::EatsAtLeast(int still_to_find,
|
| + int recursion_depth,
|
| + bool not_at_start) {
|
| + return EatsAtLeastHelper(still_to_find,
|
| + recursion_depth,
|
| + loop_node_,
|
| + not_at_start);
|
| }
|
|
|
|
|
| -int ChoiceNode::EatsAtLeast(int still_to_find, int recursion_depth) {
|
| - return EatsAtLeastHelper(still_to_find, recursion_depth, NULL);
|
| +int ChoiceNode::EatsAtLeast(int still_to_find,
|
| + int recursion_depth,
|
| + bool not_at_start) {
|
| + return EatsAtLeastHelper(still_to_find,
|
| + recursion_depth,
|
| + NULL,
|
| + not_at_start);
|
| }
|
|
|
|
|
| @@ -2630,8 +2665,9 @@
|
| }
|
|
|
|
|
| -int ChoiceNode::CalculatePreloadCharacters(RegExpCompiler* compiler) {
|
| - int preload_characters = EatsAtLeast(4, 0);
|
| +int ChoiceNode::CalculatePreloadCharacters(RegExpCompiler* compiler,
|
| + bool not_at_start) {
|
| + int preload_characters = EatsAtLeast(4, 0, not_at_start);
|
| if (compiler->macro_assembler()->CanReadUnaligned()) {
|
| bool ascii = compiler->ascii();
|
| if (ascii) {
|
| @@ -2839,7 +2875,9 @@
|
|
|
| int first_normal_choice = greedy_loop ? 1 : 0;
|
|
|
| - int preload_characters = CalculatePreloadCharacters(compiler);
|
| + int preload_characters =
|
| + CalculatePreloadCharacters(compiler,
|
| + current_trace->at_start() == Trace::FALSE);
|
| bool preload_is_current =
|
| (current_trace->characters_preloaded() == preload_characters);
|
| bool preload_has_checked_bounds = preload_is_current;
|
|
|