emacs-diffs
[Top][All Lists]
Advanced

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

[Emacs-diffs] master aca938d 07/10: Avoid allocating Lisp_Save_Value for


From: Paul Eggert
Subject: [Emacs-diffs] master aca938d 07/10: Avoid allocating Lisp_Save_Value for excursions
Date: Thu, 14 Jun 2018 20:15:25 -0400 (EDT)

branch: master
commit aca938d1f4ec176a2d00a77693b231298b9c5c4e
Author: Paul Eggert <address@hidden>
Commit: Paul Eggert <address@hidden>

    Avoid allocating Lisp_Save_Value for excursions
    
    * src/editfns.c (save_excursion_save): New arg PDL,
    specifying where to save the state.  All uses changed.
    (save_excursion_restore): Args are now the marker and info
    rather than a pointer to a Lisp_Save_Value containing them.
    All uses changed.
    * src/eval.c (default_toplevel_binding, Fbacktrace__locals):
    Treat excursions like other miscellaneous pdl types.
    (record_unwind_protect_excursion): Save data directly
    into the pdl rather than creating an object on the heap.
    This avoids the need to allocate and free an object.
    (do_one_unbind, backtrace_eval_unrewind):
    Unwind excursions directly.
    (mark_specpdl): Mark excursions directly.
    * src/lisp.h (SPECPDL_UNWIND_EXCURSION): New constant.
    (union specbinding): New member unwind_excursion.
---
 src/editfns.c | 27 +++++++++++----------------
 src/eval.c    | 38 +++++++++++++++++++++++++++-----------
 src/lisp.h    |  9 +++++++--
 3 files changed, 45 insertions(+), 29 deletions(-)

diff --git a/src/editfns.c b/src/editfns.c
index e672c0e..3147f9d 100644
--- a/src/editfns.c
+++ b/src/editfns.c
@@ -995,30 +995,24 @@ This function does not move point.  */)
                              Qnil, Qt, Qnil);
 }
 
-/* Save current buffer state for `save-excursion' special form.
-   We (ab)use Lisp_Misc_Save_Value to allow explicit free and so
-   offload some work from GC.  */
+/* Save current buffer state for save-excursion special form.  */
 
-Lisp_Object
-save_excursion_save (void)
+void
+save_excursion_save (union specbinding *pdl)
 {
-  return make_save_obj_obj_obj_obj
-    (Fpoint_marker (),
-     Qnil,
-     /* Selected window if current buffer is shown in it, nil otherwise.  */
-     (EQ (XWINDOW (selected_window)->contents, Fcurrent_buffer ())
-      ? selected_window : Qnil),
-     Qnil);
+  eassert (pdl->unwind_excursion.kind == SPECPDL_UNWIND_EXCURSION);
+  pdl->unwind_excursion.marker = Fpoint_marker ();
+  /* Selected window if current buffer is shown in it, nil otherwise.  */
+  pdl->unwind_excursion.window
+    = (EQ (XWINDOW (selected_window)->contents, Fcurrent_buffer ())
+       ? selected_window : Qnil);
 }
 
 /* Restore saved buffer before leaving `save-excursion' special form.  */
 
 void
-save_excursion_restore (Lisp_Object info)
+save_excursion_restore (Lisp_Object marker, Lisp_Object window)
 {
-  Lisp_Object marker = XSAVE_OBJECT (info, 0);
-  Lisp_Object window = XSAVE_OBJECT (info, 2);
-  free_misc (info);
   Lisp_Object buffer = Fmarker_buffer (marker);
   /* If we're unwinding to top level, saved buffer may be deleted.  This
      means that all of its markers are unchained and so BUFFER is nil.  */
@@ -1027,6 +1021,7 @@ save_excursion_restore (Lisp_Object info)
 
   Fset_buffer (buffer);
 
+  /* Point marker.  */
   Fgoto_char (marker);
   unchain_marker (XMARKER (marker));
 
diff --git a/src/eval.c b/src/eval.c
index 5c7cb31..dded16b 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -675,6 +675,7 @@ default_toplevel_binding (Lisp_Object symbol)
        case SPECPDL_UNWIND:
        case SPECPDL_UNWIND_PTR:
        case SPECPDL_UNWIND_INT:
+       case SPECPDL_UNWIND_EXCURSION:
        case SPECPDL_UNWIND_VOID:
        case SPECPDL_BACKTRACE:
        case SPECPDL_LET_LOCAL:
@@ -3427,7 +3428,9 @@ record_unwind_protect_int (void (*function) (int), int 
arg)
 void
 record_unwind_protect_excursion (void)
 {
-  record_unwind_protect (save_excursion_restore, save_excursion_save ());
+  specpdl_ptr->unwind_excursion.kind = SPECPDL_UNWIND_EXCURSION;
+  save_excursion_save (specpdl_ptr);
+  grow_specpdl ();
 }
 
 void
@@ -3475,6 +3478,10 @@ do_one_unbind (union specbinding *this_binding, bool 
unwinding,
     case SPECPDL_UNWIND_VOID:
       this_binding->unwind_void.func ();
       break;
+    case SPECPDL_UNWIND_EXCURSION:
+      save_excursion_restore (this_binding->unwind_excursion.marker,
+                             this_binding->unwind_excursion.window);
+      break;
     case SPECPDL_BACKTRACE:
       break;
     case SPECPDL_LET:
@@ -3749,18 +3756,21 @@ backtrace_eval_unrewind (int distance)
             unwind_protect, but the problem is that we don't know how to
             rewind them afterwards.  */
        case SPECPDL_UNWIND:
-         {
-           Lisp_Object oldarg = tmp->unwind.arg;
-           if (tmp->unwind.func == set_buffer_if_live)
+         if (tmp->unwind.func == set_buffer_if_live)
+           {
+             Lisp_Object oldarg = tmp->unwind.arg;
              tmp->unwind.arg = Fcurrent_buffer ();
-           else if (tmp->unwind.func == save_excursion_restore)
-             tmp->unwind.arg = save_excursion_save ();
-           else
-             break;
-           tmp->unwind.func (oldarg);
-           break;
+             set_buffer_if_live (oldarg);
+           }
+         break;
+       case SPECPDL_UNWIND_EXCURSION:
+         {
+           Lisp_Object marker = tmp->unwind_excursion.marker;
+           Lisp_Object window = tmp->unwind_excursion.window;
+           save_excursion_save (tmp);
+           save_excursion_restore (marker, window);
          }
-
+         break;
        case SPECPDL_UNWIND_PTR:
        case SPECPDL_UNWIND_INT:
        case SPECPDL_UNWIND_VOID:
@@ -3895,6 +3905,7 @@ NFRAMES and BASE specify the activation frame to use, as 
in `backtrace-frame'.
          case SPECPDL_UNWIND:
          case SPECPDL_UNWIND_PTR:
          case SPECPDL_UNWIND_INT:
+         case SPECPDL_UNWIND_EXCURSION:
          case SPECPDL_UNWIND_VOID:
          case SPECPDL_BACKTRACE:
            break;
@@ -3924,6 +3935,11 @@ mark_specpdl (union specbinding *first, union 
specbinding *ptr)
          mark_object (specpdl_arg (pdl));
          break;
 
+       case SPECPDL_UNWIND_EXCURSION:
+         mark_object (pdl->unwind_excursion.marker);
+         mark_object (pdl->unwind_excursion.window);
+         break;
+
        case SPECPDL_BACKTRACE:
          {
            ptrdiff_t nargs = backtrace_nargs (pdl);
diff --git a/src/lisp.h b/src/lisp.h
index b7e5d9e..af3f587 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -3188,6 +3188,7 @@ enum specbind_tag {
   SPECPDL_UNWIND,              /* An unwind_protect function on Lisp_Object.  
*/
   SPECPDL_UNWIND_PTR,          /* Likewise, on void *.  */
   SPECPDL_UNWIND_INT,          /* Likewise, on int.  */
+  SPECPDL_UNWIND_EXCURSION,    /* Likewise, on an execursion.  */
   SPECPDL_UNWIND_VOID,         /* Likewise, with no arg.  */
   SPECPDL_BACKTRACE,           /* An element of the backtrace.  */
   SPECPDL_LET,                 /* A plain and simple dynamic let-binding.  */
@@ -3216,6 +3217,10 @@ union specbinding
     } unwind_int;
     struct {
       ENUM_BF (specbind_tag) kind : CHAR_BIT;
+      Lisp_Object marker, window;
+    } unwind_excursion;
+    struct {
+      ENUM_BF (specbind_tag) kind : CHAR_BIT;
       void (*func) (void);
     } unwind_void;
     struct {
@@ -4106,9 +4111,9 @@ extern void mark_threads (void);
 
 /* Defined in editfns.c.  */
 extern void insert1 (Lisp_Object);
-extern Lisp_Object save_excursion_save (void);
+extern void save_excursion_save (union specbinding *);
+extern void save_excursion_restore (Lisp_Object, Lisp_Object);
 extern Lisp_Object save_restriction_save (void);
-extern void save_excursion_restore (Lisp_Object);
 extern void save_restriction_restore (Lisp_Object);
 extern _Noreturn void time_overflow (void);
 extern Lisp_Object make_buffer_string (ptrdiff_t, ptrdiff_t, bool);



reply via email to

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