aop_join_on_copy() support for function entry pointcuts.
authorJustin Seyster <jseyster@cs.sunysb.edu>
Thu, 12 Aug 2010 22:59:51 +0000 (18:59 -0400)
committerJustin Seyster <jseyster@cs.sunysb.edu>
Thu, 12 Aug 2010 22:59:51 +0000 (18:59 -0400)
Added in_edge field to join points to support this feature.

src/aop-pc-entry.c
src/aop-pointcut.c
src/aop-pointcut.h

index a3fae6ab76754f35ea1a84b792aaaa7d2a7389fc..cd1179a788bbe62c8e17ec9cc3fd95e443651536 100644 (file)
@@ -34,6 +34,7 @@
 #include <string.h>
 
 #include "aop.h"
+#include "aop-duplicate.h"
 #include "aop-pointcut.h"
 #include "aop-type.h"
 
  * \{
  */
 
-static void
-op_join_on_function_entry (struct aop_pointcut *pc, join_callback cb,
-                          void *callback_param)
+/* Function have only one entry.  Return true if that entry matches
+   the pointcut's filtering criteria. */
+static bool
+is_function_entry_matching (struct aop_pointcut *pc)
 {
-  struct aop_joinpoint jp;
-  gimple_stmt_iterator gsi;
-
-  aop_assert (pc->kind == ATP_ENTRY);
-
-  /* Filter this pointcut by function name if necessary. */
-  if(pc->pc_entry.function_name != NULL)
+  /* Filter by name. */
+  if(pc->pc_entry.function_name == NULL)
+    {
+      /* No name filter in place. */
+      return true;
+    }
+  else
     {
       const char *func_name =
        IDENTIFIER_POINTER (DECL_NAME (current_function_decl));
-      if (strcmp (func_name, pc->pc_entry.function_name) != 0)
-       return;
-    }
+      return (strcmp (func_name, pc->pc_entry.function_name) == 0);
+    }  
+}
+
+/* We represent the function's entry as a control-flow graph edge.
+   That edge is the only thing necessary to join on the pointcut's one
+   join point. */
+static void
+join_on_entry_edge (struct aop_pointcut *pc, edge in_edge, join_callback cb,
+                   void *callback_param)
+{
+  struct aop_joinpoint jp;
+  gimple_stmt_iterator gsi;
 
   /* Note that the gimple iterator gets initialized by
      op_prepare_entry when it is time to insert advice.  (We poison it
@@ -66,15 +78,48 @@ op_join_on_function_entry (struct aop_pointcut *pc, join_callback cb,
   memset (&gsi, 0xfa, sizeof (gimple_stmt_iterator));
 
   init_joinpoint (&jp, &gsi, pc, NULL);
+  jp.in_edge = in_edge;
   cb (&jp, callback_param);
 }
 
+static void
+op_join_on_function_entry (struct aop_pointcut *pc, join_callback cb,
+                          void *callback_param)
+{
+  edge in_edge;
+
+  aop_assert (pc->kind == ATP_ENTRY);
+
+  if (!is_function_entry_matching (pc))
+    return;
+
+  /* Get the function's actual entry point: the edge coming out of the
+     entry block. */  
+  in_edge = single_succ_edge (ENTRY_BLOCK_PTR_FOR_FUNCTION (cfun));
+  join_on_entry_edge (pc, in_edge, cb, callback_param);
+}
+
 static void 
 op_join_on_copy_function_entry (struct aop_pointcut *pc, int copy,
                                join_callback cb, void *callback_param)
 {
-  /* Not yet supported. */
-  aop_assert(0);
+  int last_copy;
+  edge in_edge;
+
+  aop_assert (pc->kind == ATP_ENTRY);
+  aop_assert (is_current_func_duplicated ());
+
+  if (!is_function_entry_matching (pc))
+    return;
+
+  /* We wish to join on the entry to the duplicated function body.
+     This will be one of the edges coming out of the distributor
+     block. */
+  last_copy = EDGE_COUNT (distributor_bb->succs) - 1;
+  copy = (copy <= last_copy) ? copy : last_copy;
+  in_edge = EDGE_SUCC (distributor_bb, copy);
+
+  join_on_entry_edge (pc, in_edge, cb, callback_param);
 }
 
 /* There is no GIMPLE statement that is suitable as an anchor point
@@ -93,14 +138,12 @@ op_prepare_entry (struct aop_joinpoint *jp)
 {
   gimple nop;
   basic_block bb;
-  edge in_edge;
 
   aop_assert (jp->pc->kind = ATP_ENTRY);
+  aop_assert (jp->in_edge != NULL);
 
   nop = gimple_build_nop ();
-
-  in_edge = single_succ_edge (ENTRY_BLOCK_PTR_FOR_FUNCTION(cfun));
-  gsi_insert_on_edge_immediate (in_edge, nop);
+  gsi_insert_on_edge_immediate (jp->in_edge, nop);
 
   /* Find an iterator pointing to the nop. */
   FOR_EACH_BB (bb)
@@ -114,7 +157,7 @@ op_prepare_entry (struct aop_joinpoint *jp)
        }
     }
 
-  /* We failed to found the statement we just inserted! */
+  /* We failed to find the statement we just inserted! */
   aop_assert (0);
 }
 
index 587b097f55ed26e75f2355af34a6333a640792df..086feefc10bf90c726e0ccf60396a18844470c24 100644 (file)
@@ -59,5 +59,6 @@ init_joinpoint (struct aop_joinpoint *jp, gimple_stmt_iterator *gsi,
   jp->pc = pc;
   jp->gsi = gsi;
   jp->stmt = stmt;
+  jp->in_edge = NULL;
   jp->is_prepared = false;
 }
index e12966dec045cc89adaab6817ae67b1163315a46..c86fc2dc3a547a0db5479521fee21ee18228aee7 100644 (file)
@@ -101,6 +101,10 @@ struct aop_joinpoint {
   /* The GIMPLE statement being instrumented (where relevant). */
   gimple stmt;
 
+  /* The control-flow graph edge representing function entry (used
+     only for the function entry pointcut). */
+  edge in_edge;
+
   /* True if prepare_for_weave() has been called for this
      joinpoint. */
   bool is_prepared;