diff --git a/src/eval.c b/src/eval.c index 4c5949d40a7..78a21bf6657 100644 --- a/src/eval.c +++ b/src/eval.c @@ -3846,7 +3846,7 @@ do_one_unbind (union specbinding *this_binding, bool unwinding, this_binding->unwind.func (this_binding->unwind.arg); break; case SPECPDL_UNWIND_ARRAY: - xfree (this_binding->unwind_array.array); + SAFE_ALLOCA_XFREE (this_binding->unwind_array.array); break; case SPECPDL_UNWIND_PTR: this_binding->unwind_ptr.func (this_binding->unwind_ptr.arg); diff --git a/src/igc.c b/src/igc.c index f8cf1ab642f..0eb05e76bb8 100644 --- a/src/igc.c +++ b/src/igc.c @@ -5184,6 +5184,16 @@ igc_make_face_cache (void) return c; } +/* Allocate a Lisp_Object vector with N elements. + Currently only used by SAFE_ALLOCA_LISP. */ + +Lisp_Object * +igc_alloc_lisp_obj_vec (size_t n) +{ + Lisp_Object v = make_vector (n, Qnil); + return XVECTOR (v)->contents; +} + #ifndef USE_EPHEMERON_POOL static mps_addr_t weak_hash_find_dependent (mps_addr_t addr) diff --git a/src/igc.h b/src/igc.h index 0c4d6d69020..8f343f43a8a 100644 --- a/src/igc.h +++ b/src/igc.h @@ -57,6 +57,7 @@ void *igc_realloc_ambig (void *block, size_t size); #ifdef ENABLE_CHECKING void igc_check_freeable (void *p); #endif +Lisp_Object *igc_xalloc_lisp_objs_exact (size_t n, const char *label); void *igc_xalloc_raw_exact (size_t n, const char *label); void *igc_xpalloc_ambig (void *pa, ptrdiff_t *nitems, diff --git a/src/lisp.h b/src/lisp.h index 3a16a1a44dd..d6cf4a33af4 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -6120,12 +6120,6 @@ extern void *record_xmalloc (size_t) extern void *igc_record_xmalloc_ambig (size_t size, const char *label) ATTRIBUTE_ALLOC_SIZE ((1)) ATTRIBUTE_RETURNS_NONNULL; -extern void *igc_xnmalloc_ambig (ptrdiff_t nitems, - ptrdiff_t item_size, - const char *label); -extern Lisp_Object *igc_xalloc_lisp_objs_exact (size_t n, - const char *label); -extern void igc_xfree (void *p); #endif #define USE_SAFE_ALLOCA \ @@ -6158,32 +6152,18 @@ extern void igc_xfree (void *p); # define SAFE_ALLOCA(size) SAFE_ALLOCA_NOPRO (size) #endif -/* SAFE_NALLOCA_NOPRO sets BUF to a newly allocated array of MULTIPLIER - * NITEMS items, each of the same type as *BUF. MULTIPLIER must - positive. The code is tuned for MULTIPLIER being a constant. This - may never be used to hold references to objects that are relevant to - GC. */ +/* SAFE_NALLOCA sets BUF to a newly allocated array of MULTIPLIER * + NITEMS items, each of the same type as *BUF. MULTIPLIER must be + positive. The code is tuned for MULTIPLIER being a constant. */ -#define SAFE_NALLOCA_NOPRO(buf, multiplier, nitems) \ - do { \ - eassert (sa_avail >= 0); \ - if ((nitems) <= sa_avail / sizeof *(buf) / (multiplier)) \ - (buf) = AVAIL_ALLOCA (sizeof *(buf) * (multiplier) * (nitems)); \ - else \ - { \ - (buf) = xnmalloc (nitems, sizeof *(buf) * (multiplier)); \ - record_unwind_protect_ptr (xfree, buf); \ - } \ - } while (false) +# ifdef HAVE_MPS +/* Defined in igc.c. */ +void *igc_xnmalloc_ambig (ptrdiff_t nitems, ptrdiff_t item_size, + const char *label); +void igc_xfree (void *p); -#ifdef HAVE_MPS -/* SAFE_NALLOCA_AMBIG sets BUF to a newly allocated array of MULTIPLIER - * NITEMS items, each of the same type as *BUF. MULTIPLIER must be - positive. The code is tuned for MULTIPLIER being a constant. BUF - becomes an ambiguous root. */ -#define SAFE_NALLOCA_AMBIG(buf, multiplier, nitems) \ +#define SAFE_NALLOCA(buf, multiplier, nitems) \ do { \ - eassert (sa_avail >= 0); \ if ((nitems) <= sa_avail / sizeof *(buf) / (multiplier)) \ (buf) = AVAIL_ALLOCA (sizeof *(buf) * (multiplier) * (nitems)); \ else \ @@ -6194,12 +6174,20 @@ extern void igc_xfree (void *p); record_unwind_protect_ptr (igc_xfree, buf); \ } \ } while (false) -#endif -#ifdef HAVE_MPS -# define SAFE_NALLOCA(buf, m, n) SAFE_NALLOCA_AMBIG (buf, m, n) #else -# define SAFE_NALLOCA(buf, m, n) SAFE_NALLOCA_NOPRO (buf, m, n) + +#define SAFE_NALLOCA(buf, multiplier, nitems) \ + do { \ + if ((nitems) <= sa_avail / sizeof *(buf) / (multiplier)) \ + (buf) = AVAIL_ALLOCA (sizeof *(buf) * (multiplier) * (nitems)); \ + else \ + { \ + (buf) = xnmalloc (nitems, sizeof *(buf) * (multiplier)); \ + record_unwind_protect_ptr (xfree, buf); \ + } \ + } while (false) + #endif /* SAFE_ALLOCA_STRING allocates a C copy of a Lisp string. */ @@ -6210,6 +6198,15 @@ extern void igc_xfree (void *p); memcpy (ptr, SDATA (string), SBYTES (string) + 1); \ } while (false) +#ifdef HAVE_MPS +Lisp_Object *igc_alloc_lisp_obj_vec (size_t n); +#define SAFE_ALLOCA_XZALLOC(n, nbytes) igc_alloc_lisp_obj_vec (n) +#define SAFE_ALLOCA_XFREE(p) (void) 0 +#else +#define SAFE_ALLOCA_XZALLOC(n, nbytes) xzalloc (nbytes) +#define SAFE_ALLOCA_XFREE(p) xfree (p) +#endif + /* Free xmalloced memory and enable GC as needed. */ #define SAFE_FREE() safe_free (sa_count) @@ -6234,7 +6231,7 @@ safe_free (specpdl_ref sa_count) else { eassert (binding.kind == SPECPDL_UNWIND_ARRAY); - xfree (binding.unwind_array.array); + SAFE_ALLOCA_XFREE (binding.unwind_array.array); } } } @@ -6261,42 +6258,12 @@ safe_free_unbind_to (specpdl_ref count, specpdl_ref sa_count, Lisp_Object val) memory allocation in SAFE_ALLOCA_LISP_EXTRA. */ #if __GNUC__ == 13 && __GNUC_MINOR__ < 3 # pragma GCC diagnostic ignored "-Wanalyzer-allocation-size" -#endif - -#ifndef HAVE_MPS -/* Set BUF to point to an allocated array of NELT Lisp_Objects, - immediately followed by EXTRA spare bytes. */ - -#define SAFE_ALLOCA_LISP_EXTRA(buf, nelt, extra) \ - do { \ - eassert (sa_avail >= 0); \ - ptrdiff_t alloca_nbytes; \ - if (ckd_mul (&alloca_nbytes, nelt, word_size) \ - || ckd_add (&alloca_nbytes, alloca_nbytes, extra) \ - || SIZE_MAX < alloca_nbytes) \ - memory_full (SIZE_MAX); \ - else if (alloca_nbytes <= sa_avail) \ - (buf) = AVAIL_ALLOCA (alloca_nbytes); \ - else \ - { \ - /* Although only the first nelt words need clearing, \ - typically EXTRA is 0 or small so just use xzalloc; \ - this is simpler and often faster. */ \ - (buf) = xzalloc (alloca_nbytes); \ - record_unwind_protect_array (buf, nelt); \ - } \ - } while (false) +# endif /* Set BUF to point to an allocated array of NELT Lisp_Objects. */ -#define SAFE_ALLOCA_LISP(buf, nelt) SAFE_ALLOCA_LISP_EXTRA (buf, nelt, 0) - -#endif - -#ifdef HAVE_MPS #define SAFE_ALLOCA_LISP(buf, nelt) \ do { \ - eassert (sa_avail >= 0); \ ptrdiff_t alloca_nbytes; \ if (ckd_mul (&alloca_nbytes, nelt, word_size) \ || SIZE_MAX < alloca_nbytes) \ @@ -6305,12 +6272,10 @@ safe_free_unbind_to (specpdl_ref count, specpdl_ref sa_count, Lisp_Object val) (buf) = AVAIL_ALLOCA (alloca_nbytes); \ else \ { \ - eassert (sa_avail >= 0); \ - (buf) = igc_xalloc_lisp_objs_exact (nelt, __func__); \ - record_unwind_protect_ptr (igc_xfree, buf); \ + (buf) = SAFE_ALLOCA_XZALLOC (nelt, alloca_nbytes); \ + record_unwind_protect_array (buf, nelt); \ } \ } while (false) -#endif /* If USE_STACK_LISP_OBJECTS, define macros and functions that allocate some Lisp objects on the C stack. As the storage is not