Commit 9c608b2c authored by erik.corry@gmail.com's avatar erik.corry@gmail.com

Limit how many places we generate code to flush the same actions. This gives a

13% code size reduction in the php regexp with no discernable performance loss.
Review URL: http://codereview.chromium.org/20457

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@1309 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 195753ff
...@@ -1527,6 +1527,13 @@ void Trace::Flush(RegExpCompiler* compiler, RegExpNode* successor) { ...@@ -1527,6 +1527,13 @@ void Trace::Flush(RegExpCompiler* compiler, RegExpNode* successor) {
// Generate deferred actions here along with code to undo them again. // Generate deferred actions here along with code to undo them again.
OutSet affected_registers; OutSet affected_registers;
if (backtrack() != NULL) {
// Here we have a concrete backtrack location. These are set up by choice
// nodes and so they indicate that we have a deferred save of the current
// position which we may need to emit here.
assembler->PushCurrentPosition();
}
int max_register = FindAffectedRegisters(&affected_registers); int max_register = FindAffectedRegisters(&affected_registers);
OutSet registers_to_pop; OutSet registers_to_pop;
OutSet registers_to_clear; OutSet registers_to_clear;
...@@ -1535,12 +1542,6 @@ void Trace::Flush(RegExpCompiler* compiler, RegExpNode* successor) { ...@@ -1535,12 +1542,6 @@ void Trace::Flush(RegExpCompiler* compiler, RegExpNode* successor) {
affected_registers, affected_registers,
&registers_to_pop, &registers_to_pop,
&registers_to_clear); &registers_to_clear);
if (backtrack() != NULL) {
// Here we have a concrete backtrack location. These are set up by choice
// nodes and so they indicate that we have a deferred save of the current
// position which we may need to emit here.
assembler->PushCurrentPosition();
}
if (cp_offset_ != 0) { if (cp_offset_ != 0) {
assembler->AdvanceCurrentPosition(cp_offset_); assembler->AdvanceCurrentPosition(cp_offset_);
} }
...@@ -1553,9 +1554,6 @@ void Trace::Flush(RegExpCompiler* compiler, RegExpNode* successor) { ...@@ -1553,9 +1554,6 @@ void Trace::Flush(RegExpCompiler* compiler, RegExpNode* successor) {
// On backtrack we need to restore state. // On backtrack we need to restore state.
assembler->Bind(&undo); assembler->Bind(&undo);
if (backtrack() != NULL) {
assembler->PopCurrentPosition();
}
RestoreAffectedRegisters(assembler, RestoreAffectedRegisters(assembler,
max_register, max_register,
registers_to_pop, registers_to_pop,
...@@ -1563,6 +1561,7 @@ void Trace::Flush(RegExpCompiler* compiler, RegExpNode* successor) { ...@@ -1563,6 +1561,7 @@ void Trace::Flush(RegExpCompiler* compiler, RegExpNode* successor) {
if (backtrack() == NULL) { if (backtrack() == NULL) {
assembler->Backtrack(); assembler->Backtrack();
} else { } else {
assembler->PopCurrentPosition();
assembler->GoTo(backtrack()); assembler->GoTo(backtrack());
} }
} }
...@@ -3053,10 +3052,6 @@ class AlternativeGenerationList { ...@@ -3053,10 +3052,6 @@ class AlternativeGenerationList {
} }
} }
~AlternativeGenerationList() { ~AlternativeGenerationList() {
for (int i = 0; i < alt_gens_.length(); i++) {
alt_gens_[i]->possible_success.Unuse();
alt_gens_[i]->after.Unuse();
}
for (int i = kAFew; i < alt_gens_.length(); i++) { for (int i = kAFew; i < alt_gens_.length(); i++) {
delete alt_gens_[i]; delete alt_gens_[i];
alt_gens_[i] = NULL; alt_gens_[i] = NULL;
...@@ -3170,6 +3165,12 @@ void ChoiceNode::Emit(RegExpCompiler* compiler, Trace* trace) { ...@@ -3170,6 +3165,12 @@ void ChoiceNode::Emit(RegExpCompiler* compiler, Trace* trace) {
if (limit_result == DONE) return; if (limit_result == DONE) return;
ASSERT(limit_result == CONTINUE); ASSERT(limit_result == CONTINUE);
int new_flush_budget = trace->flush_budget() / choice_count;
if (trace->flush_budget() == 0 && trace->actions() != NULL) {
trace->Flush(compiler, this);
return;
}
RecursionCheck rc(compiler); RecursionCheck rc(compiler);
Trace* current_trace = trace; Trace* current_trace = trace;
...@@ -3278,6 +3279,9 @@ void ChoiceNode::Emit(RegExpCompiler* compiler, Trace* trace) { ...@@ -3278,6 +3279,9 @@ void ChoiceNode::Emit(RegExpCompiler* compiler, Trace* trace) {
generate_full_check_inline = true; generate_full_check_inline = true;
} }
if (generate_full_check_inline) { if (generate_full_check_inline) {
if (new_trace.actions() != NULL) {
new_trace.set_flush_budget(new_flush_budget);
}
for (int j = 0; j < guard_count; j++) { for (int j = 0; j < guard_count; j++) {
GenerateGuard(macro_assembler, guards->at(j), &new_trace); GenerateGuard(macro_assembler, guards->at(j), &new_trace);
} }
...@@ -3294,13 +3298,21 @@ void ChoiceNode::Emit(RegExpCompiler* compiler, Trace* trace) { ...@@ -3294,13 +3298,21 @@ void ChoiceNode::Emit(RegExpCompiler* compiler, Trace* trace) {
macro_assembler->AdvanceCurrentPosition(-text_length); macro_assembler->AdvanceCurrentPosition(-text_length);
macro_assembler->GoTo(&second_choice); macro_assembler->GoTo(&second_choice);
} }
// At this point we need to generate slow checks for the alternatives where // At this point we need to generate slow checks for the alternatives where
// 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.
for (int i = first_normal_choice; i < choice_count - 1; i++) { for (int i = first_normal_choice; i < choice_count - 1; i++) {
AlternativeGeneration* alt_gen = alt_gens.at(i); AlternativeGeneration* alt_gen = alt_gens.at(i);
Trace new_trace(*current_trace);
// If there are actions to be flushed we have to limit how many times
// they are flushed. Take the budget of the parent trace and distribute
// it fairly amongst the children.
if (new_trace.actions() != NULL) {
new_trace.set_flush_budget(new_flush_budget);
}
EmitOutOfLineContinuation(compiler, EmitOutOfLineContinuation(compiler,
current_trace, &new_trace,
alternatives_->at(i), alternatives_->at(i),
alt_gen, alt_gen,
preload_characters, preload_characters,
......
...@@ -1180,6 +1180,7 @@ class Trace { ...@@ -1180,6 +1180,7 @@ class Trace {
loop_label_(NULL), loop_label_(NULL),
characters_preloaded_(0), characters_preloaded_(0),
bound_checked_up_to_(0), bound_checked_up_to_(0),
flush_budget_(100),
at_start_(UNKNOWN) { } at_start_(UNKNOWN) { }
// End the trace. This involves flushing the deferred actions in the trace // End the trace. This involves flushing the deferred actions in the trace
...@@ -1215,6 +1216,7 @@ class Trace { ...@@ -1215,6 +1216,7 @@ class Trace {
RegExpNode* stop_node() { return stop_node_; } RegExpNode* stop_node() { return stop_node_; }
int characters_preloaded() { return characters_preloaded_; } int characters_preloaded() { return characters_preloaded_; }
int bound_checked_up_to() { return bound_checked_up_to_; } int bound_checked_up_to() { return bound_checked_up_to_; }
int flush_budget() { return flush_budget_; }
QuickCheckDetails* quick_check_performed() { return &quick_check_performed_; } QuickCheckDetails* quick_check_performed() { return &quick_check_performed_; }
bool mentions_reg(int reg); bool mentions_reg(int reg);
// Returns true if a deferred position store exists to the specified // Returns true if a deferred position store exists to the specified
...@@ -1233,6 +1235,7 @@ class Trace { ...@@ -1233,6 +1235,7 @@ class Trace {
void set_loop_label(Label* label) { loop_label_ = label; } void set_loop_label(Label* label) { loop_label_ = label; }
void set_characters_preloaded(int cpre) { characters_preloaded_ = cpre; } void set_characters_preloaded(int cpre) { characters_preloaded_ = cpre; }
void set_bound_checked_up_to(int to) { bound_checked_up_to_ = to; } void set_bound_checked_up_to(int to) { bound_checked_up_to_ = to; }
void set_flush_budget(int to) { flush_budget_ = to; }
void set_quick_check_performed(QuickCheckDetails* d) { void set_quick_check_performed(QuickCheckDetails* d) {
quick_check_performed_ = *d; quick_check_performed_ = *d;
} }
...@@ -1257,6 +1260,7 @@ class Trace { ...@@ -1257,6 +1260,7 @@ class Trace {
int characters_preloaded_; int characters_preloaded_;
int bound_checked_up_to_; int bound_checked_up_to_;
QuickCheckDetails quick_check_performed_; QuickCheckDetails quick_check_performed_;
int flush_budget_;
TriBool at_start_; TriBool at_start_;
}; };
......
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