| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 2461 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2472 } | 2472 } |
| 2473 | 2473 |
| 2474 | 2474 |
| 2475 bool RegExpNode::EmitQuickCheck(RegExpCompiler* compiler, | 2475 bool RegExpNode::EmitQuickCheck(RegExpCompiler* compiler, |
| 2476 Trace* trace, | 2476 Trace* trace, |
| 2477 bool preload_has_checked_bounds, | 2477 bool preload_has_checked_bounds, |
| 2478 Label* on_possible_success, | 2478 Label* on_possible_success, |
| 2479 QuickCheckDetails* details, | 2479 QuickCheckDetails* details, |
| 2480 bool fall_through_on_failure) { | 2480 bool fall_through_on_failure) { |
| 2481 if (details->characters() == 0) return false; | 2481 if (details->characters() == 0) return false; |
| 2482 GetQuickCheckDetails(details, compiler, 0, trace->at_start() == Trace::FALSE); | 2482 GetQuickCheckDetails( |
| 2483 details, compiler, 0, trace->at_start() == Trace::FALSE_VALUE); |
| 2483 if (details->cannot_match()) return false; | 2484 if (details->cannot_match()) return false; |
| 2484 if (!details->Rationalize(compiler->ascii())) return false; | 2485 if (!details->Rationalize(compiler->ascii())) return false; |
| 2485 ASSERT(details->characters() == 1 || | 2486 ASSERT(details->characters() == 1 || |
| 2486 compiler->macro_assembler()->CanReadUnaligned()); | 2487 compiler->macro_assembler()->CanReadUnaligned()); |
| 2487 uint32_t mask = details->mask(); | 2488 uint32_t mask = details->mask(); |
| 2488 uint32_t value = details->value(); | 2489 uint32_t value = details->value(); |
| 2489 | 2490 |
| 2490 RegExpMacroAssembler* assembler = compiler->macro_assembler(); | 2491 RegExpMacroAssembler* assembler = compiler->macro_assembler(); |
| 2491 | 2492 |
| 2492 if (trace->characters_preloaded() != details->characters()) { | 2493 if (trace->characters_preloaded() != details->characters()) { |
| (...skipping 568 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3061 } | 3062 } |
| 3062 assembler->Bind(&ok); | 3063 assembler->Bind(&ok); |
| 3063 on_success->Emit(compiler, &new_trace); | 3064 on_success->Emit(compiler, &new_trace); |
| 3064 } | 3065 } |
| 3065 | 3066 |
| 3066 | 3067 |
| 3067 // Emit the code to handle \b and \B (word-boundary or non-word-boundary). | 3068 // Emit the code to handle \b and \B (word-boundary or non-word-boundary). |
| 3068 void AssertionNode::EmitBoundaryCheck(RegExpCompiler* compiler, Trace* trace) { | 3069 void AssertionNode::EmitBoundaryCheck(RegExpCompiler* compiler, Trace* trace) { |
| 3069 RegExpMacroAssembler* assembler = compiler->macro_assembler(); | 3070 RegExpMacroAssembler* assembler = compiler->macro_assembler(); |
| 3070 Trace::TriBool next_is_word_character = Trace::UNKNOWN; | 3071 Trace::TriBool next_is_word_character = Trace::UNKNOWN; |
| 3071 bool not_at_start = (trace->at_start() == Trace::FALSE); | 3072 bool not_at_start = (trace->at_start() == Trace::FALSE_VALUE); |
| 3072 BoyerMooreLookahead* lookahead = bm_info(not_at_start); | 3073 BoyerMooreLookahead* lookahead = bm_info(not_at_start); |
| 3073 if (lookahead == NULL) { | 3074 if (lookahead == NULL) { |
| 3074 int eats_at_least = | 3075 int eats_at_least = |
| 3075 Min(kMaxLookaheadForBoyerMoore, EatsAtLeast(kMaxLookaheadForBoyerMoore, | 3076 Min(kMaxLookaheadForBoyerMoore, EatsAtLeast(kMaxLookaheadForBoyerMoore, |
| 3076 kRecursionBudget, | 3077 kRecursionBudget, |
| 3077 not_at_start)); | 3078 not_at_start)); |
| 3078 if (eats_at_least >= 1) { | 3079 if (eats_at_least >= 1) { |
| 3079 BoyerMooreLookahead* bm = | 3080 BoyerMooreLookahead* bm = |
| 3080 new(zone()) BoyerMooreLookahead(eats_at_least, compiler, zone()); | 3081 new(zone()) BoyerMooreLookahead(eats_at_least, compiler, zone()); |
| 3081 FillInBMInfo(0, kRecursionBudget, bm, not_at_start); | 3082 FillInBMInfo(0, kRecursionBudget, bm, not_at_start); |
| 3082 if (bm->at(0)->is_non_word()) next_is_word_character = Trace::FALSE; | 3083 if (bm->at(0)->is_non_word()) |
| 3083 if (bm->at(0)->is_word()) next_is_word_character = Trace::TRUE; | 3084 next_is_word_character = Trace::FALSE_VALUE; |
| 3085 if (bm->at(0)->is_word()) next_is_word_character = Trace::TRUE_VALUE; |
| 3084 } | 3086 } |
| 3085 } else { | 3087 } else { |
| 3086 if (lookahead->at(0)->is_non_word()) next_is_word_character = Trace::FALSE; | 3088 if (lookahead->at(0)->is_non_word()) |
| 3087 if (lookahead->at(0)->is_word()) next_is_word_character = Trace::TRUE; | 3089 next_is_word_character = Trace::FALSE_VALUE; |
| 3090 if (lookahead->at(0)->is_word()) |
| 3091 next_is_word_character = Trace::TRUE_VALUE; |
| 3088 } | 3092 } |
| 3089 bool at_boundary = (assertion_type_ == AssertionNode::AT_BOUNDARY); | 3093 bool at_boundary = (assertion_type_ == AssertionNode::AT_BOUNDARY); |
| 3090 if (next_is_word_character == Trace::UNKNOWN) { | 3094 if (next_is_word_character == Trace::UNKNOWN) { |
| 3091 Label before_non_word; | 3095 Label before_non_word; |
| 3092 Label before_word; | 3096 Label before_word; |
| 3093 if (trace->characters_preloaded() != 1) { | 3097 if (trace->characters_preloaded() != 1) { |
| 3094 assembler->LoadCurrentCharacter(trace->cp_offset(), &before_non_word); | 3098 assembler->LoadCurrentCharacter(trace->cp_offset(), &before_non_word); |
| 3095 } | 3099 } |
| 3096 // Fall through on non-word. | 3100 // Fall through on non-word. |
| 3097 EmitWordCheck(assembler, &before_word, &before_non_word, false); | 3101 EmitWordCheck(assembler, &before_word, &before_non_word, false); |
| 3098 // Next character is not a word character. | 3102 // Next character is not a word character. |
| 3099 assembler->Bind(&before_non_word); | 3103 assembler->Bind(&before_non_word); |
| 3100 Label ok; | 3104 Label ok; |
| 3101 BacktrackIfPrevious(compiler, trace, at_boundary ? kIsNonWord : kIsWord); | 3105 BacktrackIfPrevious(compiler, trace, at_boundary ? kIsNonWord : kIsWord); |
| 3102 assembler->GoTo(&ok); | 3106 assembler->GoTo(&ok); |
| 3103 | 3107 |
| 3104 assembler->Bind(&before_word); | 3108 assembler->Bind(&before_word); |
| 3105 BacktrackIfPrevious(compiler, trace, at_boundary ? kIsWord : kIsNonWord); | 3109 BacktrackIfPrevious(compiler, trace, at_boundary ? kIsWord : kIsNonWord); |
| 3106 assembler->Bind(&ok); | 3110 assembler->Bind(&ok); |
| 3107 } else if (next_is_word_character == Trace::TRUE) { | 3111 } else if (next_is_word_character == Trace::TRUE_VALUE) { |
| 3108 BacktrackIfPrevious(compiler, trace, at_boundary ? kIsWord : kIsNonWord); | 3112 BacktrackIfPrevious(compiler, trace, at_boundary ? kIsWord : kIsNonWord); |
| 3109 } else { | 3113 } else { |
| 3110 ASSERT(next_is_word_character == Trace::FALSE); | 3114 ASSERT(next_is_word_character == Trace::FALSE_VALUE); |
| 3111 BacktrackIfPrevious(compiler, trace, at_boundary ? kIsNonWord : kIsWord); | 3115 BacktrackIfPrevious(compiler, trace, at_boundary ? kIsNonWord : kIsWord); |
| 3112 } | 3116 } |
| 3113 } | 3117 } |
| 3114 | 3118 |
| 3115 | 3119 |
| 3116 void AssertionNode::BacktrackIfPrevious( | 3120 void AssertionNode::BacktrackIfPrevious( |
| 3117 RegExpCompiler* compiler, | 3121 RegExpCompiler* compiler, |
| 3118 Trace* trace, | 3122 Trace* trace, |
| 3119 AssertionNode::IfPrevious backtrack_if_previous) { | 3123 AssertionNode::IfPrevious backtrack_if_previous) { |
| 3120 RegExpMacroAssembler* assembler = compiler->macro_assembler(); | 3124 RegExpMacroAssembler* assembler = compiler->macro_assembler(); |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3164 RegExpMacroAssembler* assembler = compiler->macro_assembler(); | 3168 RegExpMacroAssembler* assembler = compiler->macro_assembler(); |
| 3165 switch (assertion_type_) { | 3169 switch (assertion_type_) { |
| 3166 case AT_END: { | 3170 case AT_END: { |
| 3167 Label ok; | 3171 Label ok; |
| 3168 assembler->CheckPosition(trace->cp_offset(), &ok); | 3172 assembler->CheckPosition(trace->cp_offset(), &ok); |
| 3169 assembler->GoTo(trace->backtrack()); | 3173 assembler->GoTo(trace->backtrack()); |
| 3170 assembler->Bind(&ok); | 3174 assembler->Bind(&ok); |
| 3171 break; | 3175 break; |
| 3172 } | 3176 } |
| 3173 case AT_START: { | 3177 case AT_START: { |
| 3174 if (trace->at_start() == Trace::FALSE) { | 3178 if (trace->at_start() == Trace::FALSE_VALUE) { |
| 3175 assembler->GoTo(trace->backtrack()); | 3179 assembler->GoTo(trace->backtrack()); |
| 3176 return; | 3180 return; |
| 3177 } | 3181 } |
| 3178 if (trace->at_start() == Trace::UNKNOWN) { | 3182 if (trace->at_start() == Trace::UNKNOWN) { |
| 3179 assembler->CheckNotAtStart(trace->backtrack()); | 3183 assembler->CheckNotAtStart(trace->backtrack()); |
| 3180 Trace at_start_trace = *trace; | 3184 Trace at_start_trace = *trace; |
| 3181 at_start_trace.set_at_start(true); | 3185 at_start_trace.set_at_start(true); |
| 3182 on_success()->Emit(compiler, &at_start_trace); | 3186 on_success()->Emit(compiler, &at_start_trace); |
| 3183 return; | 3187 return; |
| 3184 } | 3188 } |
| (...skipping 796 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3981 greedy_match_trace.set_loop_label(&loop_label); | 3985 greedy_match_trace.set_loop_label(&loop_label); |
| 3982 alternatives_->at(0).node()->Emit(compiler, &greedy_match_trace); | 3986 alternatives_->at(0).node()->Emit(compiler, &greedy_match_trace); |
| 3983 macro_assembler->Bind(&greedy_match_failed); | 3987 macro_assembler->Bind(&greedy_match_failed); |
| 3984 } | 3988 } |
| 3985 | 3989 |
| 3986 Label second_choice; // For use in greedy matches. | 3990 Label second_choice; // For use in greedy matches. |
| 3987 macro_assembler->Bind(&second_choice); | 3991 macro_assembler->Bind(&second_choice); |
| 3988 | 3992 |
| 3989 int first_normal_choice = greedy_loop ? 1 : 0; | 3993 int first_normal_choice = greedy_loop ? 1 : 0; |
| 3990 | 3994 |
| 3991 bool not_at_start = current_trace->at_start() == Trace::FALSE; | 3995 bool not_at_start = current_trace->at_start() == Trace::FALSE_VALUE; |
| 3992 const int kEatsAtLeastNotYetInitialized = -1; | 3996 const int kEatsAtLeastNotYetInitialized = -1; |
| 3993 int eats_at_least = kEatsAtLeastNotYetInitialized; | 3997 int eats_at_least = kEatsAtLeastNotYetInitialized; |
| 3994 | 3998 |
| 3995 bool skip_was_emitted = false; | 3999 bool skip_was_emitted = false; |
| 3996 | 4000 |
| 3997 if (!greedy_loop && choice_count == 2) { | 4001 if (!greedy_loop && choice_count == 2) { |
| 3998 GuardedAlternative alt1 = alternatives_->at(1); | 4002 GuardedAlternative alt1 = alternatives_->at(1); |
| 3999 if (alt1.guards() == NULL || alt1.guards()->length() == 0) { | 4003 if (alt1.guards() == NULL || alt1.guards()->length() == 0) { |
| 4000 RegExpNode* eats_anything_node = alt1.node(); | 4004 RegExpNode* eats_anything_node = alt1.node(); |
| 4001 if (eats_anything_node->GetSuccessorOfOmnivorousTextNode(compiler) == | 4005 if (eats_anything_node->GetSuccessorOfOmnivorousTextNode(compiler) == |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4052 ZoneList<Guard*>* guards = alternative.guards(); | 4056 ZoneList<Guard*>* guards = alternative.guards(); |
| 4053 int guard_count = (guards == NULL) ? 0 : guards->length(); | 4057 int guard_count = (guards == NULL) ? 0 : guards->length(); |
| 4054 Trace new_trace(*current_trace); | 4058 Trace new_trace(*current_trace); |
| 4055 new_trace.set_characters_preloaded(preload_is_current ? | 4059 new_trace.set_characters_preloaded(preload_is_current ? |
| 4056 preload_characters : | 4060 preload_characters : |
| 4057 0); | 4061 0); |
| 4058 if (preload_has_checked_bounds) { | 4062 if (preload_has_checked_bounds) { |
| 4059 new_trace.set_bound_checked_up_to(preload_characters); | 4063 new_trace.set_bound_checked_up_to(preload_characters); |
| 4060 } | 4064 } |
| 4061 new_trace.quick_check_performed()->Clear(); | 4065 new_trace.quick_check_performed()->Clear(); |
| 4062 if (not_at_start_) new_trace.set_at_start(Trace::FALSE); | 4066 if (not_at_start_) new_trace.set_at_start(Trace::FALSE_VALUE); |
| 4063 alt_gen->expects_preload = preload_is_current; | 4067 alt_gen->expects_preload = preload_is_current; |
| 4064 bool generate_full_check_inline = false; | 4068 bool generate_full_check_inline = false; |
| 4065 if (FLAG_regexp_optimization && | 4069 if (FLAG_regexp_optimization && |
| 4066 try_to_emit_quick_check_for_alternative(i) && | 4070 try_to_emit_quick_check_for_alternative(i) && |
| 4067 alternative.node()->EmitQuickCheck(compiler, | 4071 alternative.node()->EmitQuickCheck(compiler, |
| 4068 &new_trace, | 4072 &new_trace, |
| 4069 preload_has_checked_bounds, | 4073 preload_has_checked_bounds, |
| 4070 &alt_gen->possible_success, | 4074 &alt_gen->possible_success, |
| 4071 &alt_gen->quick_check_details, | 4075 &alt_gen->quick_check_details, |
| 4072 i < choice_count - 1)) { | 4076 i < choice_count - 1)) { |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4152 AlternativeGeneration* alt_gen, | 4156 AlternativeGeneration* alt_gen, |
| 4153 int preload_characters, | 4157 int preload_characters, |
| 4154 bool next_expects_preload) { | 4158 bool next_expects_preload) { |
| 4155 if (!alt_gen->possible_success.is_linked()) return; | 4159 if (!alt_gen->possible_success.is_linked()) return; |
| 4156 | 4160 |
| 4157 RegExpMacroAssembler* macro_assembler = compiler->macro_assembler(); | 4161 RegExpMacroAssembler* macro_assembler = compiler->macro_assembler(); |
| 4158 macro_assembler->Bind(&alt_gen->possible_success); | 4162 macro_assembler->Bind(&alt_gen->possible_success); |
| 4159 Trace out_of_line_trace(*trace); | 4163 Trace out_of_line_trace(*trace); |
| 4160 out_of_line_trace.set_characters_preloaded(preload_characters); | 4164 out_of_line_trace.set_characters_preloaded(preload_characters); |
| 4161 out_of_line_trace.set_quick_check_performed(&alt_gen->quick_check_details); | 4165 out_of_line_trace.set_quick_check_performed(&alt_gen->quick_check_details); |
| 4162 if (not_at_start_) out_of_line_trace.set_at_start(Trace::FALSE); | 4166 if (not_at_start_) out_of_line_trace.set_at_start(Trace::FALSE_VALUE); |
| 4163 ZoneList<Guard*>* guards = alternative.guards(); | 4167 ZoneList<Guard*>* guards = alternative.guards(); |
| 4164 int guard_count = (guards == NULL) ? 0 : guards->length(); | 4168 int guard_count = (guards == NULL) ? 0 : guards->length(); |
| 4165 if (next_expects_preload) { | 4169 if (next_expects_preload) { |
| 4166 Label reload_current_char; | 4170 Label reload_current_char; |
| 4167 out_of_line_trace.set_backtrack(&reload_current_char); | 4171 out_of_line_trace.set_backtrack(&reload_current_char); |
| 4168 for (int j = 0; j < guard_count; j++) { | 4172 for (int j = 0; j < guard_count; j++) { |
| 4169 GenerateGuard(macro_assembler, guards->at(j), &out_of_line_trace); | 4173 GenerateGuard(macro_assembler, guards->at(j), &out_of_line_trace); |
| 4170 } | 4174 } |
| 4171 alternative.node()->Emit(compiler, &out_of_line_trace); | 4175 alternative.node()->Emit(compiler, &out_of_line_trace); |
| 4172 macro_assembler->Bind(&reload_current_char); | 4176 macro_assembler->Bind(&reload_current_char); |
| (...skipping 1955 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6128 } | 6132 } |
| 6129 | 6133 |
| 6130 return compiler.Assemble(¯o_assembler, | 6134 return compiler.Assemble(¯o_assembler, |
| 6131 node, | 6135 node, |
| 6132 data->capture_count, | 6136 data->capture_count, |
| 6133 pattern); | 6137 pattern); |
| 6134 } | 6138 } |
| 6135 | 6139 |
| 6136 | 6140 |
| 6137 }} // namespace v8::internal | 6141 }} // namespace v8::internal |
| OLD | NEW |