[DTrace-devel] [PATCH 08/12] cg: integrate dvar lookup into dt_cg_prep_dvar()
Eugene Loh
eugene.loh at oracle.com
Mon Jan 8 22:02:28 UTC 2024
Reviewed-by: Eugene Loh <eugene.loh at oracle.com>
comments below...
On 1/5/24 00:29, Kris Van Hees via DTrace-devel wrote:
> The loading and storing of dynamic variables was implemented using a
> function dt_cg_prep_dvar_args() to prepare the arguments for a function
> call, followed by performing the actual function call in the respective
> callers. Those calls are identical, so it makes sense to consolidate
> argument setup and call into a single function.
>
> Signed-off-by: Kris Van Hees <kris.van.hees at oracle.com>
> ---
> libdtrace/dt_cg.c | 47 +++++++++++++++++++++++++++--------------------
> 1 file changed, 27 insertions(+), 20 deletions(-)
>
> diff --git a/libdtrace/dt_cg.c b/libdtrace/dt_cg.c
> index 615ebdbf..39a3b4e8 100644
> --- a/libdtrace/dt_cg.c
> +++ b/libdtrace/dt_cg.c
> @@ -2848,11 +2848,12 @@ dt_cg_arglist(dt_ident_t *idp, dt_node_t *args, dt_irlist_t *dlp,
> dt_regset_t *drp);
>
> static void
> -dt_cg_prep_dvar_args(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp,
> - dt_ident_t *idp, int isstore, dt_ident_t **fnpp)
> +dt_cg_prep_dvar(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp,
> + dt_ident_t *idp, int isstore)
> {
> uint_t varid = idp->di_id - DIF_VAR_OTHER_UBASE;
> const char *fn;
> + dt_ident_t *fnp;
>
> if (idp->di_kind == DT_IDENT_ARRAY) {
> /* Associative (global or TLS) array. Cannot be in alloca space. */
> @@ -2869,9 +2870,14 @@ dt_cg_prep_dvar_args(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp,
> emit(dlp, BPF_MOV_REG(BPF_REG_2, args->dn_args->dn_reg));
> dt_regset_free(drp, args->dn_args->dn_reg);
> emit(dlp, BPF_MOV_IMM(BPF_REG_3, isstore));
> - if (isstore)
> - emit(dlp, BPF_MOV_REG(BPF_REG_4, dnp->dn_reg));
> - else
> + if (isstore) {
> + dt_node_t *rp = dnp->dn_right;
> +
> + if (rp->dn_kind == DT_NODE_INT && rp->dn_value == 0)
> + emit(dlp, BPF_MOV_IMM(BPF_REG_4, 0));
> + else
> + emit(dlp, BPF_MOV_REG(BPF_REG_4, dnp->dn_reg));
> + } else
What's the point of specializing the =0 case? Explain in the commit
message? It's still a BPF instruction, so it isn't an optimization.
Won't the old code just work here? It's a bit more complexity and I do
not see what it buys us.
Same for TLS...
> emit(dlp, BPF_MOV_IMM(BPF_REG_4, 0));
> dt_cg_zerosptr(BPF_REG_5, dlp, drp);
> } else if (idp->di_flags & DT_IDFLG_TLS) {
> @@ -2883,16 +2889,26 @@ dt_cg_prep_dvar_args(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp,
>
> emit(dlp, BPF_MOV_IMM(BPF_REG_1, varid));
> emit(dlp, BPF_MOV_IMM(BPF_REG_2, isstore));
> - if (isstore)
> + if (isstore) {
> emit(dlp, BPF_MOV_REG(BPF_REG_3, dnp->dn_reg));
No need to assign %r3 since you're about to assign (overwrite) it
anyhow. (Or, just leave it if the funny "if =0" code is removed per my
earlier comment.)
> - else
> + dt_node_t *rp = dnp->dn_right;
> +
> + if (rp->dn_kind == DT_NODE_INT && rp->dn_value == 0)
> + emit(dlp, BPF_MOV_IMM(BPF_REG_3, 0));
> + else
> + emit(dlp, BPF_MOV_REG(BPF_REG_3, dnp->dn_reg));
> + } else
> emit(dlp, BPF_MOV_IMM(BPF_REG_3, 0));
> dt_cg_zerosptr(BPF_REG_4, dlp, drp);
> } else
> assert(0);
>
> - *fnpp = dt_dlib_get_func(yypcb->pcb_hdl, fn);
> - assert(*fnpp);
> + fnp = dt_dlib_get_func(yypcb->pcb_hdl, fn);
> + assert(fnp);
> +
> + dt_regset_xalloc(drp, BPF_REG_0);
> + emite(dlp, BPF_CALL_FUNC(fnp->di_id), fnp);
> + dt_regset_free_args(drp);
> }
>
> static void
> @@ -2905,11 +2921,7 @@ dt_cg_load_var(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
>
> /* First handle dvars. */
> if (idp->di_kind == DT_IDENT_ARRAY || idp->di_flags & DT_IDFLG_TLS) {
> - dt_cg_prep_dvar_args(dnp, dlp, drp, idp, 0, &fnp);
> -
> - dt_regset_xalloc(drp, BPF_REG_0);
> - emite(dlp, BPF_CALL_FUNC(fnp->di_id), fnp);
> - dt_regset_free_args(drp);
> + dt_cg_prep_dvar(dnp, dlp, drp, idp, 0);
>
> if ((dnp->dn_reg = dt_regset_alloc(drp)) == -1)
> longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
> @@ -3606,7 +3618,6 @@ dt_cg_store_var(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp,
> {
> int reg;
> size_t size;
> - dt_ident_t *fnp;
>
> idp->di_flags |= DT_IDFLG_DIFW;
>
> @@ -3631,11 +3642,7 @@ dt_cg_store_var(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp,
> uint_t lbl_notnull = dt_irlist_label(dlp);
> dt_node_t *rp = dnp->dn_right;
>
> - dt_cg_prep_dvar_args(dnp, dlp, drp, idp, 1, &fnp);
> -
> - dt_regset_xalloc(drp, BPF_REG_0);
> - emite(dlp, BPF_CALL_FUNC(fnp->di_id), fnp);
> - dt_regset_free_args(drp);
> + dt_cg_prep_dvar(dnp, dlp, drp, idp, 1);
>
> /*
> * Special case: a store of a literal 0 causes the dynamic
The comment block getting chopped off here in the diff is:
/*
* Special case: a store of a literal 0 causes the dynamic
* variable to be deleted by the BPF function called
above, so
* nothing is left to be done.
*/
The "BPF function called above" was already a little opaque (what is
fnp->di_id?), and with this patch the call disappears entirely, at least
from any obvious presence in the immediately preceding code. Maybe
replace "the BPF function called above" with "dt_cg_prep_dvar()".
More information about the DTrace-devel
mailing list