From 4ed05b152284d9d4b8545f6e70c57ebdcd993f46 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Thu, 5 Feb 2009 13:08:44 -0800 Subject: Simplify require() and provide() * staptree.h (require, provide): Simplify stack operations with less pointer magic, and move to be deep_copy_visitor members. * staptree.h (deep_copy_visitor::deep_copy): Templatize * staptree.cxx, tapsets.cxx: Refactor require/provide callers --- ChangeLog | 7 ++ staptree.cxx | 217 ++++++++++++++++++++++------------------------------------- staptree.h | 54 ++++++++------- tapsets.cxx | 52 +++++++------- 4 files changed, 144 insertions(+), 186 deletions(-) diff --git a/ChangeLog b/ChangeLog index 8258c422..324d6cb3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2009-02-05 Josh Stone + + * staptree.h (require, provide): Simplify stack operations with less + pointer magic, and move to be deep_copy_visitor members. + * staptree.h (deep_copy_visitor::deep_copy): Templatize + * staptree.cxx, tapsets.cxx: Refactor require/provide callers + 2009-02-04 Mark Wielaard * NEWS: process().mark(), sys/sdt.h and dtrace compatibility script. diff --git a/staptree.cxx b/staptree.cxx index cc618111..869af80a 100644 --- a/staptree.cxx +++ b/staptree.cxx @@ -2103,12 +2103,8 @@ deep_copy_visitor::visit_block (block* s) block* n = new block; n->tok = s->tok; for (unsigned i = 0; i < s->statements.size(); ++i) - { - statement* ns; - require (this, &ns, s->statements[i]); - n->statements.push_back(ns); - } - provide (this, n); + n->statements.push_back(require (s->statements[i])); + provide (n); } void @@ -2117,7 +2113,7 @@ deep_copy_visitor::visit_embeddedcode (embeddedcode* s) embeddedcode* n = new embeddedcode; n->tok = s->tok; n->code = s->code; - provide (this, n); + provide (n); } void @@ -2125,7 +2121,7 @@ deep_copy_visitor::visit_null_statement (null_statement* s) { null_statement* n = new null_statement; n->tok = s->tok; - provide (this, n); + provide (n); } void @@ -2133,8 +2129,8 @@ deep_copy_visitor::visit_expr_statement (expr_statement* s) { expr_statement* n = new expr_statement; n->tok = s->tok; - require (this, &(n->value), s->value); - provide (this, n); + n->value = require (s->value); + provide (n); } void @@ -2142,10 +2138,10 @@ deep_copy_visitor::visit_if_statement (if_statement* s) { if_statement* n = new if_statement; n->tok = s->tok; - require (this, &(n->condition), s->condition); - require (this, &(n->thenblock), s->thenblock); - require (this, &(n->elseblock), s->elseblock); - provide (this, n); + n->condition = require (s->condition); + n->thenblock = require (s->thenblock); + n->elseblock = require (s->elseblock); + provide (n); } void @@ -2153,11 +2149,11 @@ deep_copy_visitor::visit_for_loop (for_loop* s) { for_loop* n = new for_loop; n->tok = s->tok; - require (this, &(n->init), s->init); - require (this, &(n->cond), s->cond); - require (this, &(n->incr), s->incr); - require (this, &(n->block), s->block); - provide (this, n); + n->init = require (s->init); + n->cond = require (s->cond); + n->incr = require (s->incr); + n->block = require (s->block); + provide (n); } void @@ -2166,20 +2162,16 @@ deep_copy_visitor::visit_foreach_loop (foreach_loop* s) foreach_loop* n = new foreach_loop; n->tok = s->tok; for (unsigned i = 0; i < s->indexes.size(); ++i) - { - symbol* sym; - require (this, &sym, s->indexes[i]); - n->indexes.push_back(sym); - } + n->indexes.push_back(require (s->indexes[i])); - require (this, &(n->base), s->base); + n->base = require (s->base); n->sort_direction = s->sort_direction; n->sort_column = s->sort_column; - require (this, &(n->limit), s->limit); + n->limit = require (s->limit); - require (this, &(n->block), s->block); - provide (this, n); + n->block = require (s->block); + provide (n); } void @@ -2187,8 +2179,8 @@ deep_copy_visitor::visit_return_statement (return_statement* s) { return_statement* n = new return_statement; n->tok = s->tok; - require (this, &(n->value), s->value); - provide (this, n); + n->value = require (s->value); + provide (n); } void @@ -2196,8 +2188,8 @@ deep_copy_visitor::visit_delete_statement (delete_statement* s) { delete_statement* n = new delete_statement; n->tok = s->tok; - require (this, &(n->value), s->value); - provide (this, n); + n->value = require (s->value); + provide (n); } void @@ -2205,7 +2197,7 @@ deep_copy_visitor::visit_next_statement (next_statement* s) { next_statement* n = new next_statement; n->tok = s->tok; - provide (this, n); + provide (n); } void @@ -2213,7 +2205,7 @@ deep_copy_visitor::visit_break_statement (break_statement* s) { break_statement* n = new break_statement; n->tok = s->tok; - provide (this, n); + provide (n); } void @@ -2221,7 +2213,7 @@ deep_copy_visitor::visit_continue_statement (continue_statement* s) { continue_statement* n = new continue_statement; n->tok = s->tok; - provide (this, n); + provide (n); } void @@ -2229,7 +2221,7 @@ deep_copy_visitor::visit_literal_string (literal_string* e) { literal_string* n = new literal_string(e->value); n->tok = e->tok; - provide (this, n); + provide (n); } void @@ -2237,7 +2229,7 @@ deep_copy_visitor::visit_literal_number (literal_number* e) { literal_number* n = new literal_number(e->value); n->tok = e->tok; - provide (this, n); + provide (n); } void @@ -2246,9 +2238,9 @@ deep_copy_visitor::visit_binary_expression (binary_expression* e) binary_expression* n = new binary_expression; n->op = e->op; n->tok = e->tok; - require (this, &(n->left), e->left); - require (this, &(n->right), e->right); - provide (this, n); + n->left = require (e->left); + n->right = require (e->right); + provide (n); } void @@ -2257,8 +2249,8 @@ deep_copy_visitor::visit_unary_expression (unary_expression* e) unary_expression* n = new unary_expression; n->op = e->op; n->tok = e->tok; - require (this, &(n->operand), e->operand); - provide (this, n); + n->operand = require (e->operand); + provide (n); } void @@ -2267,8 +2259,8 @@ deep_copy_visitor::visit_pre_crement (pre_crement* e) pre_crement* n = new pre_crement; n->op = e->op; n->tok = e->tok; - require (this, &(n->operand), e->operand); - provide (this, n); + n->operand = require (e->operand); + provide (n); } void @@ -2277,8 +2269,8 @@ deep_copy_visitor::visit_post_crement (post_crement* e) post_crement* n = new post_crement; n->op = e->op; n->tok = e->tok; - require (this, &(n->operand), e->operand); - provide (this, n); + n->operand = require (e->operand); + provide (n); } @@ -2288,9 +2280,9 @@ deep_copy_visitor::visit_logical_or_expr (logical_or_expr* e) logical_or_expr* n = new logical_or_expr; n->op = e->op; n->tok = e->tok; - require (this, &(n->left), e->left); - require (this, &(n->right), e->right); - provide (this, n); + n->left = require (e->left); + n->right = require (e->right); + provide (n); } void @@ -2299,9 +2291,9 @@ deep_copy_visitor::visit_logical_and_expr (logical_and_expr* e) logical_and_expr* n = new logical_and_expr; n->op = e->op; n->tok = e->tok; - require (this, &(n->left), e->left); - require (this, &(n->right), e->right); - provide (this, n); + n->left = require (e->left); + n->right = require (e->right); + provide (n); } void @@ -2309,8 +2301,8 @@ deep_copy_visitor::visit_array_in (array_in* e) { array_in* n = new array_in; n->tok = e->tok; - require (this, &(n->operand), e->operand); - provide (this, n); + n->operand = require (e->operand); + provide (n); } void @@ -2319,9 +2311,9 @@ deep_copy_visitor::visit_comparison (comparison* e) comparison* n = new comparison; n->op = e->op; n->tok = e->tok; - require (this, &(n->left), e->left); - require (this, &(n->right), e->right); - provide (this, n); + n->left = require (e->left); + n->right = require (e->right); + provide (n); } void @@ -2330,9 +2322,9 @@ deep_copy_visitor::visit_concatenation (concatenation* e) concatenation* n = new concatenation; n->op = e->op; n->tok = e->tok; - require (this, &(n->left), e->left); - require (this, &(n->right), e->right); - provide (this, n); + n->left = require (e->left); + n->right = require (e->right); + provide (n); } void @@ -2340,10 +2332,10 @@ deep_copy_visitor::visit_ternary_expression (ternary_expression* e) { ternary_expression* n = new ternary_expression; n->tok = e->tok; - require (this, &(n->cond), e->cond); - require (this, &(n->truevalue), e->truevalue); - require (this, &(n->falsevalue), e->falsevalue); - provide (this, n); + n->cond = require (e->cond); + n->truevalue = require (e->truevalue); + n->falsevalue = require (e->falsevalue); + provide (n); } void @@ -2352,9 +2344,9 @@ deep_copy_visitor::visit_assignment (assignment* e) assignment* n = new assignment; n->op = e->op; n->tok = e->tok; - require (this, &(n->left), e->left); - require (this, &(n->right), e->right); - provide (this, n); + n->left = require (e->left); + n->right = require (e->right); + provide (n); } void @@ -2364,7 +2356,7 @@ deep_copy_visitor::visit_symbol (symbol* e) n->tok = e->tok; n->name = e->name; n->referent = NULL; - provide (this, n); + provide (n); } void @@ -2374,7 +2366,7 @@ deep_copy_visitor::visit_target_symbol (target_symbol* e) n->tok = e->tok; n->base_name = e->base_name; n->components = e->components; - provide (this, n); + provide (n); } void @@ -2383,15 +2375,11 @@ deep_copy_visitor::visit_arrayindex (arrayindex* e) arrayindex* n = new arrayindex; n->tok = e->tok; - require (this, &(n->base), e->base); + n->base = require (e->base); for (unsigned i = 0; i < e->indexes.size(); ++i) - { - expression* ne; - require (this, &ne, e->indexes[i]); - n->indexes.push_back(ne); - } - provide (this, n); + n->indexes.push_back(require (e->indexes[i])); + provide (n); } void @@ -2402,12 +2390,8 @@ deep_copy_visitor::visit_functioncall (functioncall* e) n->function = e->function; n->referent = NULL; for (unsigned i = 0; i < e->args.size(); ++i) - { - expression* na; - require (this, &na, e->args[i]); - n->args.push_back(na); - } - provide (this, n); + n->args.push_back(require (e->args[i])); + provide (n); } void @@ -2424,14 +2408,10 @@ deep_copy_visitor::visit_print_format (print_format* e) n->components = e->components; n->delimiter = e->delimiter; for (unsigned i = 0; i < e->args.size(); ++i) - { - expression* na; - require (this, &na, e->args[i]); - n->args.push_back(na); - } + n->args.push_back(require (e->args[i])); if (e->hist) - require (this, &n->hist, e->hist); - provide (this, n); + n->hist = require (e->hist); + provide (n); } void @@ -2440,8 +2420,8 @@ deep_copy_visitor::visit_stat_op (stat_op* e) stat_op* n = new stat_op; n->tok = e->tok; n->ctype = e->ctype; - require (this, &(n->stat), e->stat); - provide (this, n); + n->stat = require (e->stat); + provide (n); } void @@ -2451,61 +2431,28 @@ deep_copy_visitor::visit_hist_op (hist_op* e) n->tok = e->tok; n->htype = e->htype; n->params = e->params; - require (this, &(n->stat), e->stat); - provide (this, n); -} - -block* -deep_copy_visitor::deep_copy (block* b) -{ - block* n; - deep_copy_visitor v; - require (&v, &n, b); - return n; -} - -statement* -deep_copy_visitor::deep_copy (statement* s) -{ - statement* n; - deep_copy_visitor v; - require (&v, &n, s); - return n; -} - -expression* -deep_copy_visitor::deep_copy (expression* s) -{ - expression* n; - deep_copy_visitor v; - require (&v, &n, s); - return n; + n->stat = require (e->stat); + provide (n); } -template <> void -require (deep_copy_visitor* v, indexable** dst, indexable* src) +template <> indexable* +deep_copy_visitor::require (indexable* src) { + indexable *dst = NULL; if (src != NULL) { - symbol *array_src=NULL, *array_dst=NULL; - hist_op *hist_src=NULL, *hist_dst=NULL; + symbol *array_src=NULL; + hist_op *hist_src=NULL; classify_indexable(src, array_src, hist_src); - *dst = NULL; - if (array_src) - { - require (v, &array_dst, array_src); - *dst = array_dst; - } + dst = require (array_src); else - { - require (v, &hist_dst, hist_src); - *dst = hist_dst; - } - assert (*dst); + dst = require (hist_src); + assert (dst); } + return dst; } /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */ diff --git a/staptree.h b/staptree.h index 8c37776f..29196828 100644 --- a/staptree.h +++ b/staptree.h @@ -818,11 +818,30 @@ struct throwing_visitor: public visitor struct deep_copy_visitor: public visitor { - std::stack targets; + template T require (T src) + { + T dst = NULL; + if (src != NULL) + { + src->visit(this); + assert(!targets.empty()); + dst = static_cast(targets.top()); + targets.pop(); + assert(dst); + } + return dst; + } + + template void provide (T src) + { + targets.push(static_cast(src)); + } - static expression *deep_copy (expression *s); - static statement *deep_copy (statement *s); - static block *deep_copy (block *s); + template static T deep_copy (T e) + { + deep_copy_visitor v; + return v.require (e); + } virtual void visit_block (block *s); virtual void visit_embeddedcode (embeddedcode *s); @@ -856,30 +875,13 @@ struct deep_copy_visitor: public visitor virtual void visit_print_format (print_format* e); virtual void visit_stat_op (stat_op* e); virtual void visit_hist_op (hist_op* e); -}; -template void -require (deep_copy_visitor* v, T* dst, T src) -{ - *dst = NULL; - if (src != NULL) - { - v->targets.push(static_cast(dst)); - src->visit(v); - v->targets.pop(); - assert(*dst); - } -} - -template <> void -require (deep_copy_visitor* v, indexable** dst, indexable* src); +private: + std::stack targets; +}; -template void -provide (deep_copy_visitor* v, T src) -{ - assert(!v->targets.empty()); - *(static_cast(v->targets.top())) = src; -} +template <> indexable* +deep_copy_visitor::require (indexable* src); #endif // STAPTREE_H diff --git a/tapsets.cxx b/tapsets.cxx index c8742fbd..90b5c24f 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -4253,9 +4253,9 @@ var_expanding_copy_visitor::visit_assignment (assignment* e) expression *new_left, *new_right; target_symbol_setter_functioncalls.push (&fcall); - require (this, &new_left, e->left); + new_left = require (e->left); target_symbol_setter_functioncalls.pop (); - require (this, &new_right, e->right); + new_right = require (e->right); if (fcall != NULL) { @@ -4274,7 +4274,7 @@ var_expanding_copy_visitor::visit_assignment (assignment* e) assert (new_left == fcall); fcall->args.push_back (new_right); - provide (this, fcall); + provide (fcall); } else { @@ -4283,7 +4283,7 @@ var_expanding_copy_visitor::visit_assignment (assignment* e) n->tok = e->tok; n->left = new_left; n->right = new_right; - provide (this, n); + provide (n); } } @@ -4318,7 +4318,7 @@ dwarf_var_expanding_copy_visitor::visit_target_symbol (target_symbol *e) map::iterator i = return_ts_map.find(ts_name); if (i != return_ts_map.end()) { - provide (this, i->second); + provide (i->second); return; } @@ -4576,7 +4576,7 @@ dwarf_var_expanding_copy_visitor::visit_target_symbol (target_symbol *e) // (4) Provide the '_dwarf_tvar_{name}_{num}_tmp' variable to // our parent so it can be used as a substitute for the target // symbol. - provide (this, tmpsym); + provide (tmpsym); // (5) Remember this replacement since we might be able to reuse // it later if the same return probe references this target @@ -4622,7 +4622,8 @@ dwarf_var_expanding_copy_visitor::visit_target_symbol (target_symbol *e) // Ignore any variable that isn't accessible. tsym->saved_conversion_error = 0; - this->visit_target_symbol(tsym); // NB: throws nothing ... + expression *texp = tsym; + texp = require (texp); // NB: throws nothing ... if (tsym->saved_conversion_error) // ... but this is how we know it happened. { @@ -4631,7 +4632,7 @@ dwarf_var_expanding_copy_visitor::visit_target_symbol (target_symbol *e) { pf->raw_components += "return"; pf->raw_components += "=%#x "; - pf->args.push_back(*(expression**)this->targets.top()); + pf->args.push_back(texp); } } else @@ -4665,7 +4666,8 @@ dwarf_var_expanding_copy_visitor::visit_target_symbol (target_symbol *e) // Ignore any variable that isn't accessible. tsym->saved_conversion_error = 0; - this->visit_target_symbol(tsym); // NB: throws nothing ... + expression *texp = tsym; + texp = require (texp); // NB: throws nothing ... if (tsym->saved_conversion_error) // ... but this is how we know it happened. { if (q.sess.verbose>2) @@ -4684,14 +4686,14 @@ dwarf_var_expanding_copy_visitor::visit_target_symbol (target_symbol *e) { pf->raw_components += diename; pf->raw_components += "=%#x "; - pf->args.push_back(*(expression**)this->targets.top()); + pf->args.push_back(texp); } } while (dwarf_siblingof (&result, &result) == 0); } pf->components = print_format::string_to_components(pf->raw_components); - provide (this, pf); + provide (pf); return; } @@ -4735,7 +4737,7 @@ dwarf_var_expanding_copy_visitor::visit_target_symbol (target_symbol *e) // target_symbol to the next pass. We hope that this value ends // up not being referenced after all, so it can be optimized out // quietly. - provide (this, e); + provide (e); semantic_error* saveme = new semantic_error (er); // copy it saveme->tok1 = e->tok; // XXX: token not passed to q.dw code generation routines // NB: we can have multiple errors, since a $target variable @@ -4783,7 +4785,7 @@ dwarf_var_expanding_copy_visitor::visit_target_symbol (target_symbol *e) *(target_symbol_setter_functioncalls.top()) = n; } - provide (this, n); + provide (n); } @@ -4856,7 +4858,7 @@ dwarf_derived_probe::dwarf_derived_probe(const string& funcname, if (!null_die(scope_die)) { dwarf_var_expanding_copy_visitor v (q, scope_die, dwfl_addr); - require (&v, &(this->body), this->body); + this->body = v.require (this->body); this->access_vars = v.visited; // If during target-variable-expanding the probe, we added a new block @@ -6268,7 +6270,7 @@ utrace_derived_probe::utrace_derived_probe (systemtap_session &s, { // Make a local-variable-expanded copy of the probe body utrace_var_expanding_copy_visitor v (s, name, flags); - require (&v, &(this->body), base->body); + this->body = v.require (base->body); target_symbol_seen = v.target_symbol_seen; // Reset the sole element of the "locations" vector as a @@ -6379,7 +6381,7 @@ utrace_var_expanding_copy_visitor::visit_target_symbol_arg (target_symbol* e) num->tok = e->tok; n->args.push_back(num); - provide (this, n); + provide (n); } void @@ -6430,7 +6432,7 @@ utrace_var_expanding_copy_visitor::visit_target_symbol_context (target_symbol* e n->function = fname; n->referent = 0; // NB: must not resolve yet, to ensure inclusion in session - provide (this, n); + provide (n); } void @@ -6998,7 +7000,7 @@ uprobe_derived_probe::uprobe_derived_probe (const string& function, if (!null_die(scope_die)) { dwarf_var_expanding_copy_visitor v (q, scope_die, dwfl_addr); // XXX: user-space deref's! - require (&v, &(this->body), this->body); + this->body = v.require (this->body); // If during target-variable-expanding the probe, we added a new block // of code, add it to the start of the probe. @@ -7802,7 +7804,7 @@ procfs_derived_probe::procfs_derived_probe (systemtap_session &s, probe* p, { // Make a local-variable-expanded copy of the probe body procfs_var_expanding_copy_visitor v (s, name, path, write); - require (&v, &(this->body), base->body); + this->body = v.require (base->body); target_symbol_seen = v.target_symbol_seen; } @@ -8136,7 +8138,7 @@ procfs_var_expanding_copy_visitor::visit_target_symbol (target_symbol* e) *(target_symbol_setter_functioncalls.top()) = n; } - provide (this, n); + provide (n); } @@ -8371,7 +8373,7 @@ mark_var_expanding_copy_visitor::visit_target_symbol_arg (target_symbol* e) n->tok = e->tok; n->function = fname; n->referent = 0; // NB: must not resolve yet, to ensure inclusion in session - provide (this, n); + provide (n); } @@ -8413,7 +8415,7 @@ mark_var_expanding_copy_visitor::visit_target_symbol_context (target_symbol* e) n->tok = e->tok; n->function = fname; n->referent = 0; // NB: must not resolve yet, to ensure inclusion in session - provide (this, n); + provide (n); } void @@ -8452,7 +8454,7 @@ mark_derived_probe::mark_derived_probe (systemtap_session &s, // Now make a local-variable-expanded copy of the probe body mark_var_expanding_copy_visitor v (sess, name, mark_args); - require (&v, &(this->body), base->body); + this->body = v.require (base->body); target_symbol_seen = v.target_symbol_seen; if (sess.verbose > 2) @@ -9285,7 +9287,7 @@ perfmon_var_expanding_copy_visitor::visit_target_symbol (target_symbol *e) n->function = fname; n->referent = 0; // NB: must not resolve yet, to ensure inclusion in session - provide (this, n); + provide (n); } @@ -9355,7 +9357,7 @@ perfmon_derived_probe::perfmon_derived_probe (probe* p, probe_point* l, // Now make a local-variable-expanded copy of the probe body perfmon_var_expanding_copy_visitor v (sess, probes_allocated-1); - require (&v, &(this->body), base->body); + this->body = v.require (base->body); if (sess.verbose > 1) clog << "perfmon-based probe" << endl; -- cgit From 4b6455e82679becf3ad12e4f12abb70de1ee271d Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Thu, 5 Feb 2009 20:02:35 -0800 Subject: Create update_visitor for modifying trees * staptree.h (update_visitor): A new visitor to make it easier to rewrite parts of a probe or function without making a full copy. * staptree.cxx (update_visitor::*): Each child is recursed with a require() call, and then the parent returns itself with provide(). * staptree.h (deep_copy_visitor): Inherit from update_visitor to get the recursive descent while updating nodes. * staptree.cxx (deep_copy_visitor::*): Use the implicit copy constructors to copy all fields, then defer to update_visitor for the recursion. Referents are still cleared from the copies of symbols and function calls. --- ChangeLog | 13 ++ staptree.cxx | 498 ++++++++++++++++++++++++++++++++++++----------------------- staptree.h | 65 ++++++-- 3 files changed, 367 insertions(+), 209 deletions(-) diff --git a/ChangeLog b/ChangeLog index 324d6cb3..38a2eabc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2009-02-05 Josh Stone + + * staptree.h (update_visitor): A new visitor to make it easier to + rewrite parts of a probe or function without making a full copy. + * staptree.cxx (update_visitor::*): Each child is recursed with a + require() call, and then the parent returns itself with provide(). + * staptree.h (deep_copy_visitor): Inherit from update_visitor to get + the recursive descent while updating nodes. + * staptree.cxx (deep_copy_visitor::*): Use the implicit copy + constructors to copy all fields, then defer to update_visitor for the + recursion. Referents are still cleared from the copies of symbols and + function calls. + 2009-02-05 Josh Stone * staptree.h (require, provide): Simplify stack operations with less diff --git a/staptree.cxx b/staptree.cxx index 869af80a..2b963bc3 100644 --- a/staptree.cxx +++ b/staptree.cxx @@ -2098,361 +2098,465 @@ throwing_visitor::visit_hist_op (hist_op* e) void -deep_copy_visitor::visit_block (block* s) +update_visitor::visit_block (block* s) { - block* n = new block; - n->tok = s->tok; for (unsigned i = 0; i < s->statements.size(); ++i) - n->statements.push_back(require (s->statements[i])); - provide (n); + s->statements[i] = require (s->statements[i]); + provide (s); +} + +void +update_visitor::visit_embeddedcode (embeddedcode* s) +{ + provide (s); +} + +void +update_visitor::visit_null_statement (null_statement* s) +{ + provide (s); +} + +void +update_visitor::visit_expr_statement (expr_statement* s) +{ + s->value = require (s->value); + provide (s); +} + +void +update_visitor::visit_if_statement (if_statement* s) +{ + s->condition = require (s->condition); + s->thenblock = require (s->thenblock); + s->elseblock = require (s->elseblock); + provide (s); +} + +void +update_visitor::visit_for_loop (for_loop* s) +{ + s->init = require (s->init); + s->cond = require (s->cond); + s->incr = require (s->incr); + s->block = require (s->block); + provide (s); +} + +void +update_visitor::visit_foreach_loop (foreach_loop* s) +{ + for (unsigned i = 0; i < s->indexes.size(); ++i) + s->indexes[i] = require (s->indexes[i]); + s->base = require (s->base); + s->limit = require (s->limit); + s->block = require (s->block); + provide (s); +} + +void +update_visitor::visit_return_statement (return_statement* s) +{ + s->value = require (s->value); + provide (s); +} + +void +update_visitor::visit_delete_statement (delete_statement* s) +{ + s->value = require (s->value); + provide (s); +} + +void +update_visitor::visit_next_statement (next_statement* s) +{ + provide (s); +} + +void +update_visitor::visit_break_statement (break_statement* s) +{ + provide (s); +} + +void +update_visitor::visit_continue_statement (continue_statement* s) +{ + provide (s); +} + +void +update_visitor::visit_literal_string (literal_string* e) +{ + provide (e); +} + +void +update_visitor::visit_literal_number (literal_number* e) +{ + provide (e); +} + +void +update_visitor::visit_binary_expression (binary_expression* e) +{ + e->left = require (e->left); + e->right = require (e->right); + provide (e); +} + +void +update_visitor::visit_unary_expression (unary_expression* e) +{ + e->operand = require (e->operand); + provide (e); +} + +void +update_visitor::visit_pre_crement (pre_crement* e) +{ + e->operand = require (e->operand); + provide (e); +} + +void +update_visitor::visit_post_crement (post_crement* e) +{ + e->operand = require (e->operand); + provide (e); +} + + +void +update_visitor::visit_logical_or_expr (logical_or_expr* e) +{ + e->left = require (e->left); + e->right = require (e->right); + provide (e); +} + +void +update_visitor::visit_logical_and_expr (logical_and_expr* e) +{ + e->left = require (e->left); + e->right = require (e->right); + provide (e); +} + +void +update_visitor::visit_array_in (array_in* e) +{ + e->operand = require (e->operand); + provide (e); +} + +void +update_visitor::visit_comparison (comparison* e) +{ + e->left = require (e->left); + e->right = require (e->right); + provide (e); +} + +void +update_visitor::visit_concatenation (concatenation* e) +{ + e->left = require (e->left); + e->right = require (e->right); + provide (e); +} + +void +update_visitor::visit_ternary_expression (ternary_expression* e) +{ + e->cond = require (e->cond); + e->truevalue = require (e->truevalue); + e->falsevalue = require (e->falsevalue); + provide (e); +} + +void +update_visitor::visit_assignment (assignment* e) +{ + e->left = require (e->left); + e->right = require (e->right); + provide (e); +} + +void +update_visitor::visit_symbol (symbol* e) +{ + provide (e); +} + +void +update_visitor::visit_target_symbol (target_symbol* e) +{ + provide (e); +} + +void +update_visitor::visit_arrayindex (arrayindex* e) +{ + e->base = require (e->base); + for (unsigned i = 0; i < e->indexes.size(); ++i) + e->indexes[i] = require (e->indexes[i]); + provide (e); +} + +void +update_visitor::visit_functioncall (functioncall* e) +{ + for (unsigned i = 0; i < e->args.size(); ++i) + e->args[i] = require (e->args[i]); + provide (e); +} + +void +update_visitor::visit_print_format (print_format* e) +{ + for (unsigned i = 0; i < e->args.size(); ++i) + e->args[i] = require (e->args[i]); + e->hist = require (e->hist); + provide (e); +} + +void +update_visitor::visit_stat_op (stat_op* e) +{ + e->stat = require (e->stat); + provide (e); +} + +void +update_visitor::visit_hist_op (hist_op* e) +{ + e->stat = require (e->stat); + provide (e); +} + +template <> indexable* +update_visitor::require (indexable* src) +{ + indexable *dst = NULL; + if (src != NULL) + { + symbol *array_src=NULL; + hist_op *hist_src=NULL; + + classify_indexable(src, array_src, hist_src); + + if (array_src) + dst = require (array_src); + else + dst = require (hist_src); + assert (dst); + } + return dst; +} + + +// ------------------------------------------------------------------------ + + +void +deep_copy_visitor::visit_block (block* s) +{ + update_visitor::visit_block(new block(*s)); } void deep_copy_visitor::visit_embeddedcode (embeddedcode* s) { - embeddedcode* n = new embeddedcode; - n->tok = s->tok; - n->code = s->code; - provide (n); + update_visitor::visit_embeddedcode(new embeddedcode(*s)); } void deep_copy_visitor::visit_null_statement (null_statement* s) { - null_statement* n = new null_statement; - n->tok = s->tok; - provide (n); + update_visitor::visit_null_statement(new null_statement(*s)); } void deep_copy_visitor::visit_expr_statement (expr_statement* s) { - expr_statement* n = new expr_statement; - n->tok = s->tok; - n->value = require (s->value); - provide (n); + update_visitor::visit_expr_statement(new expr_statement(*s)); } void deep_copy_visitor::visit_if_statement (if_statement* s) { - if_statement* n = new if_statement; - n->tok = s->tok; - n->condition = require (s->condition); - n->thenblock = require (s->thenblock); - n->elseblock = require (s->elseblock); - provide (n); + update_visitor::visit_if_statement(new if_statement(*s)); } void deep_copy_visitor::visit_for_loop (for_loop* s) { - for_loop* n = new for_loop; - n->tok = s->tok; - n->init = require (s->init); - n->cond = require (s->cond); - n->incr = require (s->incr); - n->block = require (s->block); - provide (n); + update_visitor::visit_for_loop(new for_loop(*s)); } void deep_copy_visitor::visit_foreach_loop (foreach_loop* s) { - foreach_loop* n = new foreach_loop; - n->tok = s->tok; - for (unsigned i = 0; i < s->indexes.size(); ++i) - n->indexes.push_back(require (s->indexes[i])); - - n->base = require (s->base); - - n->sort_direction = s->sort_direction; - n->sort_column = s->sort_column; - n->limit = require (s->limit); - - n->block = require (s->block); - provide (n); + update_visitor::visit_foreach_loop(new foreach_loop(*s)); } void deep_copy_visitor::visit_return_statement (return_statement* s) { - return_statement* n = new return_statement; - n->tok = s->tok; - n->value = require (s->value); - provide (n); + update_visitor::visit_return_statement(new return_statement(*s)); } void deep_copy_visitor::visit_delete_statement (delete_statement* s) { - delete_statement* n = new delete_statement; - n->tok = s->tok; - n->value = require (s->value); - provide (n); + update_visitor::visit_delete_statement(new delete_statement(*s)); } void deep_copy_visitor::visit_next_statement (next_statement* s) { - next_statement* n = new next_statement; - n->tok = s->tok; - provide (n); + update_visitor::visit_next_statement(new next_statement(*s)); } void deep_copy_visitor::visit_break_statement (break_statement* s) { - break_statement* n = new break_statement; - n->tok = s->tok; - provide (n); + update_visitor::visit_break_statement(new break_statement(*s)); } void deep_copy_visitor::visit_continue_statement (continue_statement* s) { - continue_statement* n = new continue_statement; - n->tok = s->tok; - provide (n); + update_visitor::visit_continue_statement(new continue_statement(*s)); } void deep_copy_visitor::visit_literal_string (literal_string* e) { - literal_string* n = new literal_string(e->value); - n->tok = e->tok; - provide (n); + update_visitor::visit_literal_string(new literal_string(*e)); } void deep_copy_visitor::visit_literal_number (literal_number* e) { - literal_number* n = new literal_number(e->value); - n->tok = e->tok; - provide (n); + update_visitor::visit_literal_number(new literal_number(*e)); } void deep_copy_visitor::visit_binary_expression (binary_expression* e) { - binary_expression* n = new binary_expression; - n->op = e->op; - n->tok = e->tok; - n->left = require (e->left); - n->right = require (e->right); - provide (n); + update_visitor::visit_binary_expression(new binary_expression(*e)); } void deep_copy_visitor::visit_unary_expression (unary_expression* e) { - unary_expression* n = new unary_expression; - n->op = e->op; - n->tok = e->tok; - n->operand = require (e->operand); - provide (n); + update_visitor::visit_unary_expression(new unary_expression(*e)); } void deep_copy_visitor::visit_pre_crement (pre_crement* e) { - pre_crement* n = new pre_crement; - n->op = e->op; - n->tok = e->tok; - n->operand = require (e->operand); - provide (n); + update_visitor::visit_pre_crement(new pre_crement(*e)); } void deep_copy_visitor::visit_post_crement (post_crement* e) { - post_crement* n = new post_crement; - n->op = e->op; - n->tok = e->tok; - n->operand = require (e->operand); - provide (n); + update_visitor::visit_post_crement(new post_crement(*e)); } void deep_copy_visitor::visit_logical_or_expr (logical_or_expr* e) { - logical_or_expr* n = new logical_or_expr; - n->op = e->op; - n->tok = e->tok; - n->left = require (e->left); - n->right = require (e->right); - provide (n); + update_visitor::visit_logical_or_expr(new logical_or_expr(*e)); } void deep_copy_visitor::visit_logical_and_expr (logical_and_expr* e) { - logical_and_expr* n = new logical_and_expr; - n->op = e->op; - n->tok = e->tok; - n->left = require (e->left); - n->right = require (e->right); - provide (n); + update_visitor::visit_logical_and_expr(new logical_and_expr(*e)); } void deep_copy_visitor::visit_array_in (array_in* e) { - array_in* n = new array_in; - n->tok = e->tok; - n->operand = require (e->operand); - provide (n); + update_visitor::visit_array_in(new array_in(*e)); } void deep_copy_visitor::visit_comparison (comparison* e) { - comparison* n = new comparison; - n->op = e->op; - n->tok = e->tok; - n->left = require (e->left); - n->right = require (e->right); - provide (n); + update_visitor::visit_comparison(new comparison(*e)); } void deep_copy_visitor::visit_concatenation (concatenation* e) { - concatenation* n = new concatenation; - n->op = e->op; - n->tok = e->tok; - n->left = require (e->left); - n->right = require (e->right); - provide (n); + update_visitor::visit_concatenation(new concatenation(*e)); } void deep_copy_visitor::visit_ternary_expression (ternary_expression* e) { - ternary_expression* n = new ternary_expression; - n->tok = e->tok; - n->cond = require (e->cond); - n->truevalue = require (e->truevalue); - n->falsevalue = require (e->falsevalue); - provide (n); + update_visitor::visit_ternary_expression(new ternary_expression(*e)); } void deep_copy_visitor::visit_assignment (assignment* e) { - assignment* n = new assignment; - n->op = e->op; - n->tok = e->tok; - n->left = require (e->left); - n->right = require (e->right); - provide (n); + update_visitor::visit_assignment(new assignment(*e)); } void deep_copy_visitor::visit_symbol (symbol* e) { - symbol* n = new symbol; - n->tok = e->tok; - n->name = e->name; - n->referent = NULL; - provide (n); + symbol* n = new symbol(*e); + n->referent = NULL; // don't copy! + update_visitor::visit_symbol(n); } void deep_copy_visitor::visit_target_symbol (target_symbol* e) { - target_symbol* n = new target_symbol; - n->tok = e->tok; - n->base_name = e->base_name; - n->components = e->components; - provide (n); + target_symbol* n = new target_symbol(*e); + n->referent = NULL; // don't copy! + update_visitor::visit_target_symbol(n); } void deep_copy_visitor::visit_arrayindex (arrayindex* e) { - arrayindex* n = new arrayindex; - n->tok = e->tok; - - n->base = require (e->base); - - for (unsigned i = 0; i < e->indexes.size(); ++i) - n->indexes.push_back(require (e->indexes[i])); - provide (n); + update_visitor::visit_arrayindex(new arrayindex(*e)); } void deep_copy_visitor::visit_functioncall (functioncall* e) { - functioncall* n = new functioncall; - n->tok = e->tok; - n->function = e->function; - n->referent = NULL; - for (unsigned i = 0; i < e->args.size(); ++i) - n->args.push_back(require (e->args[i])); - provide (n); + functioncall* n = new functioncall(*e); + n->referent = NULL; // don't copy! + update_visitor::visit_functioncall(n); } void deep_copy_visitor::visit_print_format (print_format* e) { - print_format* n = new print_format; - n->tok = e->tok; - n->print_to_stream = e->print_to_stream; - n->print_with_format = e->print_with_format; - n->print_with_delim = e->print_with_delim; - n->print_with_newline = e->print_with_newline; - n->print_char = e->print_char; - n->raw_components = e->raw_components; - n->components = e->components; - n->delimiter = e->delimiter; - for (unsigned i = 0; i < e->args.size(); ++i) - n->args.push_back(require (e->args[i])); - if (e->hist) - n->hist = require (e->hist); - provide (n); + update_visitor::visit_print_format(new print_format(*e)); } void deep_copy_visitor::visit_stat_op (stat_op* e) { - stat_op* n = new stat_op; - n->tok = e->tok; - n->ctype = e->ctype; - n->stat = require (e->stat); - provide (n); + update_visitor::visit_stat_op(new stat_op(*e)); } void deep_copy_visitor::visit_hist_op (hist_op* e) { - hist_op* n = new hist_op; - n->tok = e->tok; - n->htype = e->htype; - n->params = e->params; - n->stat = require (e->stat); - provide (n); -} - -template <> indexable* -deep_copy_visitor::require (indexable* src) -{ - indexable *dst = NULL; - if (src != NULL) - { - symbol *array_src=NULL; - hist_op *hist_src=NULL; - - classify_indexable(src, array_src, hist_src); - - if (array_src) - dst = require (array_src); - else - dst = require (hist_src); - assert (dst); - } - return dst; + update_visitor::visit_hist_op(new hist_op(*e)); } /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */ diff --git a/staptree.h b/staptree.h index 29196828..00809ed0 100644 --- a/staptree.h +++ b/staptree.h @@ -810,13 +810,10 @@ struct throwing_visitor: public visitor void visit_hist_op (hist_op* e); }; -// A visitor which performs a deep copy of the root node it's applied -// to. NB: It does not copy any of the variable or function -// declarations; those fields are set to NULL, assuming you want to -// re-infer the declarations in a new context (the one you're copying -// to). +// A visitor similar to a traversing_visitor, but with the ability to rewrite +// parts of the tree through require/provide. -struct deep_copy_visitor: public visitor +struct update_visitor: public visitor { template T require (T src) { @@ -837,11 +834,7 @@ struct deep_copy_visitor: public visitor targets.push(static_cast(src)); } - template static T deep_copy (T e) - { - deep_copy_visitor v; - return v.require (e); - } + virtual ~update_visitor() { assert(targets.empty()); } virtual void visit_block (block *s); virtual void visit_embeddedcode (embeddedcode *s); @@ -881,7 +874,55 @@ private: }; template <> indexable* -deep_copy_visitor::require (indexable* src); +update_visitor::require (indexable* src); + +// A visitor which performs a deep copy of the root node it's applied +// to. NB: It does not copy any of the variable or function +// declarations; those fields are set to NULL, assuming you want to +// re-infer the declarations in a new context (the one you're copying +// to). + +struct deep_copy_visitor: public update_visitor +{ + template static T deep_copy (T e) + { + deep_copy_visitor v; + return v.require (e); + } + + virtual void visit_block (block *s); + virtual void visit_embeddedcode (embeddedcode *s); + virtual void visit_null_statement (null_statement *s); + virtual void visit_expr_statement (expr_statement *s); + virtual void visit_if_statement (if_statement* s); + virtual void visit_for_loop (for_loop* s); + virtual void visit_foreach_loop (foreach_loop* s); + virtual void visit_return_statement (return_statement* s); + virtual void visit_delete_statement (delete_statement* s); + virtual void visit_next_statement (next_statement* s); + virtual void visit_break_statement (break_statement* s); + virtual void visit_continue_statement (continue_statement* s); + virtual void visit_literal_string (literal_string* e); + virtual void visit_literal_number (literal_number* e); + virtual void visit_binary_expression (binary_expression* e); + virtual void visit_unary_expression (unary_expression* e); + virtual void visit_pre_crement (pre_crement* e); + virtual void visit_post_crement (post_crement* e); + virtual void visit_logical_or_expr (logical_or_expr* e); + virtual void visit_logical_and_expr (logical_and_expr* e); + virtual void visit_array_in (array_in* e); + virtual void visit_comparison (comparison* e); + virtual void visit_concatenation (concatenation* e); + virtual void visit_ternary_expression (ternary_expression* e); + virtual void visit_assignment (assignment* e); + virtual void visit_symbol (symbol* e); + virtual void visit_target_symbol (target_symbol* e); + virtual void visit_arrayindex (arrayindex* e); + virtual void visit_functioncall (functioncall* e); + virtual void visit_print_format (print_format* e); + virtual void visit_stat_op (stat_op* e); + virtual void visit_hist_op (hist_op* e); +}; #endif // STAPTREE_H -- cgit From de68882508cf4b6e25bab9341e95b708a2bd39dc Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Thu, 5 Feb 2009 20:04:56 -0800 Subject: Expand probe variables without a deep copy * tapsets.cxx (var_expanding_copy_visitor): This struct becomes var_expanding_visitor and inherits from update_visitor instead of deep_copy_visitor. Each of the probe-type variants of this are also no longer copiers. --- ChangeLog | 7 +++++ tapsets.cxx | 96 +++++++++++++++++++++++++++++-------------------------------- 2 files changed, 53 insertions(+), 50 deletions(-) diff --git a/ChangeLog b/ChangeLog index 38a2eabc..6c71d29d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2009-02-05 Josh Stone + + * tapsets.cxx (var_expanding_copy_visitor): This struct becomes + var_expanding_visitor and inherits from update_visitor instead of + deep_copy_visitor. Each of the probe-type variants of this are also no + longer copiers. + 2009-02-05 Josh Stone * staptree.h (update_visitor): A new visitor to make it easier to diff --git a/tapsets.cxx b/tapsets.cxx index 90b5c24f..4ba685bd 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -4205,17 +4205,17 @@ dwflpp::query_modules(dwarf_query *q) iterate_over_modules(&query_module, q); } -struct var_expanding_copy_visitor: public deep_copy_visitor +struct var_expanding_visitor: public update_visitor { static unsigned tick; stack target_symbol_setter_functioncalls; - var_expanding_copy_visitor() {} + var_expanding_visitor() {} void visit_assignment (assignment* e); }; -struct dwarf_var_expanding_copy_visitor: public var_expanding_copy_visitor +struct dwarf_var_expanding_visitor: public var_expanding_visitor { dwarf_query & q; Dwarf_Die *scope_die; @@ -4225,17 +4225,17 @@ struct dwarf_var_expanding_copy_visitor: public var_expanding_copy_visitor std::map return_ts_map; bool visited; - dwarf_var_expanding_copy_visitor(dwarf_query & q, Dwarf_Die *sd, Dwarf_Addr a): + dwarf_var_expanding_visitor(dwarf_query & q, Dwarf_Die *sd, Dwarf_Addr a): q(q), scope_die(sd), addr(a), add_block(NULL), add_probe(NULL), visited(false) {} void visit_target_symbol (target_symbol* e); }; -unsigned var_expanding_copy_visitor::tick = 0; +unsigned var_expanding_visitor::tick = 0; void -var_expanding_copy_visitor::visit_assignment (assignment* e) +var_expanding_visitor::visit_assignment (assignment* e) { // Our job would normally be to require() the left and right sides // into a new assignment. What we're doing is slightly trickier: @@ -4263,7 +4263,7 @@ var_expanding_copy_visitor::visit_assignment (assignment* e) // and it has been replaced with a set_target_foo() function // call; we are going to provide that function call -- with the // right child spliced in as sole argument -- in place of - // ourselves, in the deep copy we're in the middle of making. + // ourselves, in the var expansion we're in the middle of making. // FIXME: for the time being, we only support plan $foo = bar, // not += or any other op= variant. This is fixable, but a bit @@ -4278,18 +4278,15 @@ var_expanding_copy_visitor::visit_assignment (assignment* e) } else { - assignment* n = new assignment; - n->op = e->op; - n->tok = e->tok; - n->left = new_left; - n->right = new_right; - provide (n); + e->left = new_left; + e->right = new_right; + provide (e); } } void -dwarf_var_expanding_copy_visitor::visit_target_symbol (target_symbol *e) +dwarf_var_expanding_visitor::visit_target_symbol (target_symbol *e) { assert(e->base_name.size() > 0 && e->base_name[0] == '$'); visited = true; @@ -4854,10 +4851,10 @@ dwarf_derived_probe::dwarf_derived_probe(const string& funcname, + lex_cast(USHRT_MAX) + "]", q.base_loc->tok); - // Make a target-variable-expanded copy of the probe body + // Expand target variables in the probe body if (!null_die(scope_die)) { - dwarf_var_expanding_copy_visitor v (q, scope_die, dwfl_addr); + dwarf_var_expanding_visitor v (q, scope_die, dwfl_addr); this->body = v.require (this->body); this->access_vars = v.visited; @@ -6242,10 +6239,10 @@ public: }; -struct utrace_var_expanding_copy_visitor: public var_expanding_copy_visitor +struct utrace_var_expanding_visitor: public var_expanding_visitor { - utrace_var_expanding_copy_visitor(systemtap_session& s, const string& pn, - enum utrace_derived_probe_flags f): + utrace_var_expanding_visitor(systemtap_session& s, const string& pn, + enum utrace_derived_probe_flags f): sess (s), probe_name (pn), flags (f), target_symbol_seen (false) {} systemtap_session& sess; @@ -6268,9 +6265,9 @@ utrace_derived_probe::utrace_derived_probe (systemtap_session &s, has_path(hp), path(pn), pid(pd), flags(f), target_symbol_seen(false) { - // Make a local-variable-expanded copy of the probe body - utrace_var_expanding_copy_visitor v (s, name, flags); - this->body = v.require (base->body); + // Expand local variables in the probe body + utrace_var_expanding_visitor v (s, name, flags); + this->body = v.require (this->body); target_symbol_seen = v.target_symbol_seen; // Reset the sole element of the "locations" vector as a @@ -6332,7 +6329,7 @@ utrace_derived_probe::join_group (systemtap_session& s) void -utrace_var_expanding_copy_visitor::visit_target_symbol_arg (target_symbol* e) +utrace_var_expanding_visitor::visit_target_symbol_arg (target_symbol* e) { string argnum_s = e->base_name.substr(4,e->base_name.length()-4); int argnum = lex_cast(argnum_s); @@ -6385,7 +6382,7 @@ utrace_var_expanding_copy_visitor::visit_target_symbol_arg (target_symbol* e) } void -utrace_var_expanding_copy_visitor::visit_target_symbol_context (target_symbol* e) +utrace_var_expanding_visitor::visit_target_symbol_context (target_symbol* e) { string sname = e->base_name; @@ -6436,7 +6433,7 @@ utrace_var_expanding_copy_visitor::visit_target_symbol_context (target_symbol* e } void -utrace_var_expanding_copy_visitor::visit_target_symbol (target_symbol* e) +utrace_var_expanding_visitor::visit_target_symbol (target_symbol* e) { assert(e->base_name.size() > 0 && e->base_name[0] == '$'); @@ -6996,10 +6993,10 @@ uprobe_derived_probe::uprobe_derived_probe (const string& function, this->tok = q.base_probe->tok; - // Make a target-variable-expanded copy of the probe body + // Expand target variables in the probe body if (!null_die(scope_die)) { - dwarf_var_expanding_copy_visitor v (q, scope_die, dwfl_addr); // XXX: user-space deref's! + dwarf_var_expanding_visitor v (q, scope_die, dwfl_addr); // XXX: user-space deref's! this->body = v.require (this->body); // If during target-variable-expanding the probe, we added a new block @@ -7781,10 +7778,10 @@ public: }; -struct procfs_var_expanding_copy_visitor: public var_expanding_copy_visitor +struct procfs_var_expanding_visitor: public var_expanding_visitor { - procfs_var_expanding_copy_visitor(systemtap_session& s, const string& pn, - string path, bool write_probe): + procfs_var_expanding_visitor(systemtap_session& s, const string& pn, + string path, bool write_probe): sess (s), probe_name (pn), path (path), write_probe (write_probe), target_symbol_seen (false) {} @@ -7802,9 +7799,9 @@ procfs_derived_probe::procfs_derived_probe (systemtap_session &s, probe* p, probe_point* l, string ps, bool w): derived_probe(p, l), path(ps), write(w), target_symbol_seen(false) { - // Make a local-variable-expanded copy of the probe body - procfs_var_expanding_copy_visitor v (s, name, path, write); - this->body = v.require (base->body); + // Expand local variables in the probe body + procfs_var_expanding_visitor v (s, name, path, write); + this->body = v.require (this->body); target_symbol_seen = v.target_symbol_seen; } @@ -8053,7 +8050,7 @@ procfs_derived_probe_group::emit_module_exit (systemtap_session& s) void -procfs_var_expanding_copy_visitor::visit_target_symbol (target_symbol* e) +procfs_var_expanding_visitor::visit_target_symbol (target_symbol* e) { assert(e->base_name.size() > 0 && e->base_name[0] == '$'); @@ -8257,11 +8254,10 @@ public: }; -struct mark_var_expanding_copy_visitor: public var_expanding_copy_visitor +struct mark_var_expanding_visitor: public var_expanding_visitor { - mark_var_expanding_copy_visitor(systemtap_session& s, - const string& pn, - vector &mark_args): + mark_var_expanding_visitor(systemtap_session& s, const string& pn, + vector &mark_args): sess (s), probe_name (pn), mark_args (mark_args), target_symbol_seen (false) {} systemtap_session& sess; @@ -8312,7 +8308,7 @@ hex_dump(unsigned char *data, size_t len) void -mark_var_expanding_copy_visitor::visit_target_symbol_arg (target_symbol* e) +mark_var_expanding_visitor::visit_target_symbol_arg (target_symbol* e) { string argnum_s = e->base_name.substr(4,e->base_name.length()-4); int argnum = atoi (argnum_s.c_str()); @@ -8378,7 +8374,7 @@ mark_var_expanding_copy_visitor::visit_target_symbol_arg (target_symbol* e) void -mark_var_expanding_copy_visitor::visit_target_symbol_context (target_symbol* e) +mark_var_expanding_visitor::visit_target_symbol_context (target_symbol* e) { string sname = e->base_name; @@ -8419,7 +8415,7 @@ mark_var_expanding_copy_visitor::visit_target_symbol_context (target_symbol* e) } void -mark_var_expanding_copy_visitor::visit_target_symbol (target_symbol* e) +mark_var_expanding_visitor::visit_target_symbol (target_symbol* e) { assert(e->base_name.size() > 0 && e->base_name[0] == '$'); @@ -8452,9 +8448,9 @@ mark_derived_probe::mark_derived_probe (systemtap_session &s, // expand the marker format parse_probe_format(); - // Now make a local-variable-expanded copy of the probe body - mark_var_expanding_copy_visitor v (sess, name, mark_args); - this->body = v.require (base->body); + // Now expand the local variables in the probe body + mark_var_expanding_visitor v (sess, name, mark_args); + this->body = v.require (this->body); target_symbol_seen = v.target_symbol_seen; if (sess.verbose > 2) @@ -9222,18 +9218,18 @@ timer_builder::register_patterns(match_node *root) // -struct perfmon_var_expanding_copy_visitor: public var_expanding_copy_visitor +struct perfmon_var_expanding_visitor: public var_expanding_visitor { systemtap_session & sess; unsigned counter_number; - perfmon_var_expanding_copy_visitor(systemtap_session & s, unsigned c): + perfmon_var_expanding_visitor(systemtap_session & s, unsigned c): sess(s), counter_number(c) {} void visit_target_symbol (target_symbol* e); }; void -perfmon_var_expanding_copy_visitor::visit_target_symbol (target_symbol *e) +perfmon_var_expanding_visitor::visit_target_symbol (target_symbol *e) { assert(e->base_name.size() > 0 && e->base_name[0] == '$'); @@ -9355,9 +9351,9 @@ perfmon_derived_probe::perfmon_derived_probe (probe* p, probe_point* l, { ++probes_allocated; - // Now make a local-variable-expanded copy of the probe body - perfmon_var_expanding_copy_visitor v (sess, probes_allocated-1); - this->body = v.require (base->body); + // Now expand the local variables in the probe body + perfmon_var_expanding_visitor v (sess, probes_allocated-1); + this->body = v.require (this->body); if (sess.verbose > 1) clog << "perfmon-based probe" << endl; -- cgit From 8bda649876b523f7733aa547ff86924a90f0e57b Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Tue, 10 Feb 2009 15:31:50 -0800 Subject: Simplify dead_assignment_remover By converting to an update_visitor, we now get full statement coverage in this optimizer for free. * elaborate.cxx (dead_assignment_remover): Convert into an update_visitor and remove its now-redundant traversal methods. --- ChangeLog | 5 +++ elaborate.cxx | 124 ++++++++-------------------------------------------------- 2 files changed, 21 insertions(+), 108 deletions(-) diff --git a/ChangeLog b/ChangeLog index 6c71d29d..cf6bf61e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2009-02-10 Josh Stone + + * elaborate.cxx (dead_assignment_remover): Convert into an + update_visitor and remove its now-redundant traversal methods. + 2009-02-05 Josh Stone * tapsets.cxx (var_expanding_copy_visitor): This struct becomes diff --git a/elaborate.cxx b/elaborate.cxx index 5678e8a7..d4b07e8d 100644 --- a/elaborate.cxx +++ b/elaborate.cxx @@ -2091,59 +2091,30 @@ void semantic_pass_opt2 (systemtap_session& s, bool& relaxed_p, unsigned iterati // ------------------------------------------------------------------------ -struct dead_assignment_remover: public traversing_visitor +struct dead_assignment_remover: public update_visitor { systemtap_session& session; bool& relaxed_p; const varuse_collecting_visitor& vut; - expression** current_expr; dead_assignment_remover(systemtap_session& s, bool& r, const varuse_collecting_visitor& v): - session(s), relaxed_p(r), vut(v), current_expr(0) {} - - void visit_expr_statement (expr_statement* s); - // XXX: other places where an assignment may be nested should be - // handled too (e.g., loop/if conditionals, array indexes, function - // parameters). Until then, they result in visit_assignment() being - // called with null current_expr. + session(s), relaxed_p(r), vut(v) {} void visit_assignment (assignment* e); - void visit_binary_expression (binary_expression* e); - void visit_arrayindex (arrayindex* e); - void visit_functioncall (functioncall* e); - void visit_if_statement (if_statement* e); - void visit_for_loop (for_loop* e); }; -void -dead_assignment_remover::visit_expr_statement (expr_statement* s) -{ - expression** last_expr = current_expr; - current_expr = & s->value; - s->value->visit (this); - s->tok = s->value->tok; // in case it was replaced - current_expr = last_expr; -} - - void dead_assignment_remover::visit_assignment (assignment* e) { + e->left = require (e->left); + e->right = require (e->right); + symbol* left = get_symbol_within_expression (e->left); vardecl* leftvar = left->referent; // NB: may be 0 for unresolved $target - if (current_expr && // see XXX above: this case represents a missed - // optimization opportunity - *current_expr == e && // we're not nested any deeper than expected - leftvar) // not unresolved $target; intended sideeffect cannot be elided + if (leftvar) // not unresolved $target, so intended sideeffect may be elided { - expression** last_expr = current_expr; - e->left->visit (this); - current_expr = &e->right; - e->right->visit (this); - current_expr = last_expr; - if (vut.read.find(leftvar) == vut.read.end()) // var never read? { // NB: Not so fast! The left side could be an array whose @@ -2163,9 +2134,9 @@ dead_assignment_remover::visit_assignment (assignment* e) break; } - varuse_collecting_visitor vut; - e->left->visit (& vut); - if (vut.side_effect_free () && !is_global) // XXX: use _wrt() once we track focal_vars + varuse_collecting_visitor lvut; + e->left->visit (& lvut); + if (lvut.side_effect_free () && !is_global) // XXX: use _wrt() once we track focal_vars { /* PR 1119: NB: This is not necessary here. A write-only variable will also be elided soon at the next _opt2 iteration. @@ -2178,77 +2149,13 @@ dead_assignment_remover::visit_assignment (assignment* e) clog << "Eliding assignment to " << leftvar->name << " at " << *e->tok << endl; - *current_expr = e->right; // goodbye assignment* + provide (e->right); // goodbye assignment* relaxed_p = false; + return; } } } -} - -void -dead_assignment_remover::visit_binary_expression (binary_expression* e) -{ - expression** last_expr = current_expr; - current_expr = &e->left; - e->left->visit (this); - current_expr = &e->right; - e->right->visit (this); - current_expr = last_expr; -} - -void -dead_assignment_remover::visit_arrayindex (arrayindex *e) -{ - symbol *array = NULL; - hist_op *hist = NULL; - classify_indexable(e->base, array, hist); - - if (array) - { - expression** last_expr = current_expr; - for (unsigned i=0; i < e->indexes.size(); i++) - { - current_expr = & e->indexes[i]; - e->indexes[i]->visit (this); - } - current_expr = last_expr; - } -} - -void -dead_assignment_remover::visit_functioncall (functioncall* e) -{ - expression** last_expr = current_expr; - for (unsigned i=0; iargs.size(); i++) - { - current_expr = & e->args[i]; - e->args[i]->visit (this); - } - current_expr = last_expr; -} - -void -dead_assignment_remover::visit_if_statement (if_statement* s) -{ - expression** last_expr = current_expr; - current_expr = & s->condition; - s->condition->visit (this); - s->thenblock->visit (this); - if (s->elseblock) - s->elseblock->visit (this); - current_expr = last_expr; -} - -void -dead_assignment_remover::visit_for_loop (for_loop* s) -{ - expression** last_expr = current_expr; - if (s->init) s->init->visit (this); - current_expr = & s->cond; - s->cond->visit (this); - if (s->incr) s->incr->visit (this); - s->block->visit (this); - current_expr = last_expr; + provide (e); } // Let's remove assignments to variables that are never read. We @@ -2268,9 +2175,10 @@ void semantic_pass_opt3 (systemtap_session& s, bool& relaxed_p) // This instance may be reused for multiple probe/function body trims. for (unsigned i=0; ibody->visit (& dar); - for (map::iterator it = s.functions.begin(); it != s.functions.end(); it++) - it->second->body->visit (& dar); + s.probes[i]->body = dar.require (s.probes[i]->body); + for (map::iterator it = s.functions.begin(); + it != s.functions.end(); it++) + it->second->body = dar.require (it->second->body); // The rewrite operation is performed within the visitor. // XXX: we could also zap write-only globals here -- cgit From 1cd151d5b9e1fd46590d5e4c3473a86ea9bbe043 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Tue, 10 Feb 2009 18:29:55 -0800 Subject: Simplify dead_stmtexpr_remover * staptree.h (update_visitor::require): Add a clearok parameter for optimizing traversers to signal that they're ready for NULL back. * elaborate.cxx (dead_stmtexpr_remover): Convert to an update_visitor. --- ChangeLog | 3 ++ elaborate.cxx | 91 ++++++++++++++++++++++++----------------------------------- staptree.cxx | 4 +-- staptree.h | 6 ++-- 4 files changed, 45 insertions(+), 59 deletions(-) diff --git a/ChangeLog b/ChangeLog index cf6bf61e..208c8150 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,7 +1,10 @@ 2009-02-10 Josh Stone + * staptree.h (update_visitor::require): Add a clearok parameter for + optimizing traversers to signal that they're ready for NULL back. * elaborate.cxx (dead_assignment_remover): Convert into an update_visitor and remove its now-redundant traversal methods. + * elaborate.cxx (dead_stmtexpr_remover): Convert to an update_visitor. 2009-02-05 Josh Stone diff --git a/elaborate.cxx b/elaborate.cxx index d4b07e8d..bc9c4e7d 100644 --- a/elaborate.cxx +++ b/elaborate.cxx @@ -2187,15 +2187,14 @@ void semantic_pass_opt3 (systemtap_session& s, bool& relaxed_p) // ------------------------------------------------------------------------ -struct dead_stmtexpr_remover: public traversing_visitor +struct dead_stmtexpr_remover: public update_visitor { systemtap_session& session; bool& relaxed_p; - statement** current_stmt; // pointer to current stmt* being iterated set focal_vars; // vars considered subject to side-effects dead_stmtexpr_remover(systemtap_session& s, bool& r): - session(s), relaxed_p(r), current_stmt(0) {} + session(s), relaxed_p(r) {} void visit_block (block *s); void visit_null_statement (null_statement *s); @@ -2214,7 +2213,8 @@ dead_stmtexpr_remover::visit_null_statement (null_statement *s) // easy! if (session.verbose>2) clog << "Eliding side-effect-free null statement " << *s->tok << endl; - *current_stmt = 0; + s = 0; + provide (s); } @@ -2224,13 +2224,11 @@ dead_stmtexpr_remover::visit_block (block *s) vector new_stmts; for (unsigned i=0; istatements.size(); i++ ) { - statement** last_stmt = current_stmt; - current_stmt = & s->statements[i]; - s->statements[i]->visit (this); - if (*current_stmt != 0) + statement* new_stmt = require (s->statements[i], true); + if (new_stmt != 0) { // flatten nested blocks into this one - block *b = dynamic_cast(*current_stmt); + block *b = dynamic_cast(new_stmt); if (b) { if (session.verbose>2) @@ -2240,42 +2238,32 @@ dead_stmtexpr_remover::visit_block (block *s) relaxed_p = false; } else - new_stmts.push_back (*current_stmt); + new_stmts.push_back (new_stmt); } - current_stmt = last_stmt; } if (new_stmts.size() == 0) { if (session.verbose>2) clog << "Eliding side-effect-free empty block " << *s->tok << endl; - *current_stmt = 0; + s = 0; } else if (new_stmts.size() == 1) { if (session.verbose>2) clog << "Eliding side-effect-free singleton block " << *s->tok << endl; - *current_stmt = new_stmts[0]; + provide (new_stmts[0]); + return; } else - { - s->statements = new_stmts; - } + s->statements = new_stmts; + provide (s); } void dead_stmtexpr_remover::visit_if_statement (if_statement *s) { - statement** last_stmt = current_stmt; - current_stmt = & s->thenblock; - s->thenblock->visit (this); - - if (s->elseblock) - { - current_stmt = & s->elseblock; - s->elseblock->visit (this); - // null *current_stmt is OK here. - } - current_stmt = last_stmt; + s->thenblock = require (s->thenblock, true); + s->elseblock = require (s->elseblock, true); if (s->thenblock == 0) { @@ -2290,7 +2278,7 @@ dead_stmtexpr_remover::visit_if_statement (if_statement *s) if (session.verbose>2) clog << "Eliding side-effect-free if statement " << *s->tok << endl; - *current_stmt = 0; // yeah, baby + s = 0; // yeah, baby } else { @@ -2301,7 +2289,8 @@ dead_stmtexpr_remover::visit_if_statement (if_statement *s) expr_statement *es = new expr_statement; es->value = s->condition; es->tok = es->value->tok; - *current_stmt = es; + provide (es); + return; } } else @@ -2320,31 +2309,27 @@ dead_stmtexpr_remover::visit_if_statement (if_statement *s) s->elseblock = 0; } } + provide (s); } void dead_stmtexpr_remover::visit_foreach_loop (foreach_loop *s) { - statement** last_stmt = current_stmt; - current_stmt = & s->block; - s->block->visit (this); - current_stmt = last_stmt; + s->block = require(s->block, true); if (s->block == 0) { if (session.verbose>2) clog << "Eliding side-effect-free foreach statement " << *s->tok << endl; - *current_stmt = 0; // yeah, baby + s = 0; // yeah, baby } + provide (s); } void dead_stmtexpr_remover::visit_for_loop (for_loop *s) { - statement** last_stmt = current_stmt; - current_stmt = & s->block; - s->block->visit (this); - current_stmt = last_stmt; + s->block = require(s->block, true); if (s->block == 0) { @@ -2358,14 +2343,16 @@ dead_stmtexpr_remover::visit_for_loop (for_loop *s) { if (session.verbose>2) clog << "Eliding side-effect-free for statement " << *s->tok << endl; - *current_stmt = 0; // yeah, baby - return; + s = 0; // yeah, baby + } + else + { + // Can't elide this whole statement; put a null in there. + s->block = new null_statement(); + s->block->tok = s->tok; } - - // Can't elide this whole statement; put a null in there. - s->block = new null_statement(); - s->block->tok = s->tok; } + provide (s); } @@ -2375,8 +2362,7 @@ dead_stmtexpr_remover::visit_expr_statement (expr_statement *s) { // Run a varuse query against the operand expression. If it has no // side-effects, replace the entire statement expression by a null - // statement. This replacement is done by overwriting the - // current_stmt pointer. + // statement with the provide() call. // // Unlike many other visitors, we do *not* traverse this outermost // one into the expression subtrees. There is no need - no @@ -2389,8 +2375,7 @@ dead_stmtexpr_remover::visit_expr_statement (expr_statement *s) varuse_collecting_visitor vut; s->value->visit (& vut); - if (vut.side_effect_free_wrt (focal_vars) && - *current_stmt == s) // we're not nested any deeper than expected + if (vut.side_effect_free_wrt (focal_vars)) { /* PR 1119: NB: this message is not a good idea here. It can name some arbitrary RHS expression of an assignment. @@ -2405,10 +2390,10 @@ dead_stmtexpr_remover::visit_expr_statement (expr_statement *s) // NB: this 0 pointer is invalid to leave around for any length of // time, but the parent parse tree objects above handle it. - * current_stmt = 0; - + s = 0; relaxed_p = false; } + provide (s); } @@ -2433,8 +2418,7 @@ void semantic_pass_opt4 (systemtap_session& s, bool& relaxed_p) duv.focal_vars.insert (p->locals.begin(), p->locals.end()); - duv.current_stmt = & p->body; - p->body->visit (& duv); + p->body = duv.require(p->body, true); if (p->body == 0) { if (! s.suppress_warnings) @@ -2459,8 +2443,7 @@ void semantic_pass_opt4 (systemtap_session& s, bool& relaxed_p) duv.focal_vars.insert (s.globals.begin(), s.globals.end()); - duv.current_stmt = & fn->body; - fn->body->visit (& duv); + fn->body = duv.require(fn->body, true); if (fn->body == 0) { if (! s.suppress_warnings) diff --git a/staptree.cxx b/staptree.cxx index 2b963bc3..9ffbaf09 100644 --- a/staptree.cxx +++ b/staptree.cxx @@ -2337,7 +2337,7 @@ update_visitor::visit_hist_op (hist_op* e) } template <> indexable* -update_visitor::require (indexable* src) +update_visitor::require (indexable* src, bool clearok) { indexable *dst = NULL; if (src != NULL) @@ -2351,7 +2351,7 @@ update_visitor::require (indexable* src) dst = require (array_src); else dst = require (hist_src); - assert (dst); + assert(clearok || dst); } return dst; } diff --git a/staptree.h b/staptree.h index 00809ed0..0cd0ee0d 100644 --- a/staptree.h +++ b/staptree.h @@ -815,7 +815,7 @@ struct throwing_visitor: public visitor struct update_visitor: public visitor { - template T require (T src) + template T require (T src, bool clearok=false) { T dst = NULL; if (src != NULL) @@ -824,7 +824,7 @@ struct update_visitor: public visitor assert(!targets.empty()); dst = static_cast(targets.top()); targets.pop(); - assert(dst); + assert(clearok || dst); } return dst; } @@ -874,7 +874,7 @@ private: }; template <> indexable* -update_visitor::require (indexable* src); +update_visitor::require (indexable* src, bool clearok); // A visitor which performs a deep copy of the root node it's applied // to. NB: It does not copy any of the variable or function -- cgit From 9f9873dfc0978ef3ce7b7b5aa7ae1e2b5b4909b9 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Tue, 10 Feb 2009 19:51:12 -0800 Subject: Simplify void_statement_reducer * elaborate.cxx (void_statement_reducer): Convert to an update_visitor. --- ChangeLog | 1 + elaborate.cxx | 161 ++++++++++++++++++++++++---------------------------------- 2 files changed, 68 insertions(+), 94 deletions(-) diff --git a/ChangeLog b/ChangeLog index 208c8150..13c57518 100644 --- a/ChangeLog +++ b/ChangeLog @@ -5,6 +5,7 @@ * elaborate.cxx (dead_assignment_remover): Convert into an update_visitor and remove its now-redundant traversal methods. * elaborate.cxx (dead_stmtexpr_remover): Convert to an update_visitor. + * elaborate.cxx (void_statement_reducer): Convert to an update_visitor. 2009-02-05 Josh Stone diff --git a/elaborate.cxx b/elaborate.cxx index bc9c4e7d..ba50defb 100644 --- a/elaborate.cxx +++ b/elaborate.cxx @@ -2468,21 +2468,27 @@ void semantic_pass_opt4 (systemtap_session& s, bool& relaxed_p) // into separate statements that evaluate each subcomponent of the expression. // The dead-statement-remover can later remove some parts if they have no side // effects. -struct void_statement_reducer: public traversing_visitor +// +// All expressions must be overridden here so we never visit their subexpressions +// accidentally. Thus, the only visited expressions should be value of an +// expr_statement. +// +// For an expression to replace its expr_statement with something else, it will +// let the new statement provide(), and then provide(0) for itself. The +// expr_statement will take this as a sign that it's been replaced. +struct void_statement_reducer: public update_visitor { systemtap_session& session; bool& relaxed_p; - statement** current_stmt; // pointer to current stmt* being iterated - expr_statement* current_expr; // pointer to current expr being iterated set focal_vars; // vars considered subject to side-effects void_statement_reducer(systemtap_session& s, bool& r): - session(s), relaxed_p(r), current_stmt(0), current_expr(0) {} + session(s), relaxed_p(r) {} - // these just maintain current_stmt while recursing, but don't visit - // expressions in the conditional / loop controls. void visit_expr_statement (expr_statement* s); - void visit_block (block *s); + + // expressions in conditional / loop controls are definitely a side effect, + // but still recurse into the child statements void visit_if_statement (if_statement* s); void visit_for_loop (for_loop* s); void visit_foreach_loop (foreach_loop* s); @@ -2502,72 +2508,54 @@ struct void_statement_reducer: public traversing_visitor // these are a bit hairy to grok due to the intricacies of indexables and // stats, so I'm chickening out and skipping them... - void visit_array_in (array_in* e) {} - void visit_arrayindex (arrayindex* e) {} - void visit_stat_op (stat_op* e) {} - void visit_hist_op (hist_op* e) {} + void visit_array_in (array_in* e) { provide (e); } + void visit_arrayindex (arrayindex* e) { provide (e); } + void visit_stat_op (stat_op* e) { provide (e); } + void visit_hist_op (hist_op* e) { provide (e); } // these can't be reduced because they always have an effect - void visit_return_statement (return_statement* s) {} - void visit_delete_statement (delete_statement* s) {} - void visit_pre_crement (pre_crement* e) {} - void visit_post_crement (post_crement* e) {} - void visit_assignment (assignment* e) {} + void visit_return_statement (return_statement* s) { provide (s); } + void visit_delete_statement (delete_statement* s) { provide (s); } + void visit_pre_crement (pre_crement* e) { provide (e); } + void visit_post_crement (post_crement* e) { provide (e); } + void visit_assignment (assignment* e) { provide (e); } }; void void_statement_reducer::visit_expr_statement (expr_statement* s) { - assert(!current_expr); // it shouldn't be possible to have nested expr's - current_expr = s; - s->value->visit (this); - current_expr = NULL; -} + s->value = require (s->value, true); -void -void_statement_reducer::visit_block (block *s) -{ - statement** last_stmt = current_stmt; - for (unsigned i=0; istatements.size(); i++ ) - { - current_stmt = & s->statements[i]; - s->statements[i]->visit (this); - } - current_stmt = last_stmt; + // if the expression provides 0, that's our signal that a new + // statement has been provided, so we shouldn't provide this one. + if (s->value != 0) + provide(s); } void void_statement_reducer::visit_if_statement (if_statement* s) { - statement** last_stmt = current_stmt; - current_stmt = & s->thenblock; - s->thenblock->visit (this); - - if (s->elseblock) - { - current_stmt = & s->elseblock; - s->elseblock->visit (this); - } - current_stmt = last_stmt; + // s->condition is never void + s->thenblock = require (s->thenblock); + s->elseblock = require (s->elseblock); + provide (s); } void void_statement_reducer::visit_for_loop (for_loop* s) { - statement** last_stmt = current_stmt; - current_stmt = & s->block; - s->block->visit (this); - current_stmt = last_stmt; + // s->init/cond/incr are never void + s->block = require (s->block); + provide (s); } void void_statement_reducer::visit_foreach_loop (foreach_loop* s) { - statement** last_stmt = current_stmt; - current_stmt = & s->block; - s->block->visit (this); - current_stmt = last_stmt; + // s->indexes/base/limit are never void + s->block = require (s->block); + provide (s); } void @@ -2576,8 +2564,6 @@ void_statement_reducer::visit_logical_or_expr (logical_or_expr* e) // In void context, the evaluation of "a || b" is exactly like // "if (!a) b", so let's do that instead. - assert(current_expr && current_expr->value == e); - if (session.verbose>2) clog << "Creating if statement from unused logical-or " << *e->tok << endl; @@ -2585,8 +2571,6 @@ void_statement_reducer::visit_logical_or_expr (logical_or_expr* e) if_statement *is = new if_statement; is->tok = e->tok; is->elseblock = 0; - *current_stmt = is; - current_expr = NULL; unary_expression *ue = new unary_expression; ue->operand = e->left; @@ -2601,6 +2585,8 @@ void_statement_reducer::visit_logical_or_expr (logical_or_expr* e) is->visit(this); relaxed_p = false; + e = 0; + provide (e); } void @@ -2609,8 +2595,6 @@ void_statement_reducer::visit_logical_and_expr (logical_and_expr* e) // In void context, the evaluation of "a && b" is exactly like // "if (a) b", so let's do that instead. - assert(current_expr && current_expr->value == e); - if (session.verbose>2) clog << "Creating if statement from unused logical-and " << *e->tok << endl; @@ -2619,8 +2603,6 @@ void_statement_reducer::visit_logical_and_expr (logical_and_expr* e) is->tok = e->tok; is->elseblock = 0; is->condition = e->left; - *current_stmt = is; - current_expr = NULL; expr_statement *es = new expr_statement; es->value = e->right; @@ -2629,6 +2611,8 @@ void_statement_reducer::visit_logical_and_expr (logical_and_expr* e) is->visit(this); relaxed_p = false; + e = 0; + provide (e); } void @@ -2637,8 +2621,6 @@ void_statement_reducer::visit_ternary_expression (ternary_expression* e) // In void context, the evaluation of "a ? b : c" is exactly like // "if (a) b else c", so let's do that instead. - assert(current_expr && current_expr->value == e); - if (session.verbose>2) clog << "Creating if statement from unused ternary expression " << *e->tok << endl; @@ -2646,8 +2628,6 @@ void_statement_reducer::visit_ternary_expression (ternary_expression* e) if_statement *is = new if_statement; is->tok = e->tok; is->condition = e->cond; - *current_stmt = is; - current_expr = NULL; expr_statement *es = new expr_statement; es->value = e->truevalue; @@ -2661,6 +2641,8 @@ void_statement_reducer::visit_ternary_expression (ternary_expression* e) is->visit(this); relaxed_p = false; + e = 0; + provide (e); } void @@ -2669,15 +2651,11 @@ void_statement_reducer::visit_binary_expression (binary_expression* e) // When the result of a binary operation isn't needed, it's just as good to // evaluate the operands as sequential statements in a block. - assert(current_expr && current_expr->value == e); - if (session.verbose>2) clog << "Eliding unused binary " << *e->tok << endl; block *b = new block; - b->tok = current_expr->tok; - *current_stmt = b; - current_expr = NULL; + b->tok = e->tok; expr_statement *es = new expr_statement; es->value = e->left; @@ -2691,6 +2669,8 @@ void_statement_reducer::visit_binary_expression (binary_expression* e) b->visit(this); relaxed_p = false; + e = 0; + provide (e); } void @@ -2699,16 +2679,11 @@ void_statement_reducer::visit_unary_expression (unary_expression* e) // When the result of a unary operation isn't needed, it's just as good to // evaluate the operand directly - assert(current_expr && current_expr->value == e); - if (session.verbose>2) clog << "Eliding unused unary " << *e->tok << endl; - current_expr->value = e->operand; - current_expr->tok = current_expr->value->tok; - current_expr->value->visit(this); - relaxed_p = false; + e->operand->visit(this); } void @@ -2730,24 +2705,26 @@ void_statement_reducer::visit_functioncall (functioncall* e) // and just evaluate the arguments in sequence if (!e->args.size()) - return; + { + provide (e); + return; + } varuse_collecting_visitor vut; vut.traversed.insert (e->referent); vut.current_function = e->referent; e->referent->body->visit (& vut); if (!vut.side_effect_free_wrt (focal_vars)) - return; - - assert(current_expr && current_expr->value == e); + { + provide (e); + return; + } if (session.verbose>2) clog << "Eliding side-effect-free function call " << *e->tok << endl; block *b = new block; b->tok = e->tok; - *current_stmt = b; - current_expr = NULL; for (unsigned i=0; iargs.size(); i++ ) { @@ -2759,6 +2736,8 @@ void_statement_reducer::visit_functioncall (functioncall* e) b->visit(this); relaxed_p = false; + e = 0; + provide (e); } void @@ -2768,17 +2747,16 @@ void_statement_reducer::visit_print_format (print_format* e) // arguments in sequence if (e->print_to_stream || !e->args.size()) - return; - - assert(current_expr && current_expr->value == e); + { + provide (e); + return; + } if (session.verbose>2) clog << "Eliding unused print " << *e->tok << endl; block *b = new block; b->tok = e->tok; - *current_stmt = b; - current_expr = NULL; for (unsigned i=0; iargs.size(); i++ ) { @@ -2790,6 +2768,8 @@ void_statement_reducer::visit_print_format (print_format* e) b->visit(this); relaxed_p = false; + e = 0; + provide (e); } @@ -2803,17 +2783,10 @@ void semantic_pass_opt5 (systemtap_session& s, bool& relaxed_p) vuv.focal_vars.insert (s.globals.begin(), s.globals.end()); for (unsigned i=0; ibody; - p->body->visit (& vuv); - } - for (map::iterator it = s.functions.begin(); it != s.functions.end(); it++) - { - functiondecl* fn = it->second; - vuv.current_stmt = & fn->body; - fn->body->visit (& vuv); - } + s.probes[i]->body = vuv.require (s.probes[i]->body); + for (map::iterator it = s.functions.begin(); + it != s.functions.end(); it++) + it->second->body = vuv.require (it->second->body); } -- cgit