[DTrace-devel] [PATCH 07/20] regset: add spill protection

Kris Van Hees kris.van.hees at oracle.com
Wed Jul 27 19:42:27 UTC 2022


I do not believe this is a good idea.  With the introduction of an actual
(D) stack pointer I have been working (slowly) on implementing "real" register
spilling by storing to the stack so that e.g. the same register could be
spilled multiple times, etc and also to enable us to explicitly spill a
register where needed.

On Wed, May 11, 2022 at 10:12:49PM +0100, Nick Alcock via DTrace-devel wrote:
> This simple mechanism allows callers to prevent specific registers from
> being spilled, perhaps while a live variable holding that reg number is
> in active use.
> 
> Signed-off-by: Nick Alcock <nick.alcock at oracle.com>
> ---
>  libdtrace/dt_regset.c | 29 ++++++++++++++++++++++++++---
>  libdtrace/dt_regset.h |  2 ++
>  2 files changed, 28 insertions(+), 3 deletions(-)
> 
> diff --git a/libdtrace/dt_regset.c b/libdtrace/dt_regset.c
> index 6028e389dc1f..37e6166c565f 100644
> --- a/libdtrace/dt_regset.c
> +++ b/libdtrace/dt_regset.c
> @@ -31,9 +31,12 @@ dt_regset_create(ulong_t size, dt_cg_spill_f stf, dt_cg_spill_f ldf)
>  	drp->dr_spill_load = ldf;
>  	drp->dr_active = malloc(BT_SIZEOFMAP(size));
>  	drp->dr_spilled = malloc(BT_SIZEOFMAP(size));
> -	if (drp->dr_active == NULL || drp->dr_spilled == NULL) {
> +	drp->dr_nonspillable = malloc(BT_SIZEOFMAP(size));
> +	if (drp->dr_active == NULL || drp->dr_spilled == NULL ||
> +	    drp->dr_nonspillable == NULL) {
>  		free(drp->dr_active);
>  		free(drp->dr_spilled);
> +		free(drp->dr_nonspillable);
>  		free(drp);
>  		return NULL;
>  	}
> @@ -47,6 +50,7 @@ dt_regset_destroy(dt_regset_t *drp)
>  {
>  	free(drp->dr_active);
>  	free(drp->dr_spilled);
> +	free(drp->dr_nonspillable);
>  	free(drp);
>  }
>  
> @@ -55,6 +59,7 @@ dt_regset_reset(dt_regset_t *drp)
>  {
>  	memset(drp->dr_active, 0, BT_SIZEOFMAP(drp->dr_size));
>  	memset(drp->dr_spilled, 0, BT_SIZEOFMAP(drp->dr_size));
> +	memset(drp->dr_nonspillable, 0, BT_SIZEOFMAP(drp->dr_size));
>  }
>  
>  int
> @@ -70,7 +75,8 @@ dt_regset_alloc(dt_regset_t *drp)
>  	}
>  
>  	for (reg = drp->dr_size - 1; reg > 0; reg--) {
> -		if (BT_TEST(drp->dr_spilled, reg) == 0) {
> +		if (BT_TEST(drp->dr_spilled, reg) == 0 &&
> +		    BT_TEST(drp->dr_nonspillable, reg) == 0) {
>  			drp->dr_spill_store(reg);
>  			BT_SET(drp->dr_spilled, reg);
>  			return reg;
> @@ -89,10 +95,11 @@ dt_regset_xalloc(dt_regset_t *drp, int reg)
>  	assert(reg >= 0 && reg < drp->dr_size);
>  	if (BT_TEST(drp->dr_active, reg) != 0) {
>  		if (BT_TEST(drp->dr_spilled, reg) != 0)
> -			return -1;	/* register in use (and spilled)*/
> +			return -1;	/* register in use (and spilled) */
>  
>  		drp->dr_spill_store(reg);
>  		BT_SET(drp->dr_spilled, reg);
> +		BT_CLEAR(drp->dr_nonspillable, reg);
>  	}
>  
>  	BT_SET(drp->dr_active, reg);
> @@ -109,12 +116,28 @@ dt_regset_free(dt_regset_t *drp, int reg)
>  	if (BT_TEST(drp->dr_spilled, reg) != 0) {
>  		drp->dr_spill_load(reg);
>  		BT_CLEAR(drp->dr_spilled, reg);
> +		BT_CLEAR(drp->dr_nonspillable, reg);
>  		return;
>  	}
>  
>  	BT_CLEAR(drp->dr_active, reg);
>  }
>  
> +/*
> + * Prevent the spill machinery from spilling a given reg (perhaps because of
> + * a live reference to this reg by number)
> + */
> +void
> +dt_regset_no_spill(dt_regset_t *drp, int reg, int nonspillable)
> +{
> +	if (nonspillable) {
> +		BT_SET(drp->dr_nonspillable, reg);
> +	} else {
> +		BT_CLEAR(drp->dr_nonspillable, reg);
> +	}
> +}
> +
> +
>  /*
>   * Allocate %r1 through %r5 for use as function call arguments in BPF.
>   */
> diff --git a/libdtrace/dt_regset.h b/libdtrace/dt_regset.h
> index 7ccb66d7d568..7e2756a11c45 100644
> --- a/libdtrace/dt_regset.h
> +++ b/libdtrace/dt_regset.h
> @@ -25,6 +25,7 @@ typedef struct dt_regset {
>  	dt_cg_spill_f	dr_spill_load;	/* register spill load function */
>  	ulong_t		*dr_active;	/* bitmap of active registers */
>  	ulong_t		*dr_spilled;	/* bitmap of spilled registers */
> +	ulong_t		*dr_nonspillable; /* bitmap of nonspillable registers */
>  } dt_regset_t;
>  
>  extern dt_regset_t *dt_regset_create(ulong_t, dt_cg_spill_f, dt_cg_spill_f);
> @@ -33,6 +34,7 @@ extern void dt_regset_reset(dt_regset_t *);
>  extern int dt_regset_alloc(dt_regset_t *);
>  extern int dt_regset_xalloc(dt_regset_t *, int);
>  extern void dt_regset_free(dt_regset_t *, int);
> +extern void dt_regset_no_spill(dt_regset_t *, int reg, int nonspillable);
>  extern int dt_regset_xalloc_args(dt_regset_t *);
>  extern void dt_regset_free_args(dt_regset_t *);
>  extern void dt_regset_dump(dt_regset_t *, const char *);
> -- 
> 2.36.1.263.g194b774378.dirty
> 
> 
> _______________________________________________
> DTrace-devel mailing list
> DTrace-devel at oss.oracle.com
> https://oss.oracle.com/mailman/listinfo/dtrace-devel



More information about the DTrace-devel mailing list