From fe65db05f42bcbf755f037575b3c29b74f279bdf Mon Sep 17 00:00:00 2001 From: =?utf8?q?Mattias=20Engdeg=C3=A5rd?= Date: Sat, 26 Feb 2022 12:49:02 +0100 Subject: [PATCH] Maintain end of specpdl instead of size Keep track of the end of specpdl explicitly since that is what we are comparing against on critical code paths. * src/eval.c (init_eval_once_for_pdumper, signal_or_quit) (grow_specpdl_allocation): * src/fileio.c (Fdo_auto_save): * src/lisp.h (grow_specpdl): * src/thread.c (run_thread, Fmake_thread): * src/thread.h (struct thread_state): Replace specpdl_size with specpdl_end, according to the equation specpdl_end = specpdl + specpdl_size. --- src/eval.c | 15 ++++++++------- src/fileio.c | 3 ++- src/lisp.h | 2 +- src/thread.c | 11 +++++------ src/thread.h | 8 ++++---- 5 files changed, 20 insertions(+), 19 deletions(-) diff --git a/src/eval.c b/src/eval.c index 0fc492fbe0e..a9d56ca23b3 100644 --- a/src/eval.c +++ b/src/eval.c @@ -223,8 +223,8 @@ init_eval_once_for_pdumper (void) { enum { size = 50 }; union specbinding *pdlvec = malloc ((size + 1) * sizeof *specpdl); - specpdl_size = size; specpdl = specpdl_ptr = pdlvec + 1; + specpdl_end = specpdl + size; } void @@ -1773,7 +1773,7 @@ signal_or_quit (Lisp_Object error_symbol, Lisp_Object data, bool keyboard_quit) && ! NILP (error_symbol) /* Don't try to call a lisp function if we've already overflowed the specpdl stack. */ - && specpdl_ptr < specpdl + specpdl_size) + && specpdl_ptr < specpdl_end) { /* Edebug takes care of restoring these variables when it exits. */ max_ensure_room (&max_lisp_eval_depth, lisp_eval_depth, 20); @@ -2323,22 +2323,23 @@ alist mapping symbols to their value. */) void grow_specpdl_allocation (void) { - eassert (specpdl_ptr == specpdl + specpdl_size); + eassert (specpdl_ptr == specpdl_end); specpdl_ref count = SPECPDL_INDEX (); ptrdiff_t max_size = min (max_specpdl_size, PTRDIFF_MAX - 1000); union specbinding *pdlvec = specpdl - 1; - ptrdiff_t pdlvecsize = specpdl_size + 1; - if (max_size <= specpdl_size) + ptrdiff_t size = specpdl_end - specpdl; + ptrdiff_t pdlvecsize = size + 1; + if (max_size <= size) { if (max_specpdl_size < 400) max_size = max_specpdl_size = 400; - if (max_size <= specpdl_size) + if (max_size <= size) xsignal0 (Qexcessive_variable_binding); } pdlvec = xpalloc (pdlvec, &pdlvecsize, 1, max_size + 1, sizeof *specpdl); specpdl = pdlvec + 1; - specpdl_size = pdlvecsize - 1; + specpdl_end = specpdl + pdlvecsize - 1; specpdl_ptr = specpdl_ref_to_ptr (count); } diff --git a/src/fileio.c b/src/fileio.c index 243a87a4821..a0282204de8 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -5973,7 +5973,8 @@ A non-nil CURRENT-ONLY argument means save only current buffer. */) bool old_message_p = 0; struct auto_save_unwind auto_save_unwind; - intmax_t sum = INT_ADD_WRAPV (specpdl_size, 40, &sum) ? INTMAX_MAX : sum; + intmax_t sum = INT_ADD_WRAPV (specpdl_end - specpdl, 40, &sum) + ? INTMAX_MAX : sum; if (max_specpdl_size < sum) max_specpdl_size = sum; diff --git a/src/lisp.h b/src/lisp.h index b99441fa6c1..3c73570babf 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -3469,7 +3469,7 @@ INLINE void grow_specpdl (void) { specpdl_ptr++; - if (specpdl_ptr == specpdl + specpdl_size) + if (specpdl_ptr == specpdl_end) grow_specpdl_allocation (); } diff --git a/src/thread.c b/src/thread.c index 4c98d590b7a..b5b7d7c0d71 100644 --- a/src/thread.c +++ b/src/thread.c @@ -790,7 +790,7 @@ run_thread (void *state) xfree (self->m_specpdl - 1); self->m_specpdl = NULL; self->m_specpdl_ptr = NULL; - self->m_specpdl_size = 0; + self->m_specpdl_end = NULL; { struct handler *c, *c_next; @@ -862,11 +862,10 @@ If NAME is given, it must be a string; it names the new thread. */) /* Perhaps copy m_last_thing_searched from parent? */ new_thread->m_current_buffer = current_thread->m_current_buffer; - new_thread->m_specpdl_size = 50; - new_thread->m_specpdl = xmalloc ((1 + new_thread->m_specpdl_size) - * sizeof (union specbinding)); - /* Skip the dummy entry. */ - ++new_thread->m_specpdl; + ptrdiff_t size = 50; + union specbinding *pdlvec = xmalloc ((1 + size) * sizeof (union specbinding)); + new_thread->m_specpdl = pdlvec + 1; /* Skip the dummy entry. */ + new_thread->m_specpdl_end = new_thread->m_specpdl + size; new_thread->m_specpdl_ptr = new_thread->m_specpdl; sys_cond_init (&new_thread->thread_condvar); diff --git a/src/thread.h b/src/thread.h index 1e7eb86f6ee..f2755045b2e 100644 --- a/src/thread.h +++ b/src/thread.h @@ -92,14 +92,14 @@ struct thread_state struct handler *m_handlerlist_sentinel; #define handlerlist_sentinel (current_thread->m_handlerlist_sentinel) - /* Current number of specbindings allocated in specpdl. */ - ptrdiff_t m_specpdl_size; -#define specpdl_size (current_thread->m_specpdl_size) - /* Pointer to beginning of specpdl. */ union specbinding *m_specpdl; #define specpdl (current_thread->m_specpdl) + /* End of specpld (just beyond the last element). */ + union specbinding *m_specpdl_end; +#define specpdl_end (current_thread->m_specpdl_end) + /* Pointer to first unused element in specpdl. */ union specbinding *m_specpdl_ptr; #define specpdl_ptr (current_thread->m_specpdl_ptr) -- 2.39.2