diff options
author | Tom Tromey <tromey@redhat.com> | 2013-07-12 18:44:13 -0600 |
---|---|---|
committer | Tom Tromey <tromey@redhat.com> | 2013-07-12 18:44:13 -0600 |
commit | b34a529f177a6ea32da5cb1254f91bf9d71838db (patch) | |
tree | 477131abc15d3107b30b635223d87a22550b480b /src/eval.c | |
parent | e6f63071a3f7721f55220514b6d9a8ee8c1232d8 (diff) | |
parent | 5e301d7651c0691bb2bc7f3fbe711fdbe26ac471 (diff) | |
download | emacs-b34a529f177a6ea32da5cb1254f91bf9d71838db.tar.gz |
Merge from trunk
Diffstat (limited to 'src/eval.c')
-rw-r--r-- | src/eval.c | 71 |
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 |