OLD | NEW |
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 1962 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1973 return on_success()->EatsAtLeast(recursion_depth + 1); | 1973 return on_success()->EatsAtLeast(recursion_depth + 1); |
1974 } | 1974 } |
1975 | 1975 |
1976 | 1976 |
1977 int BackReferenceNode::EatsAtLeast(int recursion_depth) { | 1977 int BackReferenceNode::EatsAtLeast(int recursion_depth) { |
1978 if (recursion_depth > RegExpCompiler::kMaxRecursion) return 0; | 1978 if (recursion_depth > RegExpCompiler::kMaxRecursion) return 0; |
1979 return on_success()->EatsAtLeast(recursion_depth + 1); | 1979 return on_success()->EatsAtLeast(recursion_depth + 1); |
1980 } | 1980 } |
1981 | 1981 |
1982 | 1982 |
1983 | |
1984 int TextNode::EatsAtLeast(int recursion_depth) { | 1983 int TextNode::EatsAtLeast(int recursion_depth) { |
1985 int answer = Length(); | 1984 int answer = Length(); |
1986 if (answer >= 4) return answer; | 1985 if (answer >= 4) return answer; |
1987 if (recursion_depth > RegExpCompiler::kMaxRecursion) return answer; | 1986 if (recursion_depth > RegExpCompiler::kMaxRecursion) return answer; |
1988 return answer + on_success()->EatsAtLeast(recursion_depth + 1); | 1987 return answer + on_success()->EatsAtLeast(recursion_depth + 1); |
1989 } | 1988 } |
1990 | 1989 |
1991 | 1990 |
| 1991 int NegativeLookaheadChoiceNode:: EatsAtLeast(int recursion_depth) { |
| 1992 if (recursion_depth > RegExpCompiler::kMaxRecursion) return 0; |
| 1993 // Alternative 0 is the negative lookahead, alternative 1 is what comes |
| 1994 // afterwards. |
| 1995 RegExpNode* node = alternatives_->at(1).node(); |
| 1996 return node->EatsAtLeast(recursion_depth + 1); |
| 1997 } |
| 1998 |
| 1999 |
| 2000 void NegativeLookaheadChoiceNode::GetQuickCheckDetails( |
| 2001 QuickCheckDetails* details, |
| 2002 RegExpCompiler* compiler, |
| 2003 int filled_in) { |
| 2004 // Alternative 0 is the negative lookahead, alternative 1 is what comes |
| 2005 // afterwards. |
| 2006 RegExpNode* node = alternatives_->at(1).node(); |
| 2007 return node->GetQuickCheckDetails(details, compiler, filled_in); |
| 2008 } |
| 2009 |
| 2010 |
1992 int ChoiceNode::EatsAtLeastHelper(int recursion_depth, | 2011 int ChoiceNode::EatsAtLeastHelper(int recursion_depth, |
1993 RegExpNode* ignore_this_node) { | 2012 RegExpNode* ignore_this_node) { |
1994 if (recursion_depth > RegExpCompiler::kMaxRecursion) return 0; | 2013 if (recursion_depth > RegExpCompiler::kMaxRecursion) return 0; |
1995 int min = 100; | 2014 int min = 100; |
1996 int choice_count = alternatives_->length(); | 2015 int choice_count = alternatives_->length(); |
1997 for (int i = 0; i < choice_count; i++) { | 2016 for (int i = 0; i < choice_count; i++) { |
1998 RegExpNode* node = alternatives_->at(i).node(); | 2017 RegExpNode* node = alternatives_->at(i).node(); |
1999 if (node == ignore_this_node) continue; | 2018 if (node == ignore_this_node) continue; |
2000 int node_eats_at_least = node->EatsAtLeast(recursion_depth + 1); | 2019 int node_eats_at_least = node->EatsAtLeast(recursion_depth + 1); |
2001 if (node_eats_at_least < min) min = node_eats_at_least; | 2020 if (node_eats_at_least < min) min = node_eats_at_least; |
(...skipping 1015 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3017 Trace new_trace(*current_trace); | 3036 Trace new_trace(*current_trace); |
3018 new_trace.set_characters_preloaded(preload_is_current ? | 3037 new_trace.set_characters_preloaded(preload_is_current ? |
3019 preload_characters : | 3038 preload_characters : |
3020 0); | 3039 0); |
3021 if (preload_has_checked_bounds) { | 3040 if (preload_has_checked_bounds) { |
3022 new_trace.set_bound_checked_up_to(preload_characters); | 3041 new_trace.set_bound_checked_up_to(preload_characters); |
3023 } | 3042 } |
3024 new_trace.quick_check_performed()->Clear(); | 3043 new_trace.quick_check_performed()->Clear(); |
3025 alt_gen->expects_preload = preload_is_current; | 3044 alt_gen->expects_preload = preload_is_current; |
3026 bool generate_full_check_inline = false; | 3045 bool generate_full_check_inline = false; |
3027 if (alternative.node()->EmitQuickCheck(compiler, | 3046 if (try_to_emit_quick_check_for_alternative(i) && |
| 3047 alternative.node()->EmitQuickCheck(compiler, |
3028 &new_trace, | 3048 &new_trace, |
3029 preload_has_checked_bounds, | 3049 preload_has_checked_bounds, |
3030 &alt_gen->possible_success, | 3050 &alt_gen->possible_success, |
3031 &alt_gen->quick_check_details, | 3051 &alt_gen->quick_check_details, |
3032 i < choice_count - 1)) { | 3052 i < choice_count - 1)) { |
3033 // Quick check was generated for this choice. | 3053 // Quick check was generated for this choice. |
3034 preload_is_current = true; | 3054 preload_is_current = true; |
3035 preload_has_checked_bounds = true; | 3055 preload_has_checked_bounds = true; |
3036 // On the last choice in the ChoiceNode we generated the quick | 3056 // On the last choice in the ChoiceNode we generated the quick |
3037 // check to fall through on possible success. So now we need to | 3057 // check to fall through on possible success. So now we need to |
(...skipping 912 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3950 position_register, | 3970 position_register, |
3951 on_success))); | 3971 on_success))); |
3952 } else { | 3972 } else { |
3953 // We use a ChoiceNode for a negative lookahead because it has most of | 3973 // We use a ChoiceNode for a negative lookahead because it has most of |
3954 // the characteristics we need. It has the body of the lookahead as its | 3974 // the characteristics we need. It has the body of the lookahead as its |
3955 // first alternative and the expression after the lookahead of the second | 3975 // first alternative and the expression after the lookahead of the second |
3956 // alternative. If the first alternative succeeds then the | 3976 // alternative. If the first alternative succeeds then the |
3957 // NegativeSubmatchSuccess will unwind the stack including everything the | 3977 // NegativeSubmatchSuccess will unwind the stack including everything the |
3958 // choice node set up and backtrack. If the first alternative fails then | 3978 // choice node set up and backtrack. If the first alternative fails then |
3959 // the second alternative is tried, which is exactly the desired result | 3979 // the second alternative is tried, which is exactly the desired result |
3960 // for a negative lookahead. In the case where the dispatch table | 3980 // for a negative lookahead. The NegativeLookaheadChoiceNode is a special |
3961 // determines that the first alternative cannot match we will save time | 3981 // ChoiceNode that knows to ignore the first exit when calculating quick |
3962 // by not trying it. Things are not quite so well-optimized if the | 3982 // checks. |
3963 // dispatch table determines that the second alternative cannot match. | |
3964 // In this case we could optimize by immediately backtracking. | |
3965 ChoiceNode* choice_node = new ChoiceNode(2); | |
3966 GuardedAlternative body_alt( | 3983 GuardedAlternative body_alt( |
3967 body()->ToNode( | 3984 body()->ToNode( |
3968 compiler, | 3985 compiler, |
3969 success = new NegativeSubmatchSuccess(stack_pointer_register, | 3986 success = new NegativeSubmatchSuccess(stack_pointer_register, |
3970 position_register))); | 3987 position_register))); |
3971 choice_node->AddAlternative(body_alt); | 3988 ChoiceNode* choice_node = |
3972 choice_node->AddAlternative(GuardedAlternative(on_success)); | 3989 new NegativeLookaheadChoiceNode(body_alt, |
| 3990 GuardedAlternative(on_success)); |
3973 return ActionNode::BeginSubmatch(stack_pointer_register, | 3991 return ActionNode::BeginSubmatch(stack_pointer_register, |
3974 position_register, | 3992 position_register, |
3975 choice_node); | 3993 choice_node); |
3976 } | 3994 } |
3977 } | 3995 } |
3978 | 3996 |
3979 | 3997 |
3980 RegExpNode* RegExpCapture::ToNode(RegExpCompiler* compiler, | 3998 RegExpNode* RegExpCapture::ToNode(RegExpCompiler* compiler, |
3981 RegExpNode* on_success) { | 3999 RegExpNode* on_success) { |
3982 return ToNode(body(), index(), compiler, on_success); | 4000 return ToNode(body(), index(), compiler, on_success); |
(...skipping 680 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4663 EmbeddedVector<byte, 1024> codes; | 4681 EmbeddedVector<byte, 1024> codes; |
4664 RegExpMacroAssemblerIrregexp macro_assembler(codes); | 4682 RegExpMacroAssemblerIrregexp macro_assembler(codes); |
4665 return compiler.Assemble(¯o_assembler, | 4683 return compiler.Assemble(¯o_assembler, |
4666 node, | 4684 node, |
4667 data->capture_count, | 4685 data->capture_count, |
4668 pattern); | 4686 pattern); |
4669 } | 4687 } |
4670 | 4688 |
4671 | 4689 |
4672 }} // namespace v8::internal | 4690 }} // namespace v8::internal |
OLD | NEW |