summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJosh Stone <joshua.i.stone@intel.com>2008-06-13 19:24:49 -0700
committerJosh Stone <joshua.i.stone@intel.com>2008-06-13 19:37:09 -0700
commit9d0808b420815955053cd503e9fc2ab1180f70b6 (patch)
tree1c1426e55cb3b1f065dc5718b61912c43018e75e
parent12363146250f7271a78c9d63be636605b4bccf61 (diff)
downloadsystemtap-steved-9d0808b420815955053cd503e9fc2ab1180f70b6.tar.gz
systemtap-steved-9d0808b420815955053cd503e9fc2ab1180f70b6.tar.xz
systemtap-steved-9d0808b420815955053cd503e9fc2ab1180f70b6.zip
Reduce the number of actionremaining checks.
The generated code now only checks the actionremaining count at control points and after executing a large sequence of statements.
-rw-r--r--ChangeLog3
-rw-r--r--translate.cxx85
2 files changed, 45 insertions, 43 deletions
diff --git a/ChangeLog b/ChangeLog
index 7f5c93e1..75b53783 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,6 +2,9 @@
* translate.cxx: Jump out directly after setting last_error, rather
than passively checking last_error everywhere.
+ * translate.cxx: Only make actionremaining checks at control points,
+ i.e. roughly at the end of basic blocks, or after executing a few
+ statements in a row.
2008-06-13 Frank Ch. Eigler <fche@elastic.org>
diff --git a/translate.cxx b/translate.cxx
index 3a671433..2c1cb84c 100644
--- a/translate.cxx
+++ b/translate.cxx
@@ -43,6 +43,7 @@ struct c_unparser: public unparser, public visitor
functiondecl* current_function;
unsigned tmpvar_counter;
unsigned label_counter;
+ unsigned action_counter;
bool probe_or_function_needs_deref_fault_handler;
varuse_collecting_visitor vcv_needs_global_locks;
@@ -110,7 +111,7 @@ struct c_unparser: public unparser, public visitor
void collect_map_index_types(vector<vardecl* > const & vars,
set< pair<vector<exp_type>, exp_type> > & types);
- void visit_statement (statement* s, unsigned actions, bool stmtize);
+ void record_actions (unsigned actions, bool update=false);
void visit_block (block* s);
void visit_embeddedcode (embeddedcode* s);
@@ -1341,6 +1342,7 @@ c_unparser::emit_function (functiondecl* v)
this->current_probe = 0;
this->current_function = v;
this->tmpvar_counter = 0;
+ this->action_counter = 0;
o->newline()
<< "struct function_" << c_varname (v->name) << "_locals * "
@@ -1389,6 +1391,8 @@ c_unparser::emit_function (functiondecl* v)
this->current_function = 0;
+ record_actions(0, true);
+
if (this->probe_or_function_needs_deref_fault_handler) {
// Emit this handler only if the body included a
// print/printf/etc. using a string or memory buffer!
@@ -1418,6 +1422,7 @@ c_unparser::emit_probe (derived_probe* v)
this->current_function = 0;
this->current_probe = v;
this->tmpvar_counter = 0;
+ this->action_counter = 0;
// If we about to emit a probe that is exactly the same as another
// probe previously emitted, make the second probe just call the
@@ -1537,6 +1542,14 @@ c_unparser::emit_probe (derived_probe* v)
v->body->visit (this);
+ record_actions(0, true);
+
+ if (this->probe_or_function_needs_deref_fault_handler) {
+ // Emit this handler only if the body included a
+ // print/printf/etc. using a string or memory buffer!
+ o->newline() << "CATCH_DEREF_FAULT ();";
+ }
+
o->newline(-1) << "out:";
// NB: no need to uninitialize locals, except if arrays/stats can
// someday be local
@@ -1548,14 +1561,6 @@ c_unparser::emit_probe (derived_probe* v)
if (v->needs_global_locks ())
emit_unlocks (vut);
- if (this->probe_or_function_needs_deref_fault_handler) {
- // Emit this handler only if the body included a
- // print/printf/etc. using a string or memory buffer!
- o->newline() << "return;";
- o->newline() << "CATCH_DEREF_FAULT ();";
- o->newline() << "goto out;";
- }
-
o->newline(-1) << "}\n";
}
@@ -2196,27 +2201,24 @@ c_unparser::getiter(symbol *s)
}
-
-// An artificial common "header" for each statement. This is where
-// activity counts limits and error state early exits are enforced.
+// Queue up some actions to remove from actionremaining. Set update=true at
+// the end of basic blocks to actually update actionremaining and check it
+// against MAXACTION.
void
-c_unparser::visit_statement (statement *s, unsigned actions, bool stmtize)
+c_unparser::record_actions (unsigned actions, bool update)
{
- if (s)
- {
- assert (s->tok);
- if (stmtize)
- o->newline() << "c->last_stmt = " << lex_cast_qstring(*s->tok) << ";";
- }
+ action_counter += actions;
- if (actions > 0)
+ // Update if needed, or after queueing up a few actions, in case of very
+ // large code sequences.
+ if ((update && action_counter > 0) || action_counter >= 10/*<-arbitrary*/)
{
- o->newline() << "c->actionremaining -= " << actions << ";";
- // XXX: This check is inserted too frequently.
+ o->newline() << "c->actionremaining -= " << action_counter << ";";
o->newline() << "if (unlikely (c->actionremaining <= 0)) {";
o->newline(1) << "c->last_error = \"MAXACTION exceeded\";";
o->newline() << "goto out;";
o->newline(-1) << "}";
+ action_counter = 0;
}
}
@@ -2246,12 +2248,6 @@ c_unparser::visit_block (block *s)
void
c_unparser::visit_embeddedcode (embeddedcode *s)
{
- // visit_statement (s, 1, true);
- //
- // NB: this is not necessary, since this can occur only at the top
- // level of a function (so no errors can be pending), and the
- // action-count is already incremented at the point of call.
-
o->newline() << "{";
o->newline(1) << s->code;
o->newline(-1) << "}";
@@ -2268,17 +2264,17 @@ c_unparser::visit_null_statement (null_statement *)
void
c_unparser::visit_expr_statement (expr_statement *s)
{
- visit_statement (s, 1, false);
o->newline() << "(void) ";
s->value->visit (this);
o->line() << ";";
+ record_actions(1);
}
void
c_unparser::visit_if_statement (if_statement *s)
{
- visit_statement (s, 1, false);
+ record_actions(1, true);
o->newline() << "if (";
o->indent (1);
s->condition->visit (this);
@@ -2286,12 +2282,14 @@ c_unparser::visit_if_statement (if_statement *s)
o->line() << ") {";
o->indent (1);
s->thenblock->visit (this);
+ record_actions(0, true);
o->newline(-1) << "}";
if (s->elseblock)
{
o->newline() << "else {";
o->indent (1);
s->elseblock->visit (this);
+ record_actions(0, true);
o->newline(-1) << "}";
}
}
@@ -2341,8 +2339,6 @@ c_tmpcounter::visit_for_loop (for_loop *s)
void
c_unparser::visit_for_loop (for_loop *s)
{
- visit_statement (s, 1, false);
-
string ctr = stringify (label_counter++);
string toplabel = "top_" + ctr;
string contlabel = "continue_" + ctr;
@@ -2350,6 +2346,7 @@ c_unparser::visit_for_loop (for_loop *s)
// initialization
if (s->init) s->init->visit (this);
+ record_actions(1, true);
// condition
o->newline(-1) << toplabel << ":";
@@ -2358,7 +2355,7 @@ c_unparser::visit_for_loop (for_loop *s)
// Equivalently, it can stand for the evaluation of the condition
// expression.
o->indent(1);
- visit_statement (0, 1, false);
+ record_actions(1);
o->newline() << "if (! (";
if (s->cond->type != pe_long)
@@ -2370,6 +2367,7 @@ c_unparser::visit_for_loop (for_loop *s)
loop_break_labels.push_back (breaklabel);
loop_continue_labels.push_back (contlabel);
s->block->visit (this);
+ record_actions(0, true);
loop_break_labels.pop_back ();
loop_continue_labels.pop_back ();
@@ -2490,8 +2488,6 @@ c_unparser::visit_foreach_loop (foreach_loop *s)
if (array)
{
- visit_statement (s, 1, false);
-
mapvar mv = getmap (array->referent, s->tok);
itervar iv = getiter (array);
vector<var> keys;
@@ -2586,6 +2582,8 @@ c_unparser::visit_foreach_loop (foreach_loop *s)
o->newline() << *limitv << " = 0LL;";
}
+ record_actions(1, true);
+
// condition
o->newline(-1) << toplabel << ":";
@@ -2593,7 +2591,7 @@ c_unparser::visit_foreach_loop (foreach_loop *s)
// Equivalently, it can stand for the evaluation of the
// condition expression.
o->indent(1);
- visit_statement (0, 1, false);
+ record_actions(1);
o->newline() << "if (! (" << iv << ")) goto " << breaklabel << ";";
@@ -2621,6 +2619,7 @@ c_unparser::visit_foreach_loop (foreach_loop *s)
c_assign (v, iv.get_key (v.type(), i), s->tok);
}
s->block->visit (this);
+ record_actions(0, true);
o->newline(-1) << "}";
loop_break_labels.pop_back ();
loop_continue_labels.pop_back ();
@@ -2665,6 +2664,7 @@ c_unparser::visit_foreach_loop (foreach_loop *s)
}
// XXX: break / continue don't work here yet
+ record_actions(1, true);
o->newline() << "for (" << bucketvar << " = 0; "
<< bucketvar << " < " << v.buckets() << "; "
<< bucketvar << "++) { ";
@@ -2682,6 +2682,7 @@ c_unparser::visit_foreach_loop (foreach_loop *s)
}
s->block->visit (this);
+ record_actions(1, true);
o->newline(-1) << "}";
}
}
@@ -2690,8 +2691,6 @@ c_unparser::visit_foreach_loop (foreach_loop *s)
void
c_unparser::visit_return_statement (return_statement* s)
{
- visit_statement (s, 1, false);
-
if (current_function == 0)
throw semantic_error ("cannot 'return' from probe", s->tok);
@@ -2700,6 +2699,7 @@ c_unparser::visit_return_statement (return_statement* s)
"vs", s->tok);
c_assign ("l->__retvalue", s->value, "return value");
+ record_actions(1, true);
o->newline() << "goto out;";
}
@@ -2707,11 +2707,10 @@ c_unparser::visit_return_statement (return_statement* s)
void
c_unparser::visit_next_statement (next_statement* s)
{
- visit_statement (s, 1, false);
-
if (current_probe == 0)
throw semantic_error ("cannot 'next' from function", s->tok);
+ record_actions(1, true);
o->newline() << "goto out;";
}
@@ -2839,19 +2838,19 @@ c_tmpcounter::visit_delete_statement (delete_statement* s)
void
c_unparser::visit_delete_statement (delete_statement* s)
{
- visit_statement (s, 1, false);
delete_statement_operand_visitor dv (this);
s->value->visit (&dv);
+ record_actions(1);
}
void
c_unparser::visit_break_statement (break_statement* s)
{
- visit_statement (s, 1, false);
if (loop_break_labels.size() == 0)
throw semantic_error ("cannot 'break' outside loop", s->tok);
+ record_actions(1, true);
string label = loop_break_labels[loop_break_labels.size()-1];
o->newline() << "goto " << label << ";";
}
@@ -2860,10 +2859,10 @@ c_unparser::visit_break_statement (break_statement* s)
void
c_unparser::visit_continue_statement (continue_statement* s)
{
- visit_statement (s, 1, false);
if (loop_continue_labels.size() == 0)
throw semantic_error ("cannot 'continue' outside loop", s->tok);
+ record_actions(1, true);
string label = loop_continue_labels[loop_continue_labels.size()-1];
o->newline() << "goto " << label << ";";
}