From: Ketan Dixit Date: Thu, 16 Sep 2010 00:06:29 +0000 (-0400) Subject: Generic param capture for pointcut X-Git-Tag: release-v1.0~40^2~6 X-Git-Url: https://git.fsl.cs.stonybrook.edu/?a=commitdiff_plain;h=f67a0f58cdf62c5da06061b2cb7b0f558d6040ff;p=interaspect.git Generic param capture for pointcut --- diff --git a/src/aop-dynval.h b/src/aop-dynval.h index 3c32266..bb706f7 100644 --- a/src/aop-dynval.h +++ b/src/aop-dynval.h @@ -28,6 +28,10 @@ enum aop_dvkind { ADV_ASSIGN_VAL, }; +struct aop_dynval_in_param { + int param_index; +}; + struct aop_dynval_fun_call { int param_index; }; @@ -44,6 +48,7 @@ struct aop_dynval union { struct aop_dynval_fun_call dynval_call; + struct aop_dynval_in_param dynval_in_param; }; /* Ops vector for aop_dynval. */ diff --git a/src/aop-pc-entry.c b/src/aop-pc-entry.c index b1afec8..49157fc 100644 --- a/src/aop-pc-entry.c +++ b/src/aop-pc-entry.c @@ -33,9 +33,11 @@ #include #include #include +#include #include "aop.h" #include "aop-duplicate.h" +#include "aop-dynval.h" #include "aop-pointcut.h" #include "aop-type.h" @@ -84,7 +86,8 @@ is_function_entry_matching (struct aop_pointcut *pc) const char *func_name = IDENTIFIER_POINTER (DECL_NAME (current_function_decl)); return (strcmp (func_name, pc->pc_entry.function_name) == 0); - } + } + return check_in_params (pc); } /* We represent the function's entry as a control-flow graph edge. @@ -199,6 +202,7 @@ aop_match_function_entry () pc->prepare_for_weave = op_prepare_entry; pc->pc_entry.function_name = NULL; + pc->in_param_list_head = NULL; return pc; } @@ -208,6 +212,54 @@ void aop_filter_entry_by_name(struct aop_pointcut *pc_function_entry, pc_function_entry->pc_entry.function_name = advice_function_entry; } +/** + * Filter a function entry pointcut to only include function entries + * with a parameter that matches a specified type. This filter removes join + * points when parameter n does not match type or when there is no + * parameter n. + * + * Filters on the same parameter do not stack on top of each other. + * If multiple parameter filters with the same n are applied a + * pointcut, only the last one will have any effect. + * + * Note that you must filter a parameter by its type in order to + * capture it with aop_capture_in_param(). + * \param pc The function call pointcut to filter. Function entry + * pointcuts are created with aop_match_function_entry(). + * \param n The index of the parameter to filter on. Parameters are + * indexed from zero. + * \param The parameter type to filter by. + */ +void +aop_filter_entry_by_in_param (struct aop_pointcut *pc, int n, + const struct aop_type *type) +{ + struct aop_param_desc *param = NULL; + struct aop_param_desc *iter; + + /* Is there already a filter for this parameter? */ + for (iter = pc->in_param_list_head ; iter != NULL ; iter = iter->next) + { + if (iter->param_index == n) + { + param = iter; + break; + } + } + + /* No? Then create one and add it to the list. */ + if (param == NULL) + { + param = ggc_alloc (sizeof (struct aop_param_desc)); + + param->next = pc->in_param_list_head; + pc->in_param_list_head = param; + } + + param->param_index = n; + param->type = type; +} + /* Close Doxygen defgroup block. */ /** * \} diff --git a/src/aop-pointcut.c b/src/aop-pointcut.c index 3663666..7d61d69 100644 --- a/src/aop-pointcut.c +++ b/src/aop-pointcut.c @@ -26,12 +26,15 @@ #include #include #include +#include #include #include #include #include "aop.h" +#include "aop-dynval.h" #include "aop-pointcut.h" +#include "aop-type.h" /* Allocates a pointcut and initializes it with default values. */ struct aop_pointcut * @@ -78,3 +81,123 @@ aop_capture_file_name (struct aop_joinpoint *jp) { return jp->file; } + +static tree +op_get_in_param (struct aop_dynval *dv) +{ + gimple stmt; + tree param; + tree param_iter; + struct aop_joinpoint *jp = dv->jp; + int index = 0; + + aop_assert (dv->kind == ADV_FUN_PARAM); + aop_assert (jp->pc->kind == ATP_ENTRY); + + stmt = jp->stmt; + + for (param_iter = DECL_ARGUMENTS (current_function_decl); + param_iter; param_iter = TREE_CHAIN (param_iter)) + { + if (index == dv->dynval_in_param.param_index) + { + param = param_iter; + param = stabilize_reference (param); + break; + } + index++; + } + return param; +} + +/** + * Get a dynval representing parameter n passed to a function call. + * Note that you must use aop_filter_entry_by_in_param() to filter a + * pointcut by parameter type for any parameter you wish to capture + * with this function. + * \param jp A function call join point. Function entry join points + * are obtained by joining on an aop_match_function_entry() pointcut. + * \param n The index of the parameter to capture. Parameters are + * indexed from zero. + * \return A dynval with its type determined by + * aop_filter_call_pc_by_param(). + */ +struct aop_dynval * +aop_capture_in_param (struct aop_joinpoint *jp, int n) +{ + struct aop_pointcut *pc; + struct aop_dynval *dv; + struct aop_param_desc *param; + + pc = jp->pc; + if (pc->kind != ATP_ENTRY) + fatal_error ("(InterAspect) Attempt to capture parameter from an" + " unsupported join point."); + + /* Search for an aop_param_desc for this parameter, so that we know + its type. */ + for (param = pc->in_param_list_head; param != NULL; param = param->next) + if (param->param_index == n) + break; /* Found it. */ + + /* If we don't find the appropriate aop_param_desc, param will be NULL. */ + if (param == NULL) + fatal_error ("(InterAspect) Attempt to capture parameter without specifying" + " type."); + + dv = ggc_alloc (sizeof (struct aop_dynval)); + dv->kind = ADV_FUN_PARAM; + dv->type = param->type; + dv->jp = jp; + dv->get_dynval = op_get_in_param; + dv->dynval_in_param.param_index = n; + return dv; +} + +bool +check_in_param (struct aop_param_desc *param_desc) +{ + tree param_type; + tree param_decl; + int index = 0; + bool index_found = false; + for (param_decl = DECL_ARGUMENTS (current_function_decl); + param_decl; param_decl = TREE_CHAIN (param_decl)) + { + if (index == param_desc->param_index) + { + /* Index found check the type */ + if ((param_type = TREE_TYPE (param_decl)) == NULL + || !does_type_match (param_type, param_desc->type)) + index_found = false; + else + index_found = true; + + break; + } + index++; + } + return index_found; +} + +bool +check_in_params (struct aop_pointcut *pc) +{ + struct aop_param_desc *param_desc; + bool params_matched = false; + /* Check parameter types. */ + for (param_desc = pc->in_param_list_head ; param_desc != NULL ; + param_desc = param_desc->next) + { + if(!check_in_param (param_desc)) + { + params_matched = false; + break; + } + else + { + params_matched = true; + } + } + return params_matched; +} diff --git a/src/aop-pointcut.h b/src/aop-pointcut.h index 1cd103c..00a7bce 100644 --- a/src/aop-pointcut.h +++ b/src/aop-pointcut.h @@ -76,6 +76,8 @@ struct aop_pointcut { any advice gets inserted at that joinpoint. */ void (*prepare_for_weave) (struct aop_joinpoint *); + struct aop_param_desc *in_param_list_head; + union { struct aop_pc_assign pc_assign; struct aop_pc_entry pc_entry; @@ -124,4 +126,5 @@ void op_default_prepare_for_weave (struct aop_joinpoint *jp); void op_default_insert_before (struct aop_joinpoint *jp, gimple stmt); void op_default_insert_after (struct aop_joinpoint *jp, gimple stmt); +bool check_in_params (struct aop_pointcut *pc); #endif diff --git a/src/aop.h b/src/aop.h index fb322dc..2e5393d 100644 --- a/src/aop.h +++ b/src/aop.h @@ -254,6 +254,11 @@ enum aop_argkind { extern const char *aop_capture_function_name (struct aop_joinpoint *jp); extern struct aop_pointcut *aop_match_function_entry (); +extern void aop_filter_entry_by_in_param (struct aop_pointcut *pc, int n, + const struct aop_type *type); +extern struct aop_dynval *aop_capture_in_param (struct aop_joinpoint *jp, + int param_index); + extern struct aop_pointcut *aop_match_function_exit (); extern void aop_filter_entry_by_name(struct aop_pointcut *pc_function_entry,