1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2026-01-01 09:51:22 -08:00

Abolish max-specpdl-size (bug#57911)

The max-lisp-eval-depth limit is sufficient to prevent unbounded stack
growth including the specbind stack; simplify matters for the user by
not having them to worry about two different limits.  This change
turns max-specpdl-size into a harmless variable with no effects,
to keep existing code happy.

* lisp/subr.el (max-specpdl-size):
Define as an ordinary (but obsolete) dynamic variable.
* admin/grammars/Makefile.in:
* doc/lispintro/emacs-lisp-intro.texi (Loops & Recursion):
* doc/lispref/control.texi (Cleanups):
* doc/lispref/edebug.texi (Checking Whether to Stop):
* doc/lispref/eval.texi (Eval):
* doc/lispref/variables.texi (Local Variables):
* doc/misc/calc.texi (Recursion Depth):
Update documentation.
* etc/NEWS: Announce.
* src/eval.c
(FletX): Use safe iteration to guard against circular bindings list.
(syms_of_eval): Remove old max-specpdl-size definition.
(init_eval_once, restore_stack_limits, call_debugger)
(signal_or_quit, grow_specpdl_allocation):
* leim/Makefile.in:
* lisp/Makefile.in:
* lisp/calc/calc-stuff.el (calc-more-recursion-depth)
(calc-less-recursion-depth):
* lisp/calc/calc.el (calc-do):
* lisp/cedet/semantic/ede-grammar.el (ede-proj-makefile-insert-rules):
* lisp/cedet/semantic/grammar.el (semantic-grammar-batch-build-one-package):
* lisp/cus-start.el (standard):
* lisp/emacs-lisp/comp.el (comp--native-compile):
* lisp/emacs-lisp/edebug.el (edebug-max-depth):
(edebug-read-and-maybe-wrap-form, edebug-default-enter):
* lisp/emacs-lisp/regexp-opt.el (regexp-opt):
* lisp/eshell/esh-mode.el (eshell-mode):
* lisp/loadup.el (max-specpdl-size):
* lisp/mh-e/mh-e.el (mh-invisible-headers):
* lisp/net/shr.el (shr-insert-document, shr-descend):
* lisp/play/hanoi.el (hanoi-internal):
* lisp/progmodes/cperl-mode.el:
* src/fileio.c (Fdo_auto_save):
Remove references to and modifications of max-specpdl-size.
This commit is contained in:
Mattias Engdegård 2022-09-19 10:55:09 +02:00
parent a7c65fc666
commit 60102016e4
27 changed files with 68 additions and 173 deletions

View file

@ -211,9 +211,7 @@ backtrace_thread_next (struct thread_state *tstate, union specbinding *pdl)
void
init_eval_once (void)
{
/* Don't forget to update docs
(lispref nodes "Local Variables" and "Eval"). */
max_specpdl_size = 2500;
/* Don't forget to update docs (lispref node "Eval"). */
max_lisp_eval_depth = 1600;
Vrun_hooks = Qnil;
pdumper_do_now_and_after_load (init_eval_once_for_pdumper);
@ -265,8 +263,7 @@ max_ensure_room (intmax_t *m, intmax_t a, intmax_t b)
static void
restore_stack_limits (Lisp_Object data)
{
integer_to_intmax (XCAR (data), &max_specpdl_size);
integer_to_intmax (XCDR (data), &max_lisp_eval_depth);
integer_to_intmax (data, &max_lisp_eval_depth);
}
/* Call the Lisp debugger, giving it argument ARG. */
@ -278,9 +275,6 @@ call_debugger (Lisp_Object arg)
specpdl_ref count = SPECPDL_INDEX ();
Lisp_Object val;
intmax_t old_depth = max_lisp_eval_depth;
/* Do not allow max_specpdl_size less than actual depth (Bug#16603). */
ptrdiff_t counti = specpdl_ref_to_count (count);
intmax_t old_max = max (max_specpdl_size, counti);
/* The previous value of 40 is too small now that the debugger
prints using cl-prin1 instead of prin1. Printing lists nested 8
@ -288,20 +282,8 @@ call_debugger (Lisp_Object arg)
currently requires 77 additional frames. See bug#31919. */
max_ensure_room (&max_lisp_eval_depth, lisp_eval_depth, 100);
/* While debugging Bug#16603, previous value of 100 was found
too small to avoid specpdl overflow in the debugger itself. */
max_ensure_room (&max_specpdl_size, counti, 200);
if (old_max == counti)
{
/* We can enter the debugger due to specpdl overflow (Bug#16603). */
specpdl_ptr--;
grow_specpdl ();
}
/* Restore limits after leaving the debugger. */
record_unwind_protect (restore_stack_limits,
Fcons (make_int (old_max), make_int (old_depth)));
record_unwind_protect (restore_stack_limits, make_int (old_depth));
#ifdef HAVE_WINDOW_SYSTEM
if (display_hourglass_p)
@ -933,12 +915,9 @@ usage: (let* VARLIST BODY...) */)
lexenv = Vinternal_interpreter_environment;
Lisp_Object varlist = XCAR (args);
while (CONSP (varlist))
FOR_EACH_TAIL (varlist)
{
maybe_quit ();
elt = XCAR (varlist);
varlist = XCDR (varlist);
if (SYMBOLP (elt))
{
var = elt;
@ -1752,8 +1731,6 @@ signal_or_quit (Lisp_Object error_symbol, Lisp_Object data, bool keyboard_quit)
{
/* Edebug takes care of restoring these variables when it exits. */
max_ensure_room (&max_lisp_eval_depth, lisp_eval_depth, 20);
ptrdiff_t counti = specpdl_ref_to_count (SPECPDL_INDEX ());
max_ensure_room (&max_specpdl_size, counti, 40);
call2 (Vsignal_hook_function, error_symbol, data);
}
@ -1822,8 +1799,6 @@ signal_or_quit (Lisp_Object error_symbol, Lisp_Object data, bool keyboard_quit)
{
max_ensure_room (&max_lisp_eval_depth, lisp_eval_depth, 100);
specpdl_ref count = SPECPDL_INDEX ();
ptrdiff_t counti = specpdl_ref_to_count (count);
max_ensure_room (&max_specpdl_size, counti, 200);
specbind (Qdebugger, Qdebug_early);
call_debugger (list2 (Qerror, Fcons (error_symbol, data)));
unbind_to (count, Qnil);
@ -1839,12 +1814,10 @@ signal_or_quit (Lisp_Object error_symbol, Lisp_Object data, bool keyboard_quit)
{
max_ensure_room (&max_lisp_eval_depth, lisp_eval_depth, 100);
specpdl_ref count = SPECPDL_INDEX ();
ptrdiff_t counti = specpdl_ref_to_count (count);
AUTO_STRING (redisplay_trace, "*Redisplay_trace*");
Lisp_Object redisplay_trace_buffer;
AUTO_STRING (gap, "\n\n\n\n"); /* Separates things in *Redisplay-trace* */
Lisp_Object delayed_warning;
max_ensure_room (&max_specpdl_size, counti, 200);
redisplay_trace_buffer = Fget_buffer_create (redisplay_trace, Qnil);
current_buffer = XBUFFER (redisplay_trace_buffer);
if (!backtrace_yet) /* Are we on the first backtrace of the command? */
@ -2376,17 +2349,12 @@ grow_specpdl_allocation (void)
eassert (specpdl_ptr == specpdl_end);
specpdl_ref count = SPECPDL_INDEX ();
ptrdiff_t max_size = min (max_specpdl_size, PTRDIFF_MAX - 1000);
ptrdiff_t max_size = PTRDIFF_MAX - 1000;
union specbinding *pdlvec = specpdl - 1;
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 <= size)
xsignal0 (Qexcessive_variable_binding);
}
xsignal0 (Qexcessive_variable_binding); /* Can't happen, essentially. */
pdlvec = xpalloc (pdlvec, &pdlvecsize, 1, max_size + 1, sizeof *specpdl);
specpdl = pdlvec + 1;
specpdl_end = specpdl + pdlvecsize - 1;
@ -4229,22 +4197,6 @@ Lisp_Object backtrace_top_function (void)
void
syms_of_eval (void)
{
DEFVAR_INT ("max-specpdl-size", max_specpdl_size,
doc: /* Limit on number of Lisp variable bindings and `unwind-protect's.
If Lisp code tries to use more bindings than this amount, an error is
signaled.
You can safely increase this variable substantially if the default
value proves inconveniently small. However, if you increase it too
much, Emacs could run out of memory trying to make the stack bigger.
Note that this limit may be silently increased by the debugger if
`debug-on-error' or `debug-on-quit' is set.
\"spec\" is short for \"special variables\", i.e., dynamically bound
variables. \"PDL\" is short for \"push-down list\", which is an old
term for \"stack\". */);
DEFVAR_INT ("max-lisp-eval-depth", max_lisp_eval_depth,
doc: /* Limit on depth in `eval', `apply' and `funcall' before error.