| 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 |