]> sourceware.org Git - systemtap.git/commitdiff
PR12151: Add new visitor
authorFelix Lu <flu@redhat.com>
Mon, 20 Jul 2015 15:37:03 +0000 (11:37 -0400)
committerFelix Lu <flu@redhat.com>
Fri, 14 Aug 2015 17:39:30 +0000 (13:39 -0400)
* elaborate.cxx - new visitor to support optimization

elaborate.cxx
staptree.cxx
tapset/linux/context.stp

index 00678bffc33348be07456c57fcdbd114b37d180b..9e08c77ccfa5bcde01859b8594787c0b32f42722 100644 (file)
@@ -4221,6 +4221,136 @@ void semantic_pass_opt6 (systemtap_session& s, bool& relaxed_p)
     }
 }
 
+struct stable_tag_checker: public embedded_tags_visitor
+{
+  bool stable;
+  embeddedcode* code;
+  stable_tag_checker (): embedded_tags_visitor(true), stable(false) {}
+  void visit_embeddedcode (embeddedcode* e);
+};
+
+void stable_tag_checker::visit_embeddedcode (embeddedcode* e)
+{
+  code = e;
+  embedded_tags_visitor::visit_embeddedcode(e);
+  if (tagged_p("/* stable */"))
+    stable = true;
+}
+
+struct test_visitor: public update_visitor
+{
+  systemtap_session& session;
+  functiondecl* current_function;
+  derived_probe* current_probe;
+  map<string,vardecl*> replaced;
+  vector<expr_statement*> new_stmts;
+  test_visitor(systemtap_session& s):
+    session(s), current_function(0), current_probe(0) {};
+
+  void visit_functioncall (functioncall* e);
+};
+
+void test_visitor::visit_functioncall (functioncall* e)
+{
+  if (!e->args.size())
+    {
+      varuse_collecting_visitor vut(session);
+      vut.current_function = e->referent;
+      e->referent->body->visit(&vut);
+
+      stable_tag_checker stc;
+      e->referent->body->visit(&stc);
+
+      if (stc.stable)
+        {
+          assert(stc.code);
+          if (!vut.side_effect_free())
+            throw SEMANTIC_ERROR(_("stable function must also be /* pure */"),
+                stc.code->tok);
+
+          string name("__stable_");
+          name.append(e->function).append("_value");
+
+          if (replaced.find(e->function) == replaced.end())
+            {
+              // New variable declaration to store result of function call
+              vardecl* v = new vardecl;
+              v->name = name;
+              v->tok = e->tok;
+              v->set_arity(0, e->tok);
+              v->type = e->type;
+              if (current_function)
+                current_function->locals.push_back(v);
+              else
+                current_probe->locals.push_back(v);
+
+              symbol* sym = new symbol;
+              sym->name = name;
+              sym->tok = e->tok;
+              sym->referent = v;
+              sym->type = e->type;
+
+              functioncall* fc = new functioncall;
+              fc->tok = e->tok;
+              fc->function = e->function;
+              fc->referent = e->referent;
+              fc->type = e->type;
+
+              assignment* a = new assignment;
+              a->tok = e->tok;
+              a->op = "=";
+              a->left = sym;
+              a->right = fc;
+              a->type = e->type;
+
+              expr_statement* es = new expr_statement;
+              es->tok = e->tok;
+              es->value = a;
+              new_stmts.push_back(es);
+
+              replaced[e->function] = v;
+              provide(sym);
+            }
+          else
+            {
+              // Function call value already stored
+              symbol* sym = new symbol;
+              sym->name = name;
+              sym->tok = e->tok;
+              sym->referent = replaced[e->function];
+              sym->type = e->type;
+              provide(sym);
+            }
+          return;
+        }
+    }
+
+  provide(e);
+}
+
+void optimize_test(systemtap_session& s)
+{
+  for (vector<derived_probe*>::const_iterator it = s.probes.begin();
+       it != s.probes.end(); ++it)
+    {
+      test_visitor t(s);
+      t.current_probe = *it;
+      t.replace((*it)->body);
+      block* b = static_cast<block*>((*it)->body);
+      b->statements.insert(b->statements.begin(), t.new_stmts.begin(),
+                           t.new_stmts.end());
+    }
+  for (map<string,functiondecl*>::const_iterator fn = s.functions.begin();
+       fn != s.functions.end(); ++fn)
+    {
+      test_visitor t(s);
+      t.current_function = (*fn).second;
+      t.replace((*fn).second->body);
+      block* b = static_cast<block*>((*fn).second->body);
+      b->statements.insert(b->statements.begin(), t.new_stmts.begin(),
+                           t.new_stmts.end());
+    }
+}
 
 static int
 semantic_pass_optimize1 (systemtap_session& s)
@@ -4310,6 +4440,9 @@ semantic_pass_optimize2 (systemtap_session& s)
       iterations++;
     }
 
+  if (!s.unoptimized)
+    optimize_test(s);
+
   return rc;
 }
 
index 9e72465a6d707e1bff9a1d507e828e3f3dd9dae8..e6626508c2a01559c8725aeffc4f61e6b672d81a 100644 (file)
@@ -590,6 +590,7 @@ embedded_tags_visitor::embedded_tags_visitor(bool all_tags)
       available_tags.insert("/* pure */");
       available_tags.insert("/* unmangled */");
       available_tags.insert("/* unmodified-fnargs */");
+      available_tags.insert("/* stable */");
     }
 }
 
index 4a7e2fca9c576b06e042528646286ce850e1f919..92ab1b73fc8c6bdfa94aa622270f60fed6386cd7 100644 (file)
@@ -15,7 +15,7 @@
  * Description: Returns the execname of a target process (or group of processes).
  */
 function execname:string ()
-%{ /* pure */ /* unprivileged */
+%{ /* pure */ /* unprivileged */ /* stable */
        strlcpy (STAP_RETVALUE, current->comm, MAXSTRINGLEN);
 %}
 
@@ -25,7 +25,7 @@ function execname:string ()
  * Description: This function returns the ID of a target process.
  */
 function pid:long ()
-%{ /* pure */ /* unprivileged */
+%{ /* pure */ /* unprivileged */ /* stable */
        STAP_RETVALUE = current->tgid;
 %}
 
@@ -36,7 +36,7 @@ function pid:long ()
  * the target pid namespace.
  */
 function ns_pid:long ()
-%{ /* pure */ /* unprivileged */
+%{ /* pure */ /* unprivileged */ /* stable */
   int64_t rc = from_target_pid_ns(current, PID);
   if (rc < 0) STAP_ERROR ("cannot resolve id in namespace");
   else STAP_RETURN (rc);
@@ -48,7 +48,7 @@ function ns_pid:long ()
  * Description: This function returns the thread ID of the target process.
  */
 function tid:long ()
-%{ /* pure */ /* unprivileged */
+%{ /* pure */ /* unprivileged */ /* stable */
        STAP_RETVALUE = current->pid;
 %}
 
@@ -59,7 +59,7 @@ function tid:long ()
  * in  the target pid namespace if provided, or the stap process namespace.
  */
 function ns_tid:long ()
-%{ /* pure */ /* unprivileged */
+%{ /* pure */ /* unprivileged */ /* stable */
   int64_t rc = from_target_pid_ns(current, TID);
   if (rc < 0) STAP_ERROR ("cannot resolve id in namespace");
   else STAP_RETURN (rc);
@@ -71,7 +71,7 @@ function ns_tid:long ()
  * Description: This function return the process ID of the target proccess's parent process.
  */
 function ppid:long()
-%{ /* pure */ /* unprivileged */
+%{ /* pure */ /* unprivileged */ /* stable */
 #if defined(STAPCONF_REAL_PARENT)
        STAP_RETVALUE = current->real_parent->tgid;
 #else
@@ -85,7 +85,7 @@ function ppid:long()
  * Description: This function return the process ID of the target proccess's parent process as seen in  the target pid namespace if provided, or the stap process namespace.
  */
 function ns_ppid:long()
-%{ /* pure */ /* unprivileged */
+%{ /* pure */ /* unprivileged */ /* stable */
   int64_t rc = from_target_pid_ns(current->parent, PID);
   if (rc < 0) STAP_ERROR ("cannot resolve id in namespace");
   else STAP_RETURN (rc);
@@ -98,7 +98,7 @@ function ns_ppid:long()
  * current process.
  */
 function pgrp:long ()
-%{ /* pure */ /* unprivileged */
+%{ /* pure */ /* unprivileged */ /* stable */
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
        struct signal_struct *ss = kread( &(current->signal) );
        STAP_RETVALUE = kread ( &(ss->pgrp) );
@@ -115,7 +115,7 @@ function pgrp:long ()
  * current process as seen in  the target pid namespace if provided, or the stap process namespace.
  */
 function ns_pgrp:long ()
-%{ /* pure */ /* unprivileged */
+%{ /* pure */ /* unprivileged */ /* stable */
   int64_t rc = from_target_pid_ns(current, PGRP);
   if (rc < 0) STAP_ERROR ("cannot resolve id in namespace");
   else STAP_RETURN (rc);
@@ -129,7 +129,7 @@ function ns_pgrp:long ()
  *  since Kernel 2.6.0.
  */
 function sid:long ()
-%{ /* pure */ /* unprivileged */
+%{ /* pure */ /* unprivileged */ /* stable */
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
        struct signal_struct *ss = kread( &(current->signal) );
        STAP_RETVALUE = kread ( &(ss->session) );
@@ -147,7 +147,7 @@ function sid:long ()
  *  since Kernel 2.6.0.
  */
 function ns_sid:long ()
-%{ /* pure */ /* unprivileged */
+%{ /* pure */ /* unprivileged */ /* stable */
   int64_t rc = from_target_pid_ns(current, SID);
   if (rc < 0) STAP_ERROR ("cannot resolve id in namespace");
   else STAP_RETURN (rc);
@@ -160,7 +160,7 @@ function ns_sid:long ()
  * process's parent procces.
  */
 function pexecname:string ()
-%{ /* pure */ /* unprivileged */
+%{ /* pure */ /* unprivileged */ /* stable */
 #if defined(STAPCONF_REAL_PARENT)
        strlcpy (STAP_RETVALUE, current->real_parent->comm, MAXSTRINGLEN);
 #else
@@ -174,7 +174,7 @@ function pexecname:string ()
  * Description: This function returns the group ID of a target process.
  */
 function gid:long ()
-%{ /* pure */ /* unprivileged */
+%{ /* pure */ /* unprivileged */ /* stable */
 #ifdef STAPCONF_TASK_UID
        STAP_RETVALUE = current->gid;
 #else
@@ -192,7 +192,7 @@ function gid:long ()
  * Description: This function returns the group ID of a target process as seen in the target user namespace if provided, or the stap process namespace.
  */
 function ns_gid:long ()
-%{ /* pure */ /* unprivileged */
+%{ /* pure */ /* unprivileged */ /* stable */
   int64_t rc = from_target_user_ns(current, GID);
   if (rc < 0) STAP_ERROR ("cannot resolve id in namespace");
   else STAP_RETURN (rc);
@@ -204,7 +204,7 @@ function ns_gid:long ()
  * Description: This function returns the effective gid of a target process
  */
 function egid:long ()
-%{ /* pure */ /* unprivileged */
+%{ /* pure */ /* unprivileged */ /* stable */
 #ifdef STAPCONF_TASK_UID
        STAP_RETVALUE = current->egid;
 #else
@@ -222,7 +222,7 @@ function egid:long ()
  * Description: This function returns the effective gid of a target process as seen in the target user namespace if provided, or the stap process namespace
  */
 function ns_egid:long ()
-%{ /* pure */ /* unprivileged */
+%{ /* pure */ /* unprivileged */ /* stable */
   int64_t rc = from_target_user_ns(current, EGID);
   if (rc < 0) STAP_ERROR ("cannot resolve id in namespace");
   else STAP_RETURN (rc);
@@ -234,7 +234,7 @@ function ns_egid:long ()
  * Description: This function returns the user ID of the target process.
  */
 function uid:long ()
-%{ /* pure */ /* unprivileged */
+%{ /* pure */ /* unprivileged */ /* stable */
 #ifdef STAPCONF_TASK_UID
        STAP_RETVALUE = current->uid;
 #else
@@ -252,7 +252,7 @@ function uid:long ()
  * Description: This function returns the user ID of the target process as seen in the target user namespace if provided, or the stap process namespace.
  */
 function ns_uid:long ()
-%{ /* pure */ /* unprivileged */
+%{ /* pure */ /* unprivileged */ /* stable */
   int64_t rc = from_target_user_ns(current, UID);
   if (rc < 0) STAP_ERROR ("cannot resolve id in namespace");
   else STAP_RETURN (rc);
@@ -264,7 +264,7 @@ function ns_uid:long ()
  * Description: Returns the effective user ID of the target process.
  */
 function euid:long ()
-%{ /* pure */ /* unprivileged */
+%{ /* pure */ /* unprivileged */ /* stable */
 #ifdef STAPCONF_TASK_UID
        STAP_RETVALUE = current->euid;
 #else
@@ -282,7 +282,7 @@ function euid:long ()
  * Description: This function returns the effective user ID of the target process as seen in the target user namespace if provided, or the stap process namespace.
  */
 function ns_euid:long ()
-%{ /* pure */ /* unprivileged */
+%{ /* pure */ /* unprivileged */ /* stable */
   int64_t rc = from_target_user_ns(current, EUID);
   if (rc < 0) STAP_ERROR ("cannot resolve id in namespace");
   else STAP_RETURN (rc);
@@ -295,7 +295,7 @@ function ns_euid:long ()
  * point has occurred in the user's own process.
  */
 function is_myproc:long ()
-%{ /* pure */ /* unprivileged */
+%{ /* pure */ /* unprivileged */ /* stable */
         STAP_RETVALUE = is_myproc();
 %}
 
@@ -319,7 +319,7 @@ function cpuid:long ()
  * Description: This function returns the current cpu number.
  */
 function cpu:long ()
-%{ /* pure */ /* unprivileged */
+%{ /* pure */ /* unprivileged */ /* stable */
        STAP_RETVALUE = smp_processor_id();
 %}
 
@@ -332,7 +332,7 @@ function cpu:long ()
  * when called from a begin or end probe.
  */
 function registers_valid:long ()
-%{ /* pure */ /* unprivileged */
+%{ /* pure */ /* unprivileged */ /* stable */
        STAP_RETVALUE = (c->user_mode_p
                            ? (CONTEXT->uregs != NULL)
                            : (CONTEXT->kregs != NULL));
@@ -344,7 +344,7 @@ function registers_valid:long ()
  * Return 1 if the probe point occurred in user-mode.
  */
 function user_mode:long ()
-%{ /* pure */ /* unprivileged */
+%{ /* pure */ /* unprivileged */ /* stable */
   STAP_RETVALUE = CONTEXT->user_mode_p ? 1 : 0;
 %}
 
@@ -355,7 +355,7 @@ function user_mode:long ()
  * returns 0 otherwise.
  */
 function is_return:long ()
-%{ /* pure */
+%{ /* pure */ /* stable */ /* stable */
        if (CONTEXT->probe_type == stp_probe_type_kretprobe
            || CONTEXT->probe_type == stp_probe_type_uretprobe)
                STAP_RETVALUE = 1;
@@ -378,7 +378,7 @@ function is_return:long ()
  * target() returns the pid for the executed command specified by -c
  */
 function target:long ()
-%{ /* pure */ /* unprivileged */
+%{ /* pure */ /* unprivileged */ /* stable */
         STAP_RETVALUE = _stp_target;
 %}
 
@@ -390,7 +390,7 @@ function target:long ()
  * or set by stap -m <module_name>.
  */
 function module_name:string ()
-%{ /* pure */ /* unprivileged */
+%{ /* pure */ /* unprivileged */ /* stable */
        strlcpy(STAP_RETVALUE, THIS_MODULE->name, MAXSTRINGLEN);
 %}
 
@@ -443,7 +443,7 @@ function remote_uri:string () {
  * Description: This function returns the size of the kernel stack.
  */
 function stack_size:long ()
-%{ /* pure */
+%{ /* pure */ /* stable */
         STAP_RETVALUE = THREAD_SIZE;
 %}
 
@@ -454,7 +454,7 @@ function stack_size:long ()
  * currently used in the kernel stack.
  */
 function stack_used:long ()
-%{ /* pure */
+%{ /* pure */ /* stable */
        char a;
         STAP_RETVALUE = THREAD_SIZE - ((long)&a & (THREAD_SIZE-1));
 %}
@@ -466,7 +466,7 @@ function stack_used:long ()
  * currently available in the kernel stack.
  */
 function stack_unused:long ()
-%{ /* pure */
+%{ /* pure */ /* stable */
        char a;
         STAP_RETVALUE = (long)&a & (THREAD_SIZE-1);
 %}
@@ -480,7 +480,7 @@ function stack_unused:long ()
  * like symname() and symdata().
  */
 function addr:long ()
-%{ /* pure */
+%{ /* pure */ /* stable */
   if (CONTEXT->user_mode_p) {
     STAP_RETVALUE = (intptr_t)(CONTEXT->uregs ? REG_IP(CONTEXT->uregs) : 0);
   } else {
@@ -499,7 +499,7 @@ function addr:long ()
  * where it entered the kernel.
  */
 function uaddr:long ()
-%{ /* pure */ /* myproc-unprivileged */
+%{ /* pure */ /* myproc-unprivileged */ /* stable */
   struct pt_regs *uregs;
 
   if (CONTEXT->user_mode_p)
This page took 0.055918 seconds and 5 git commands to generate.