[PATCH 10/19] perf metric: Add referenced metrics to hash data
Adding referenced metrics to the parsing context so they can be resolved during the metric processing. Adding expr__add_ref function to store referenced metrics into parse context. Signed-off-by: Jiri Olsa Reviewed-by: Kajol Jain Acked-by: Ian Rogers Cc: Alexander Shishkin Cc: Andi Kleen Cc: John Garry Cc: Michael Petlan Cc: Namhyung Kim Cc: Paul Clarke Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20200719181320.785305-11-jo...@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/expr.c| 54 +++ tools/perf/util/expr.h| 13 - tools/perf/util/stat-shadow.c | 20 + 3 files changed, 80 insertions(+), 7 deletions(-) diff --git a/tools/perf/util/expr.c b/tools/perf/util/expr.c index f726211f49d4..d3997c2b4a90 100644 --- a/tools/perf/util/expr.c +++ b/tools/perf/util/expr.c @@ -4,10 +4,14 @@ #include #include #include +#include "metricgroup.h" +#include "debug.h" #include "expr.h" #include "expr-bison.h" #include "expr-flex.h" #include +#include +#include #ifdef PARSER_DEBUG extern int expr_debug; @@ -63,6 +67,7 @@ int expr__add_id_val(struct expr_parse_ctx *ctx, const char *id, double val) if (!data_ptr) return -ENOMEM; data_ptr->val = val; + data_ptr->is_ref = false; ret = hashmap__set(>ids, id, data_ptr, (const void **)_key, (void **)_data); @@ -73,6 +78,55 @@ int expr__add_id_val(struct expr_parse_ctx *ctx, const char *id, double val) return ret; } +int expr__add_ref(struct expr_parse_ctx *ctx, struct metric_ref *ref) +{ + struct expr_id_data *data_ptr = NULL, *old_data = NULL; + char *old_key = NULL; + char *name, *p; + int ret; + + data_ptr = zalloc(sizeof(*data_ptr)); + if (!data_ptr) + return -ENOMEM; + + name = strdup(ref->metric_name); + if (!name) { + free(data_ptr); + return -ENOMEM; + } + + /* +* The jevents tool converts all metric expressions +* to lowercase, including metric references, hence +* we need to add lowercase name for metric, so it's +* properly found. +*/ + for (p = name; *p; p++) + *p = tolower(*p); + + /* +* Intentionally passing just const char pointers, +* originally from 'struct pmu_event' object. +* We don't need to change them, so there's no +* need to create our own copy. +*/ + data_ptr->ref.metric_name = ref->metric_name; + data_ptr->ref.metric_expr = ref->metric_expr; + data_ptr->is_ref = true; + + ret = hashmap__set(>ids, name, data_ptr, + (const void **)_key, (void **)_data); + if (ret) + free(data_ptr); + + pr_debug2("adding ref metric %s: %s\n", + ref->metric_name, ref->metric_expr); + + free(old_key); + free(old_data); + return ret; +} + int expr__get_id(struct expr_parse_ctx *ctx, const char *id, struct expr_id_data **data) { diff --git a/tools/perf/util/expr.h b/tools/perf/util/expr.h index 2462abd0ac65..81d04ff7f857 100644 --- a/tools/perf/util/expr.h +++ b/tools/perf/util/expr.h @@ -11,12 +11,22 @@ #include "util/hashmap.h" //#endif +struct metric_ref; + struct expr_parse_ctx { struct hashmap ids; }; struct expr_id_data { - double val; + union { + double val; + struct { + const char *metric_name; + const char *metric_expr; + } ref; + }; + + bool is_ref; }; struct expr_scanner_ctx { @@ -29,6 +39,7 @@ void expr__ctx_clear(struct expr_parse_ctx *ctx); void expr__del_id(struct expr_parse_ctx *ctx, const char *id); int expr__add_id(struct expr_parse_ctx *ctx, const char *id); int expr__add_id_val(struct expr_parse_ctx *ctx, const char *id, double val); +int expr__add_ref(struct expr_parse_ctx *ctx, struct metric_ref *ref); int expr__get_id(struct expr_parse_ctx *ctx, const char *id, struct expr_id_data **data); int expr__parse(double *final_val, struct expr_parse_ctx *ctx, diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c index fc9ac4b4218e..e1ba6c1b916a 100644 --- a/tools/perf/util/stat-shadow.c +++ b/tools/perf/util/stat-shadow.c @@ -731,13 +731,14 @@ static void print_smi_cost(struct perf_stat_config *config, } static int prepare_metric(struct evsel **metric_events, + struct metric_ref *metric_refs, struct expr_parse_ctx *pctx, int cpu, struct runtime_stat *st) { double scale; char *n, *pn; - int i; + int i, j, ret; expr__ctx_init(pctx); for (i = 0; metric_events[i]; i++) { @@
Re: [PATCH 10/19] perf metric: Add referenced metrics to hash data
Em Sun, Jul 19, 2020 at 03:32:26PM -0700, Ian Rogers escreveu: > On Sun, Jul 19, 2020 at 11:14 AM Jiri Olsa wrote: > > > > Adding referenced metrics to the parsing context so they > > can be resolved during the metric processing. > > > > Adding expr__add_ref function to store referenced metrics > > into parse context. > > > > Signed-off-by: Jiri Olsa > > Acked-by: Ian Rogers Thanks, applied. - Arnaldo > Thanks, > Ian > > > --- > > tools/perf/util/expr.c| 54 +++ > > tools/perf/util/expr.h| 13 - > > tools/perf/util/stat-shadow.c | 20 + > > 3 files changed, 80 insertions(+), 7 deletions(-) > > > > diff --git a/tools/perf/util/expr.c b/tools/perf/util/expr.c > > index f726211f49d4..d3997c2b4a90 100644 > > --- a/tools/perf/util/expr.c > > +++ b/tools/perf/util/expr.c > > @@ -4,10 +4,14 @@ > > #include > > #include > > #include > > +#include "metricgroup.h" > > +#include "debug.h" > > #include "expr.h" > > #include "expr-bison.h" > > #include "expr-flex.h" > > #include > > +#include > > +#include > > > > #ifdef PARSER_DEBUG > > extern int expr_debug; > > @@ -63,6 +67,7 @@ int expr__add_id_val(struct expr_parse_ctx *ctx, const > > char *id, double val) > > if (!data_ptr) > > return -ENOMEM; > > data_ptr->val = val; > > + data_ptr->is_ref = false; > > > > ret = hashmap__set(>ids, id, data_ptr, > >(const void **)_key, (void **)_data); > > @@ -73,6 +78,55 @@ int expr__add_id_val(struct expr_parse_ctx *ctx, const > > char *id, double val) > > return ret; > > } > > > > +int expr__add_ref(struct expr_parse_ctx *ctx, struct metric_ref *ref) > > +{ > > + struct expr_id_data *data_ptr = NULL, *old_data = NULL; > > + char *old_key = NULL; > > + char *name, *p; > > + int ret; > > + > > + data_ptr = zalloc(sizeof(*data_ptr)); > > + if (!data_ptr) > > + return -ENOMEM; > > + > > + name = strdup(ref->metric_name); > > + if (!name) { > > + free(data_ptr); > > + return -ENOMEM; > > + } > > + > > + /* > > +* The jevents tool converts all metric expressions > > +* to lowercase, including metric references, hence > > +* we need to add lowercase name for metric, so it's > > +* properly found. > > +*/ > > + for (p = name; *p; p++) > > + *p = tolower(*p); > > + > > + /* > > +* Intentionally passing just const char pointers, > > +* originally from 'struct pmu_event' object. > > +* We don't need to change them, so there's no > > +* need to create our own copy. > > +*/ > > + data_ptr->ref.metric_name = ref->metric_name; > > + data_ptr->ref.metric_expr = ref->metric_expr; > > + data_ptr->is_ref = true; > > + > > + ret = hashmap__set(>ids, name, data_ptr, > > + (const void **)_key, (void **)_data); > > + if (ret) > > + free(data_ptr); > > + > > + pr_debug2("adding ref metric %s: %s\n", > > + ref->metric_name, ref->metric_expr); > > + > > + free(old_key); > > + free(old_data); > > + return ret; > > +} > > + > > int expr__get_id(struct expr_parse_ctx *ctx, const char *id, > > struct expr_id_data **data) > > { > > diff --git a/tools/perf/util/expr.h b/tools/perf/util/expr.h > > index 2462abd0ac65..81d04ff7f857 100644 > > --- a/tools/perf/util/expr.h > > +++ b/tools/perf/util/expr.h > > @@ -11,12 +11,22 @@ > > #include "util/hashmap.h" > > //#endif > > > > +struct metric_ref; > > + > > struct expr_parse_ctx { > > struct hashmap ids; > > }; > > > > struct expr_id_data { > > - double val; > > + union { > > + double val; > > + struct { > > + const char *metric_name; > > + const char *metric_expr; > > + } ref; > > + }; > > + > > + bool is_ref; > > }; > > > > struct expr_scanner_ctx { > > @@ -29,6 +39,7 @@ void expr__ctx_clear(struct expr_parse_ctx *ctx); > > void expr__del_id(struct expr_parse_ctx *ctx, const char *id); > > int expr__add_id(struct expr_parse_ctx *ctx, const char *id); > > int expr__add_id_val(struct expr_parse_ctx *ctx, const char *id, double > > val); > > +int expr__add_ref(struct expr_parse_ctx *ctx, struct metric_ref *ref); > > int expr__get_id(struct expr_parse_ctx *ctx, const char *id, > > struct expr_id_data **data); > > int expr__parse(double *final_val, struct expr_parse_ctx *ctx, > > diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c > > index fc9ac4b4218e..e1ba6c1b916a 100644 > > --- a/tools/perf/util/stat-shadow.c > > +++ b/tools/perf/util/stat-shadow.c > > @@ -731,13 +731,14 @@ static void print_smi_cost(struct perf_stat_config > > *config,
Re: [PATCH 10/19] perf metric: Add referenced metrics to hash data
On 7/20/20 4:02 AM, Ian Rogers wrote: > On Sun, Jul 19, 2020 at 11:14 AM Jiri Olsa wrote: >> >> Adding referenced metrics to the parsing context so they >> can be resolved during the metric processing. >> >> Adding expr__add_ref function to store referenced metrics >> into parse context. >> >> Signed-off-by: Jiri Olsa > > Acked-by: Ian Rogers Reviewed-By : Kajol Jain Thanks, Kajol Jain > > Thanks, > Ian > >> --- >> tools/perf/util/expr.c| 54 +++ >> tools/perf/util/expr.h| 13 - >> tools/perf/util/stat-shadow.c | 20 + >> 3 files changed, 80 insertions(+), 7 deletions(-) >> >> diff --git a/tools/perf/util/expr.c b/tools/perf/util/expr.c >> index f726211f49d4..d3997c2b4a90 100644 >> --- a/tools/perf/util/expr.c >> +++ b/tools/perf/util/expr.c >> @@ -4,10 +4,14 @@ >> #include >> #include >> #include >> +#include "metricgroup.h" >> +#include "debug.h" >> #include "expr.h" >> #include "expr-bison.h" >> #include "expr-flex.h" >> #include >> +#include >> +#include >> >> #ifdef PARSER_DEBUG >> extern int expr_debug; >> @@ -63,6 +67,7 @@ int expr__add_id_val(struct expr_parse_ctx *ctx, const >> char *id, double val) >> if (!data_ptr) >> return -ENOMEM; >> data_ptr->val = val; >> + data_ptr->is_ref = false; >> >> ret = hashmap__set(>ids, id, data_ptr, >>(const void **)_key, (void **)_data); >> @@ -73,6 +78,55 @@ int expr__add_id_val(struct expr_parse_ctx *ctx, const >> char *id, double val) >> return ret; >> } >> >> +int expr__add_ref(struct expr_parse_ctx *ctx, struct metric_ref *ref) >> +{ >> + struct expr_id_data *data_ptr = NULL, *old_data = NULL; >> + char *old_key = NULL; >> + char *name, *p; >> + int ret; >> + >> + data_ptr = zalloc(sizeof(*data_ptr)); >> + if (!data_ptr) >> + return -ENOMEM; >> + >> + name = strdup(ref->metric_name); >> + if (!name) { >> + free(data_ptr); >> + return -ENOMEM; >> + } >> + >> + /* >> +* The jevents tool converts all metric expressions >> +* to lowercase, including metric references, hence >> +* we need to add lowercase name for metric, so it's >> +* properly found. >> +*/ >> + for (p = name; *p; p++) >> + *p = tolower(*p); >> + >> + /* >> +* Intentionally passing just const char pointers, >> +* originally from 'struct pmu_event' object. >> +* We don't need to change them, so there's no >> +* need to create our own copy. >> +*/ >> + data_ptr->ref.metric_name = ref->metric_name; >> + data_ptr->ref.metric_expr = ref->metric_expr; >> + data_ptr->is_ref = true; >> + >> + ret = hashmap__set(>ids, name, data_ptr, >> + (const void **)_key, (void **)_data); >> + if (ret) >> + free(data_ptr); >> + >> + pr_debug2("adding ref metric %s: %s\n", >> + ref->metric_name, ref->metric_expr); >> + >> + free(old_key); >> + free(old_data); >> + return ret; >> +} >> + >> int expr__get_id(struct expr_parse_ctx *ctx, const char *id, >> struct expr_id_data **data) >> { >> diff --git a/tools/perf/util/expr.h b/tools/perf/util/expr.h >> index 2462abd0ac65..81d04ff7f857 100644 >> --- a/tools/perf/util/expr.h >> +++ b/tools/perf/util/expr.h >> @@ -11,12 +11,22 @@ >> #include "util/hashmap.h" >> //#endif >> >> +struct metric_ref; >> + >> struct expr_parse_ctx { >> struct hashmap ids; >> }; >> >> struct expr_id_data { >> - double val; >> + union { >> + double val; >> + struct { >> + const char *metric_name; >> + const char *metric_expr; >> + } ref; >> + }; >> + >> + bool is_ref; >> }; >> >> struct expr_scanner_ctx { >> @@ -29,6 +39,7 @@ void expr__ctx_clear(struct expr_parse_ctx *ctx); >> void expr__del_id(struct expr_parse_ctx *ctx, const char *id); >> int expr__add_id(struct expr_parse_ctx *ctx, const char *id); >> int expr__add_id_val(struct expr_parse_ctx *ctx, const char *id, double >> val); >> +int expr__add_ref(struct expr_parse_ctx *ctx, struct metric_ref *ref); >> int expr__get_id(struct expr_parse_ctx *ctx, const char *id, >> struct expr_id_data **data); >> int expr__parse(double *final_val, struct expr_parse_ctx *ctx, >> diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c >> index fc9ac4b4218e..e1ba6c1b916a 100644 >> --- a/tools/perf/util/stat-shadow.c >> +++ b/tools/perf/util/stat-shadow.c >> @@ -731,13 +731,14 @@ static void print_smi_cost(struct perf_stat_config >> *config, >> } >> >> static int prepare_metric(struct evsel **metric_events, >> + struct metric_ref *metric_refs, >>
Re: [PATCH 10/19] perf metric: Add referenced metrics to hash data
On Sun, Jul 19, 2020 at 11:14 AM Jiri Olsa wrote: > > Adding referenced metrics to the parsing context so they > can be resolved during the metric processing. > > Adding expr__add_ref function to store referenced metrics > into parse context. > > Signed-off-by: Jiri Olsa Acked-by: Ian Rogers Thanks, Ian > --- > tools/perf/util/expr.c| 54 +++ > tools/perf/util/expr.h| 13 - > tools/perf/util/stat-shadow.c | 20 + > 3 files changed, 80 insertions(+), 7 deletions(-) > > diff --git a/tools/perf/util/expr.c b/tools/perf/util/expr.c > index f726211f49d4..d3997c2b4a90 100644 > --- a/tools/perf/util/expr.c > +++ b/tools/perf/util/expr.c > @@ -4,10 +4,14 @@ > #include > #include > #include > +#include "metricgroup.h" > +#include "debug.h" > #include "expr.h" > #include "expr-bison.h" > #include "expr-flex.h" > #include > +#include > +#include > > #ifdef PARSER_DEBUG > extern int expr_debug; > @@ -63,6 +67,7 @@ int expr__add_id_val(struct expr_parse_ctx *ctx, const char > *id, double val) > if (!data_ptr) > return -ENOMEM; > data_ptr->val = val; > + data_ptr->is_ref = false; > > ret = hashmap__set(>ids, id, data_ptr, >(const void **)_key, (void **)_data); > @@ -73,6 +78,55 @@ int expr__add_id_val(struct expr_parse_ctx *ctx, const > char *id, double val) > return ret; > } > > +int expr__add_ref(struct expr_parse_ctx *ctx, struct metric_ref *ref) > +{ > + struct expr_id_data *data_ptr = NULL, *old_data = NULL; > + char *old_key = NULL; > + char *name, *p; > + int ret; > + > + data_ptr = zalloc(sizeof(*data_ptr)); > + if (!data_ptr) > + return -ENOMEM; > + > + name = strdup(ref->metric_name); > + if (!name) { > + free(data_ptr); > + return -ENOMEM; > + } > + > + /* > +* The jevents tool converts all metric expressions > +* to lowercase, including metric references, hence > +* we need to add lowercase name for metric, so it's > +* properly found. > +*/ > + for (p = name; *p; p++) > + *p = tolower(*p); > + > + /* > +* Intentionally passing just const char pointers, > +* originally from 'struct pmu_event' object. > +* We don't need to change them, so there's no > +* need to create our own copy. > +*/ > + data_ptr->ref.metric_name = ref->metric_name; > + data_ptr->ref.metric_expr = ref->metric_expr; > + data_ptr->is_ref = true; > + > + ret = hashmap__set(>ids, name, data_ptr, > + (const void **)_key, (void **)_data); > + if (ret) > + free(data_ptr); > + > + pr_debug2("adding ref metric %s: %s\n", > + ref->metric_name, ref->metric_expr); > + > + free(old_key); > + free(old_data); > + return ret; > +} > + > int expr__get_id(struct expr_parse_ctx *ctx, const char *id, > struct expr_id_data **data) > { > diff --git a/tools/perf/util/expr.h b/tools/perf/util/expr.h > index 2462abd0ac65..81d04ff7f857 100644 > --- a/tools/perf/util/expr.h > +++ b/tools/perf/util/expr.h > @@ -11,12 +11,22 @@ > #include "util/hashmap.h" > //#endif > > +struct metric_ref; > + > struct expr_parse_ctx { > struct hashmap ids; > }; > > struct expr_id_data { > - double val; > + union { > + double val; > + struct { > + const char *metric_name; > + const char *metric_expr; > + } ref; > + }; > + > + bool is_ref; > }; > > struct expr_scanner_ctx { > @@ -29,6 +39,7 @@ void expr__ctx_clear(struct expr_parse_ctx *ctx); > void expr__del_id(struct expr_parse_ctx *ctx, const char *id); > int expr__add_id(struct expr_parse_ctx *ctx, const char *id); > int expr__add_id_val(struct expr_parse_ctx *ctx, const char *id, double val); > +int expr__add_ref(struct expr_parse_ctx *ctx, struct metric_ref *ref); > int expr__get_id(struct expr_parse_ctx *ctx, const char *id, > struct expr_id_data **data); > int expr__parse(double *final_val, struct expr_parse_ctx *ctx, > diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c > index fc9ac4b4218e..e1ba6c1b916a 100644 > --- a/tools/perf/util/stat-shadow.c > +++ b/tools/perf/util/stat-shadow.c > @@ -731,13 +731,14 @@ static void print_smi_cost(struct perf_stat_config > *config, > } > > static int prepare_metric(struct evsel **metric_events, > + struct metric_ref *metric_refs, > struct expr_parse_ctx *pctx, > int cpu, > struct runtime_stat *st) > { > double scale; > char *n, *pn; > - int i; > + int i, j, ret; > >
[PATCH 10/19] perf metric: Add referenced metrics to hash data
Adding referenced metrics to the parsing context so they can be resolved during the metric processing. Adding expr__add_ref function to store referenced metrics into parse context. Signed-off-by: Jiri Olsa --- tools/perf/util/expr.c| 54 +++ tools/perf/util/expr.h| 13 - tools/perf/util/stat-shadow.c | 20 + 3 files changed, 80 insertions(+), 7 deletions(-) diff --git a/tools/perf/util/expr.c b/tools/perf/util/expr.c index f726211f49d4..d3997c2b4a90 100644 --- a/tools/perf/util/expr.c +++ b/tools/perf/util/expr.c @@ -4,10 +4,14 @@ #include #include #include +#include "metricgroup.h" +#include "debug.h" #include "expr.h" #include "expr-bison.h" #include "expr-flex.h" #include +#include +#include #ifdef PARSER_DEBUG extern int expr_debug; @@ -63,6 +67,7 @@ int expr__add_id_val(struct expr_parse_ctx *ctx, const char *id, double val) if (!data_ptr) return -ENOMEM; data_ptr->val = val; + data_ptr->is_ref = false; ret = hashmap__set(>ids, id, data_ptr, (const void **)_key, (void **)_data); @@ -73,6 +78,55 @@ int expr__add_id_val(struct expr_parse_ctx *ctx, const char *id, double val) return ret; } +int expr__add_ref(struct expr_parse_ctx *ctx, struct metric_ref *ref) +{ + struct expr_id_data *data_ptr = NULL, *old_data = NULL; + char *old_key = NULL; + char *name, *p; + int ret; + + data_ptr = zalloc(sizeof(*data_ptr)); + if (!data_ptr) + return -ENOMEM; + + name = strdup(ref->metric_name); + if (!name) { + free(data_ptr); + return -ENOMEM; + } + + /* +* The jevents tool converts all metric expressions +* to lowercase, including metric references, hence +* we need to add lowercase name for metric, so it's +* properly found. +*/ + for (p = name; *p; p++) + *p = tolower(*p); + + /* +* Intentionally passing just const char pointers, +* originally from 'struct pmu_event' object. +* We don't need to change them, so there's no +* need to create our own copy. +*/ + data_ptr->ref.metric_name = ref->metric_name; + data_ptr->ref.metric_expr = ref->metric_expr; + data_ptr->is_ref = true; + + ret = hashmap__set(>ids, name, data_ptr, + (const void **)_key, (void **)_data); + if (ret) + free(data_ptr); + + pr_debug2("adding ref metric %s: %s\n", + ref->metric_name, ref->metric_expr); + + free(old_key); + free(old_data); + return ret; +} + int expr__get_id(struct expr_parse_ctx *ctx, const char *id, struct expr_id_data **data) { diff --git a/tools/perf/util/expr.h b/tools/perf/util/expr.h index 2462abd0ac65..81d04ff7f857 100644 --- a/tools/perf/util/expr.h +++ b/tools/perf/util/expr.h @@ -11,12 +11,22 @@ #include "util/hashmap.h" //#endif +struct metric_ref; + struct expr_parse_ctx { struct hashmap ids; }; struct expr_id_data { - double val; + union { + double val; + struct { + const char *metric_name; + const char *metric_expr; + } ref; + }; + + bool is_ref; }; struct expr_scanner_ctx { @@ -29,6 +39,7 @@ void expr__ctx_clear(struct expr_parse_ctx *ctx); void expr__del_id(struct expr_parse_ctx *ctx, const char *id); int expr__add_id(struct expr_parse_ctx *ctx, const char *id); int expr__add_id_val(struct expr_parse_ctx *ctx, const char *id, double val); +int expr__add_ref(struct expr_parse_ctx *ctx, struct metric_ref *ref); int expr__get_id(struct expr_parse_ctx *ctx, const char *id, struct expr_id_data **data); int expr__parse(double *final_val, struct expr_parse_ctx *ctx, diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c index fc9ac4b4218e..e1ba6c1b916a 100644 --- a/tools/perf/util/stat-shadow.c +++ b/tools/perf/util/stat-shadow.c @@ -731,13 +731,14 @@ static void print_smi_cost(struct perf_stat_config *config, } static int prepare_metric(struct evsel **metric_events, + struct metric_ref *metric_refs, struct expr_parse_ctx *pctx, int cpu, struct runtime_stat *st) { double scale; char *n, *pn; - int i; + int i, j, ret; expr__ctx_init(pctx); for (i = 0; metric_events[i]; i++) { @@ -778,12 +779,19 @@ static int prepare_metric(struct evsel **metric_events, expr__add_id_val(pctx, n, avg_stats(stats)*scale); } + for (j = 0; metric_refs && metric_refs[j].metric_name; j++) { + ret = expr__add_ref(pctx, _refs[j]); + if (ret) +