summaryrefslogtreecommitdiff
path: root/src/eval.c
diff options
context:
space:
mode:
authorTom Tromey <tromey@redhat.com>2013-07-12 18:44:13 -0600
committerTom Tromey <tromey@redhat.com>2013-07-12 18:44:13 -0600
commitb34a529f177a6ea32da5cb1254f91bf9d71838db (patch)
tree477131abc15d3107b30b635223d87a22550b480b /src/eval.c
parente6f63071a3f7721f55220514b6d9a8ee8c1232d8 (diff)
parent5e301d7651c0691bb2bc7f3fbe711fdbe26ac471 (diff)
downloademacs-b34a529f177a6ea32da5cb1254f91bf9d71838db.tar.gz
Merge from trunk
Diffstat (limited to 'src/eval.c')
-rw-r--r--src/eval.c71
1 files changed, 42 insertions, 29 deletions
diff --git a/src/eval.c b/src/eval.c
index 451a7b0cc28..97e812dd890 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -114,6 +114,13 @@ Lisp_Object Vsignaling_function;
frame is half-initialized. */
Lisp_Object inhibit_lisp_code;
+/* These would ordinarily be static, but they need to be visible to GDB. */
+bool backtrace_p (union specbinding *) EXTERNALLY_VISIBLE;
+Lisp_Object *backtrace_args (union specbinding *) EXTERNALLY_VISIBLE;
+Lisp_Object backtrace_function (union specbinding *) EXTERNALLY_VISIBLE;
+union specbinding *backtrace_next (union specbinding *) EXTERNALLY_VISIBLE;
+union specbinding *backtrace_top (void) EXTERNALLY_VISIBLE;
+
static Lisp_Object funcall_lambda (Lisp_Object, ptrdiff_t, Lisp_Object *);
static Lisp_Object apply_lambda (Lisp_Object fun, Lisp_Object args);
@@ -159,7 +166,7 @@ specpdl_func (union specbinding *pdl)
return pdl->unwind.func;
}
-static Lisp_Object
+Lisp_Object
backtrace_function (union specbinding *pdl)
{
eassert (pdl->kind == SPECPDL_BACKTRACE);
@@ -173,7 +180,7 @@ backtrace_nargs (union specbinding *pdl)
return pdl->bt.nargs;
}
-static Lisp_Object *
+Lisp_Object *
backtrace_args (union specbinding *pdl)
{
eassert (pdl->kind == SPECPDL_BACKTRACE);
@@ -212,10 +219,6 @@ set_backtrace_debug_on_exit (union specbinding *pdl, bool doe)
/* Helper functions to scan the backtrace. */
-bool backtrace_p (union specbinding *) EXTERNALLY_VISIBLE;
-union specbinding *backtrace_top (void) EXTERNALLY_VISIBLE;
-union specbinding *backtrace_next (union specbinding *pdl) EXTERNALLY_VISIBLE;
-
bool
backtrace_p (union specbinding *pdl)
{ return pdl >= specpdl; }
@@ -2013,38 +2016,52 @@ If LEXICAL is t, evaluate using lexical scoping. */)
return unbind_to (count, eval_sub (form));
}
+/* Grow the specpdl stack by one entry.
+ The caller should have already initialized the entry.
+ Signal an error on stack overflow.
+
+ Make sure that there is always one unused entry past the top of the
+ stack, so that the just-initialized entry is safely unwound if
+ memory exhausted and an error is signaled here. Also, allocate a
+ never-used entry just before the bottom of the stack; sometimes its
+ address is taken. */
+
static void
grow_specpdl (void)
{
- ptrdiff_t 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)
+ specpdl_ptr++;
+
+ if (specpdl_ptr == specpdl + specpdl_size)
{
- if (max_specpdl_size < 400)
- max_size = max_specpdl_size = 400;
+ ptrdiff_t 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)
- signal_error ("Variable binding depth exceeds max-specpdl-size", Qnil);
+ {
+ if (max_specpdl_size < 400)
+ max_size = max_specpdl_size = 400;
+ if (max_size <= specpdl_size)
+ signal_error ("Variable binding depth exceeds max-specpdl-size",
+ Qnil);
+ }
+ pdlvec = xpalloc (pdlvec, &pdlvecsize, 1, max_size + 1, sizeof *specpdl);
+ specpdl = pdlvec + 1;
+ specpdl_size = pdlvecsize - 1;
+ specpdl_ptr = specpdl + count;
}
- pdlvec = xpalloc (pdlvec, &pdlvecsize, 1, max_size + 1, sizeof *specpdl);
- specpdl = pdlvec + 1;
- specpdl_size = pdlvecsize - 1;
- specpdl_ptr = specpdl + count;
}
void
record_in_backtrace (Lisp_Object function, Lisp_Object *args, ptrdiff_t nargs)
{
eassert (nargs >= UNEVALLED);
- if (specpdl_ptr == specpdl + specpdl_size)
- grow_specpdl ();
specpdl_ptr->bt.kind = SPECPDL_BACKTRACE;
specpdl_ptr->bt.debug_on_exit = false;
specpdl_ptr->bt.function = function;
specpdl_ptr->bt.args = args;
specpdl_ptr->bt.nargs = nargs;
- specpdl_ptr++;
+ grow_specpdl ();
}
/* Eval a sub-expression of the current expression (i.e. in the same
@@ -3176,8 +3193,6 @@ specbind (Lisp_Object symbol, Lisp_Object value)
CHECK_SYMBOL (symbol);
sym = XSYMBOL (symbol);
- if (specpdl_ptr == specpdl + specpdl_size)
- grow_specpdl ();
start:
switch (sym->redirect)
@@ -3191,7 +3206,7 @@ specbind (Lisp_Object symbol, Lisp_Object value)
specpdl_ptr->let.symbol = symbol;
specpdl_ptr->let.old_value = SYMBOL_VAL (sym);
specpdl_ptr->let.saved_value = Qnil;
- ++specpdl_ptr;
+ grow_specpdl ();
do_specbind (sym, specpdl_ptr - 1, value);
break;
case SYMBOL_LOCALIZED:
@@ -3224,7 +3239,7 @@ specbind (Lisp_Object symbol, Lisp_Object value)
if (NILP (Flocal_variable_p (symbol, Qnil)))
{
specpdl_ptr->let.kind = SPECPDL_LET_DEFAULT;
- ++specpdl_ptr;
+ grow_specpdl ();
do_specbind (sym, specpdl_ptr - 1, value);
return;
}
@@ -3232,7 +3247,7 @@ specbind (Lisp_Object symbol, Lisp_Object value)
else
specpdl_ptr->let.kind = SPECPDL_LET;
- specpdl_ptr++;
+ grow_specpdl ();
do_specbind (sym, specpdl_ptr - 1, value);
break;
}
@@ -3243,12 +3258,10 @@ specbind (Lisp_Object symbol, Lisp_Object value)
void
record_unwind_protect (Lisp_Object (*function) (Lisp_Object), Lisp_Object arg)
{
- if (specpdl_ptr == specpdl + specpdl_size)
- grow_specpdl ();
specpdl_ptr->unwind.kind = SPECPDL_UNWIND;
specpdl_ptr->unwind.func = function;
specpdl_ptr->unwind.arg = arg;
- specpdl_ptr++;
+ grow_specpdl ();
}
void