emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] trunk r113405: Don't lose top specpdl entry when memory is


From: Paul Eggert
Subject: [Emacs-diffs] trunk r113405: Don't lose top specpdl entry when memory is exhausted.
Date: Sat, 13 Jul 2013 00:25:21 +0000
User-agent: Bazaar (2.6b2)

------------------------------------------------------------
revno: 113405
revision-id: address@hidden
parent: address@hidden
committer: Paul Eggert <address@hidden>
branch nick: trunk
timestamp: Fri 2013-07-12 17:24:38 -0700
message:
  Don't lose top specpdl entry when memory is exhausted.
  
  * eval.c (grow_specpdl): Increment specpdl top by 1 and check for
  specpdl overflow here, to simplify callers; all callers changed.
  Always reserve an unused entry at the stack top; this avoids
  losing the top entry's information when memory is exhausted.
modified:
  src/ChangeLog                  changelog-20091113204419-o5vbwnq5f7feedwu-1438
  src/eval.c                     eval.c-20091113204419-o5vbwnq5f7feedwu-237
=== modified file 'src/ChangeLog'
--- a/src/ChangeLog     2013-07-12 17:30:48 +0000
+++ b/src/ChangeLog     2013-07-13 00:24:38 +0000
@@ -1,3 +1,11 @@
+2013-07-13  Paul Eggert  <address@hidden>
+
+       Don't lose top specpdl entry when memory is exhausted.
+       * eval.c (grow_specpdl): Increment specpdl top by 1 and check for
+       specpdl overflow here, to simplify callers; all callers changed.
+       Always reserve an unused entry at the stack top; this avoids
+       losing the top entry's information when memory is exhausted.
+
 2013-07-12  Paul Eggert  <address@hidden>
 
        Clean up errno reporting and fix some errno-reporting bugs.

=== modified file 'src/eval.c'
--- a/src/eval.c        2013-07-11 07:17:23 +0000
+++ b/src/eval.c        2013-07-13 00:24:38 +0000
@@ -1996,38 +1996,52 @@
   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
@@ -3113,8 +3127,6 @@
 
   CHECK_SYMBOL (symbol);
   sym = XSYMBOL (symbol);
-  if (specpdl_ptr == specpdl + specpdl_size)
-    grow_specpdl ();
 
  start:
   switch (sym->redirect)
@@ -3127,7 +3139,7 @@
       specpdl_ptr->let.kind = SPECPDL_LET;
       specpdl_ptr->let.symbol = symbol;
       specpdl_ptr->let.old_value = SYMBOL_VAL (sym);
-      ++specpdl_ptr;
+      grow_specpdl ();
       if (!sym->constant)
        SET_SYMBOL_VAL (sym, value);
       else
@@ -3162,7 +3174,7 @@
            if (NILP (Flocal_variable_p (symbol, Qnil)))
              {
                specpdl_ptr->let.kind = SPECPDL_LET_DEFAULT;
-               ++specpdl_ptr;
+               grow_specpdl ();
                Fset_default (symbol, value);
                return;
              }
@@ -3170,7 +3182,7 @@
        else
          specpdl_ptr->let.kind = SPECPDL_LET;
 
-       specpdl_ptr++;
+       grow_specpdl ();
        set_internal (symbol, value, Qnil, 1);
        break;
       }
@@ -3181,12 +3193,10 @@
 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 ();
 }
 
 Lisp_Object


reply via email to

[Prev in Thread] Current Thread [Next in Thread]