Skip to content

Commit

Permalink
Consolidate tvar/assoc pointer access
Browse files Browse the repository at this point in the history
To load or store a thread-local variable or associative array
element, one must generate a dynamic pointer and then access the
pointer.  Currently, there are four code paths (load or store,
tvar or assoc).  However, generating the dynamic pointer depends
only on whether it's a tvar or assoc, not on whether we will load
or store.  Further, accessing the pointer depends only on whether
we load or store, not on whether the pointer represents a tvar or
assoc.  So, there is an opportunity to consolidate code.

In this patch, consolidate the pointer-access code.  In the next
patch, we will consolidate the pointer generation.

Signed-off-by: Eugene Loh <eugene.loh@oracle.com>
Reviewed-by: Nick Alcock <nick.alcock@oracle.com>
Reviewed-by: Kris Van Hees <kris.van.hees@oracle.com>
  • Loading branch information
euloh authored and kvanhees committed May 25, 2023
1 parent 04c525f commit cda7b5b
Showing 1 changed file with 40 additions and 104 deletions.
144 changes: 40 additions & 104 deletions libdtrace/dt_cg.c
Original file line number Diff line number Diff line change
Expand Up @@ -2626,90 +2626,63 @@ dt_cg_load_var(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
{
dt_ident_t *idp = dt_ident_resolve(dnp->dn_ident);
dt_ident_t *fnp;
int args_are_ready = 0;

idp->di_flags |= DT_IDFLG_DIFR;

if (dnp->dn_ident->di_kind == DT_IDENT_ARRAY) {
uint_t varid;
/* associative arrays */
uint_t varid = idp->di_id - DIF_VAR_OTHER_UBASE;

fnp = dt_dlib_get_func(yypcb->pcb_hdl, "dt_get_assoc");
TRACE_REGSET(" assoc_op: Begin");

assert(fnp != NULL);
assert(dnp->dn_kind == DT_NODE_VAR);
assert(!(dnp->dn_ident->di_flags & DT_IDFLG_LOCAL));
assert(dnp->dn_args != NULL);

/* Get the tuple. */
dt_cg_arglist(dnp->dn_ident, dnp->dn_args, dlp, drp);

if ((dnp->dn_reg = dt_regset_alloc(drp)) == -1)
longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
if (dt_regset_xalloc_args(drp) == -1)
longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);

varid = dnp->dn_ident->di_id - DIF_VAR_OTHER_UBASE;

emit(dlp, BPF_MOV_IMM(BPF_REG_1, varid));
emit(dlp, BPF_MOV_REG(BPF_REG_2, dnp->dn_args->dn_reg));
dt_regset_free(drp, dnp->dn_args->dn_reg);
emit(dlp, BPF_MOV_IMM(BPF_REG_3, 0));
emit(dlp, BPF_MOV_IMM(BPF_REG_4, 0));
dt_cg_zerosptr(BPF_REG_5, dlp, drp);
dt_regset_xalloc(drp, BPF_REG_0);
emite(dlp, BPF_CALL_FUNC(fnp->di_id), fnp);
dt_regset_free_args(drp);

if (dnp->dn_flags & DT_NF_REF) {
emit(dlp, BPF_MOV_REG(dnp->dn_reg, BPF_REG_0));
} else {
size_t size = dt_node_type_size(dnp);
uint_t lbl_notnull = dt_irlist_label(dlp);
uint_t lbl_done = dt_irlist_label(dlp);

assert(size > 0 && size <= 8 &&
(size & (size - 1)) == 0);

emit(dlp, BPF_BRANCH_IMM(BPF_JNE, BPF_REG_0, 0, lbl_notnull));
emit(dlp, BPF_MOV_IMM(dnp->dn_reg, 0));
emit(dlp, BPF_JUMP(lbl_done));
emitl(dlp, lbl_notnull,
BPF_LOAD(ldstw[size], dnp->dn_reg, BPF_REG_0, 0));
dt_cg_promote(dnp, size, dlp, drp);
emitl(dlp, lbl_done,
BPF_NOP());
}

dt_regset_free(drp, BPF_REG_0);

TRACE_REGSET(" assoc_op: End ");

return;
}

/* thread-local variables */
if (idp->di_flags & DT_IDFLG_TLS) { /* TLS var */
args_are_ready = 1;
} else if (idp->di_flags & DT_IDFLG_TLS) {
/* thread-local variables */
uint_t varid = idp->di_id - DIF_VAR_OTHER_UBASE;

fnp = dt_dlib_get_func(yypcb->pcb_hdl, "dt_get_tvar");
assert(fnp != NULL);

if ((dnp->dn_reg = dt_regset_alloc(drp)) == -1)
longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
if (dt_regset_xalloc_args(drp) == -1)
longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);

emit(dlp, BPF_MOV_IMM(BPF_REG_1, varid));
emit(dlp, BPF_MOV_IMM(BPF_REG_2, 0));
emit(dlp, BPF_MOV_IMM(BPF_REG_3, 0));
dt_cg_zerosptr(BPF_REG_4, dlp, drp);

args_are_ready = 1;
}

if (args_are_ready) {
assert(fnp != NULL);

dt_regset_xalloc(drp, BPF_REG_0);
emite(dlp, BPF_CALL_FUNC(fnp->di_id), fnp);
dt_regset_free_args(drp);

if ((dnp->dn_reg = dt_regset_alloc(drp)) == -1)
longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);

if (dnp->dn_flags & DT_NF_REF) {
emit(dlp, BPF_MOV_REG(dnp->dn_reg, BPF_REG_0));
dt_regset_free(drp, BPF_REG_0);
} else {
size_t size = dt_node_type_size(dnp);
uint_t lbl_notnull = dt_irlist_label(dlp);
Expand All @@ -2724,12 +2697,13 @@ dt_cg_load_var(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
emitl(dlp, lbl_notnull,
BPF_LOAD(ldstw[size], dnp->dn_reg, BPF_REG_0, 0));
dt_cg_promote(dnp, size, dlp, drp);
dt_regset_free(drp, BPF_REG_0);

emitl(dlp, lbl_done,
BPF_NOP());
}

dt_regset_free(drp, BPF_REG_0);

return;
}

Expand Down Expand Up @@ -3299,7 +3273,7 @@ dt_cg_store_var(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp,
dt_ident_t *idp)
{
uint_t varid, lbl_done;
int reg;
int reg, args_are_ready = 0;
size_t size;
dt_ident_t *fnp;

Expand All @@ -3320,16 +3294,12 @@ dt_cg_store_var(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp,
idp->di_name);
}

/* Associative (global or TLS) array. Cannot be in alloca space. */
if (idp->di_kind == DT_IDENT_ARRAY) {
uint_t lbl_notnull = dt_irlist_label(dlp);

dt_cg_arglist(idp, dnp->dn_left->dn_args, dlp, drp);

/* Associative (global or TLS) array. Cannot be in alloca space. */
varid = idp->di_id - DIF_VAR_OTHER_UBASE;
size = idp->di_size;
fnp = dt_dlib_get_func(yypcb->pcb_hdl, "dt_get_assoc");
assert(fnp != NULL);

dt_cg_arglist(idp, dnp->dn_left->dn_args, dlp, drp);

if (dt_regset_xalloc_args(drp) == -1)
longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
Expand All @@ -3340,58 +3310,12 @@ dt_cg_store_var(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp,
emit(dlp, BPF_MOV_IMM(BPF_REG_3, 1));
emit(dlp, BPF_MOV_REG(BPF_REG_4, dnp->dn_reg));
dt_cg_zerosptr(BPF_REG_5, dlp, drp);
dt_regset_xalloc(drp, BPF_REG_0);
emite(dlp, BPF_CALL_FUNC(fnp->di_id), fnp);
dt_regset_free_args(drp);
lbl_done = dt_irlist_label(dlp);
emit(dlp, BPF_BRANCH_IMM(BPF_JEQ, dnp->dn_reg, 0, lbl_done));
emit(dlp, BPF_BRANCH_IMM(BPF_JNE, BPF_REG_0, 0, lbl_notnull));
emit(dlp, BPF_MOV_IMM(BPF_REG_0, 0));
emit(dlp, BPF_RETURN());

if ((reg = dt_regset_alloc(drp)) == -1)
longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);

emitl(dlp, lbl_notnull,
BPF_MOV_REG(reg, BPF_REG_0));
dt_regset_free(drp, BPF_REG_0);

if (dnp->dn_flags & DT_NF_REF) {
size_t srcsz;

/*
* Determine the amount of data to be copied. It is
* the lesser of the size of the identifier and the
* size of the data being copied in.
*/
srcsz = dt_node_type_size(dnp->dn_right);
size = MIN(srcsz, size);

dt_cg_memcpy(dlp, drp, reg, dnp->dn_reg, size);
} else {
assert(size > 0 && size <= 8 &&
(size & (size - 1)) == 0);

emit(dlp, BPF_STORE(ldstw[size], reg, 0, dnp->dn_reg));
}

dt_regset_free(drp, reg);

emitl(dlp, lbl_done,
BPF_NOP());

TRACE_REGSET(" store_var: End ");

return;
}

if (idp->di_flags & DT_IDFLG_TLS) {
args_are_ready = 1;
} else if (idp->di_flags & DT_IDFLG_TLS) {
/* TLS var */
varid = idp->di_id - DIF_VAR_OTHER_UBASE;
size = idp->di_size;

fnp = dt_dlib_get_func(yypcb->pcb_hdl, "dt_get_tvar");
assert(fnp != NULL);

if (dt_regset_xalloc_args(drp) == -1)
longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
Expand All @@ -3400,22 +3324,34 @@ dt_cg_store_var(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp,
emit(dlp, BPF_MOV_IMM(BPF_REG_2, 1));
emit(dlp, BPF_MOV_REG(BPF_REG_3, dnp->dn_reg));
dt_cg_zerosptr(BPF_REG_4, dlp, drp);

args_are_ready = 1;
}

if (args_are_ready) {
uint_t lbl_notnull = dt_irlist_label(dlp);

assert(fnp != NULL);

dt_regset_xalloc(drp, BPF_REG_0);
emite(dlp, BPF_CALL_FUNC(fnp->di_id), fnp);
dt_regset_free_args(drp);
lbl_done = dt_irlist_label(dlp);
emit(dlp, BPF_BRANCH_IMM(BPF_JEQ, dnp->dn_reg, 0, lbl_done));
emit(dlp, BPF_BRANCH_IMM(BPF_JNE, BPF_REG_0, 0, lbl_notnull));
emit(dlp, BPF_MOV_IMM(BPF_REG_0, 0));
emit(dlp, BPF_RETURN());

if ((reg = dt_regset_alloc(drp)) == -1)
longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);

emit(dlp, BPF_MOV_REG(reg, BPF_REG_0));
emitl(dlp, lbl_notnull,
BPF_MOV_REG(reg, BPF_REG_0));
dt_regset_free(drp, BPF_REG_0);

dt_cg_check_notnull(dlp, drp, reg);

size = idp->di_size;
if (dnp->dn_flags & DT_NF_REF) {
size_t srcsz;
size_t srcsz;

/*
* Determine the amount of data to be copied. It is
Expand Down

0 comments on commit cda7b5b

Please sign in to comment.