mirror of
git://git.sv.gnu.org/emacs.git
synced 2025-12-28 00:01:33 -08:00
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.
This commit is contained in:
parent
6c04c848e6
commit
aca938d1f4
3 changed files with 45 additions and 29 deletions
|
|
@ -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));
|
||||
|
||||
|
|
|
|||
38
src/eval.c
38
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);
|
||||
|
|
|
|||
|
|
@ -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. */
|
||||
|
|
@ -3214,6 +3215,10 @@ union specbinding
|
|||
void (*func) (int);
|
||||
int arg;
|
||||
} 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);
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue