Commit 7bbae6d9 authored by erik.corry@gmail.com's avatar erik.corry@gmail.com

Clean up regexp code gen a little

R=yangguo@chromium.org
BUG=

Review URL: https://codereview.chromium.org/565043003

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@23958 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 357d7c42
...@@ -2437,6 +2437,7 @@ bool QuickCheckDetails::Rationalize(bool asc) { ...@@ -2437,6 +2437,7 @@ bool QuickCheckDetails::Rationalize(bool asc) {
bool RegExpNode::EmitQuickCheck(RegExpCompiler* compiler, bool RegExpNode::EmitQuickCheck(RegExpCompiler* compiler,
Trace* bounds_check_trace,
Trace* trace, Trace* trace,
bool preload_has_checked_bounds, bool preload_has_checked_bounds,
Label* on_possible_success, Label* on_possible_success,
...@@ -2455,8 +2456,13 @@ bool RegExpNode::EmitQuickCheck(RegExpCompiler* compiler, ...@@ -2455,8 +2456,13 @@ bool RegExpNode::EmitQuickCheck(RegExpCompiler* compiler,
RegExpMacroAssembler* assembler = compiler->macro_assembler(); RegExpMacroAssembler* assembler = compiler->macro_assembler();
if (trace->characters_preloaded() != details->characters()) { if (trace->characters_preloaded() != details->characters()) {
DCHECK(trace->cp_offset() == bounds_check_trace->cp_offset());
// We are attempting to preload the minimum number of characters
// any choice would eat, so if the bounds check fails, then none of the
// choices can succeed, so we can just immediately backtrack, rather
// than go to the next choice.
assembler->LoadCurrentCharacter(trace->cp_offset(), assembler->LoadCurrentCharacter(trace->cp_offset(),
trace->backtrack(), bounds_check_trace->backtrack(),
!preload_has_checked_bounds, !preload_has_checked_bounds,
details->characters()); details->characters());
} }
...@@ -3855,10 +3861,12 @@ void BoyerMooreLookahead::EmitSkipInstructions(RegExpMacroAssembler* masm) { ...@@ -3855,10 +3861,12 @@ void BoyerMooreLookahead::EmitSkipInstructions(RegExpMacroAssembler* masm) {
* \ F V * \ F V
* \-----S4 * \-----S4
* *
* For greedy loops we reverse our expectation and expect to match rather * For greedy loops we push the current position, then generate the code that
* than fail. Therefore we want the loop code to look like this (U is the * eats the input specially in EmitGreedyLoop. The other choice (the
* unwind code that steps back in the greedy loop). The following alternatives * continuation) is generated by the normal code in EmitChoices, and steps back
* look the same as above. * in the input to the starting position when it fails to match. The loop code
* looks like this (U is the unwind code that steps back in the greedy loop).
*
* _____ * _____
* / \ * / \
* V | * V |
...@@ -3867,20 +3875,14 @@ void BoyerMooreLookahead::EmitSkipInstructions(RegExpMacroAssembler* masm) { ...@@ -3867,20 +3875,14 @@ void BoyerMooreLookahead::EmitSkipInstructions(RegExpMacroAssembler* masm) {
* / |S | * / |S |
* F/ \_____/ * F/ \_____/
* / * /
* |<----------- * |<-----
* | \ * | \
* V \ * V |S
* Q2 ---> S2 \ * Q2 ---> U----->backtrack
* | S / | * | F /
* F| / | * S| /
* | F/ | * V F /
* | / | * S2--/
* | R |
* | / |
* F VL |
* <------U |
* back |S |
* \______________/
*/ */
GreedyLoopState::GreedyLoopState(bool not_at_start) { GreedyLoopState::GreedyLoopState(bool not_at_start) {
...@@ -3966,7 +3968,6 @@ void ChoiceNode::Emit(RegExpCompiler* compiler, Trace* trace) { ...@@ -3966,7 +3968,6 @@ void ChoiceNode::Emit(RegExpCompiler* compiler, Trace* trace) {
&alt_gens, &alt_gens,
0, 0,
trace, trace,
false, // Not greedy loop.
&preload); &preload);
} }
...@@ -3974,7 +3975,7 @@ void ChoiceNode::Emit(RegExpCompiler* compiler, Trace* trace) { ...@@ -3974,7 +3975,7 @@ void ChoiceNode::Emit(RegExpCompiler* compiler, Trace* trace) {
// the quick check was inlined. We can recognize these because the associated // the quick check was inlined. We can recognize these because the associated
// label was bound. // label was bound.
int new_flush_budget = trace->flush_budget() / choice_count; int new_flush_budget = trace->flush_budget() / choice_count;
for (int i = 0; i < choice_count - 1; i++) { for (int i = 0; i < choice_count; i++) {
AlternativeGeneration* alt_gen = alt_gens.at(i); AlternativeGeneration* alt_gen = alt_gens.at(i);
Trace new_trace(*trace); Trace new_trace(*trace);
// If there are actions to be flushed we have to limit how many times // If there are actions to be flushed we have to limit how many times
...@@ -3983,12 +3984,14 @@ void ChoiceNode::Emit(RegExpCompiler* compiler, Trace* trace) { ...@@ -3983,12 +3984,14 @@ void ChoiceNode::Emit(RegExpCompiler* compiler, Trace* trace) {
if (new_trace.actions() != NULL) { if (new_trace.actions() != NULL) {
new_trace.set_flush_budget(new_flush_budget); new_trace.set_flush_budget(new_flush_budget);
} }
bool next_expects_preload =
i == choice_count - 1 ? false : alt_gens.at(i + 1)->expects_preload;
EmitOutOfLineContinuation(compiler, EmitOutOfLineContinuation(compiler,
&new_trace, &new_trace,
alternatives_->at(i), alternatives_->at(i),
alt_gen, alt_gen,
preload.preload_characters_, preload.preload_characters_,
alt_gens.at(i + 1)->expects_preload); next_expects_preload);
} }
} }
...@@ -4029,7 +4032,6 @@ Trace* ChoiceNode::EmitGreedyLoop(RegExpCompiler* compiler, ...@@ -4029,7 +4032,6 @@ Trace* ChoiceNode::EmitGreedyLoop(RegExpCompiler* compiler,
alt_gens, alt_gens,
1, 1,
new_trace, new_trace,
true, // Is greedy loop.
preload); preload);
macro_assembler->Bind(greedy_loop_state->label()); macro_assembler->Bind(greedy_loop_state->label());
...@@ -4096,7 +4098,6 @@ void ChoiceNode::EmitChoices(RegExpCompiler* compiler, ...@@ -4096,7 +4098,6 @@ void ChoiceNode::EmitChoices(RegExpCompiler* compiler,
AlternativeGenerationList* alt_gens, AlternativeGenerationList* alt_gens,
int first_choice, int first_choice,
Trace* trace, Trace* trace,
bool is_greedy_loop,
PreloadState* preload) { PreloadState* preload) {
RegExpMacroAssembler* macro_assembler = compiler->macro_assembler(); RegExpMacroAssembler* macro_assembler = compiler->macro_assembler();
SetUpPreLoad(compiler, trace, preload); SetUpPreLoad(compiler, trace, preload);
...@@ -4109,6 +4110,7 @@ void ChoiceNode::EmitChoices(RegExpCompiler* compiler, ...@@ -4109,6 +4110,7 @@ void ChoiceNode::EmitChoices(RegExpCompiler* compiler,
for (int i = first_choice; i < choice_count; i++) { for (int i = first_choice; i < choice_count; i++) {
bool is_last = i == choice_count - 1; bool is_last = i == choice_count - 1;
bool fall_through_on_failure = !is_last;
GuardedAlternative alternative = alternatives_->at(i); GuardedAlternative alternative = alternatives_->at(i);
AlternativeGeneration* alt_gen = alt_gens->at(i); AlternativeGeneration* alt_gen = alt_gens->at(i);
alt_gen->quick_check_details.set_characters(preload->preload_characters_); alt_gen->quick_check_details.set_characters(preload->preload_characters_);
...@@ -4123,23 +4125,26 @@ void ChoiceNode::EmitChoices(RegExpCompiler* compiler, ...@@ -4123,23 +4125,26 @@ void ChoiceNode::EmitChoices(RegExpCompiler* compiler,
} }
new_trace.quick_check_performed()->Clear(); new_trace.quick_check_performed()->Clear();
if (not_at_start_) new_trace.set_at_start(Trace::FALSE_VALUE); if (not_at_start_) new_trace.set_at_start(Trace::FALSE_VALUE);
if (!is_last) {
new_trace.set_backtrack(&alt_gen->after);
}
alt_gen->expects_preload = preload->preload_is_current_; alt_gen->expects_preload = preload->preload_is_current_;
bool generate_full_check_inline = false; bool generate_full_check_inline = false;
if (FLAG_regexp_optimization && if (FLAG_regexp_optimization &&
try_to_emit_quick_check_for_alternative(i == 0) && try_to_emit_quick_check_for_alternative(i == 0) &&
alternative.node()->EmitQuickCheck(compiler, alternative.node()->EmitQuickCheck(compiler,
trace,
&new_trace, &new_trace,
preload->preload_has_checked_bounds_, preload->preload_has_checked_bounds_,
&alt_gen->possible_success, &alt_gen->possible_success,
&alt_gen->quick_check_details, &alt_gen->quick_check_details,
!is_last)) { fall_through_on_failure)) {
// Quick check was generated for this choice. // Quick check was generated for this choice.
preload->preload_is_current_ = true; preload->preload_is_current_ = true;
preload->preload_has_checked_bounds_ = true; preload->preload_has_checked_bounds_ = true;
// On the last choice in the ChoiceNode we generated the quick // If we generated the quick check to fall through on possible success,
// check to fall through on possible success. So now we need to // we now need to generate the full check inline.
// generate the full check inline. if (!fall_through_on_failure) {
if (is_last) {
macro_assembler->Bind(&alt_gen->possible_success); macro_assembler->Bind(&alt_gen->possible_success);
new_trace.set_quick_check_performed(&alt_gen->quick_check_details); new_trace.set_quick_check_performed(&alt_gen->quick_check_details);
new_trace.set_characters_preloaded(preload->preload_characters_); new_trace.set_characters_preloaded(preload->preload_characters_);
...@@ -4147,9 +4152,9 @@ void ChoiceNode::EmitChoices(RegExpCompiler* compiler, ...@@ -4147,9 +4152,9 @@ void ChoiceNode::EmitChoices(RegExpCompiler* compiler,
generate_full_check_inline = true; generate_full_check_inline = true;
} }
} else if (alt_gen->quick_check_details.cannot_match()) { } else if (alt_gen->quick_check_details.cannot_match()) {
if (is_last && !is_greedy_loop) { if (!fall_through_on_failure) {
macro_assembler->GoTo(trace->backtrack()); macro_assembler->GoTo(trace->backtrack());
} // Else just fall through to the next test. }
continue; continue;
} else { } else {
// No quick check was generated. Put the full code here. // No quick check was generated. Put the full code here.
...@@ -4161,9 +4166,6 @@ void ChoiceNode::EmitChoices(RegExpCompiler* compiler, ...@@ -4161,9 +4166,6 @@ void ChoiceNode::EmitChoices(RegExpCompiler* compiler,
alt_gen->expects_preload = false; alt_gen->expects_preload = false;
new_trace.InvalidateCurrentCharacter(); new_trace.InvalidateCurrentCharacter();
} }
if (!is_last) {
new_trace.set_backtrack(&alt_gen->after);
}
generate_full_check_inline = true; generate_full_check_inline = true;
} }
if (generate_full_check_inline) { if (generate_full_check_inline) {
......
...@@ -590,6 +590,7 @@ class RegExpNode: public ZoneObject { ...@@ -590,6 +590,7 @@ class RegExpNode: public ZoneObject {
// Falls through on certain failure, jumps to the label on possible success. // Falls through on certain failure, jumps to the label on possible success.
// If the node cannot make a quick check it does nothing and returns false. // If the node cannot make a quick check it does nothing and returns false.
bool EmitQuickCheck(RegExpCompiler* compiler, bool EmitQuickCheck(RegExpCompiler* compiler,
Trace* bounds_check_trace,
Trace* trace, Trace* trace,
bool preload_has_checked_bounds, bool preload_has_checked_bounds,
Label* on_possible_success, Label* on_possible_success,
...@@ -1118,7 +1119,6 @@ class ChoiceNode: public RegExpNode { ...@@ -1118,7 +1119,6 @@ class ChoiceNode: public RegExpNode {
AlternativeGenerationList* alt_gens, AlternativeGenerationList* alt_gens,
int first_choice, int first_choice,
Trace* trace, Trace* trace,
bool is_greedy_loop,
PreloadState* preloads); PreloadState* preloads);
DispatchTable* table_; DispatchTable* table_;
// If true, this node is never checked at the start of the input. // If true, this node is never checked at the start of the input.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment