diff options
| author | Paul Eggert | 2018-06-07 19:12:28 -0700 |
|---|---|---|
| committer | Paul Eggert | 2018-06-14 17:13:39 -0700 |
| commit | d98670eb04925fdc4a4928a9b0d0858881da418f (patch) | |
| tree | 52d74dac7f568f7bcfe252ec9efd7658177895e0 /src | |
| parent | aca938d1f4ec176a2d00a77693b231298b9c5c4e (diff) | |
| download | emacs-d98670eb04925fdc4a4928a9b0d0858881da418f.tar.gz emacs-d98670eb04925fdc4a4928a9b0d0858881da418f.zip | |
Avoid allocating Lisp_Save_Value for arrays
* src/alloc.c (mark_maybe_objects): New function.
* src/eval.c (default_toplevel_binding)
(backtrace_eval_unrewind, Fbacktrace__locals):
Treat array unwindings like other miscellaneous pdl types.
(record_unwind_protect_array): New function.
(do_one_unbind): Free the array while unwinding.
(mark_specpdl): Mark arrays directly.
* src/lisp.h (SPECPDL_UNWIND_ARRAY): New constant.
(union specbinding): New member unwind_array.
(SAFE_ALLOCA_LISP_EXTRA): Use record_unwind_protect_array
instead of make_save_memory + record_unwind_protect.
Diffstat (limited to 'src')
| -rw-r--r-- | src/alloc.c | 7 | ||||
| -rw-r--r-- | src/eval.c | 19 | ||||
| -rw-r--r-- | src/lisp.h | 14 |
3 files changed, 37 insertions, 3 deletions
diff --git a/src/alloc.c b/src/alloc.c index e5fc6ebeb1a..1d3ec4fbb8a 100644 --- a/src/alloc.c +++ b/src/alloc.c | |||
| @@ -4845,6 +4845,13 @@ mark_maybe_object (Lisp_Object obj) | |||
| 4845 | } | 4845 | } |
| 4846 | } | 4846 | } |
| 4847 | 4847 | ||
| 4848 | void | ||
| 4849 | mark_maybe_objects (Lisp_Object *array, ptrdiff_t nelts) | ||
| 4850 | { | ||
| 4851 | for (Lisp_Object *lim = array + nelts; array < lim; array++) | ||
| 4852 | mark_maybe_object (*array); | ||
| 4853 | } | ||
| 4854 | |||
| 4848 | /* Return true if P might point to Lisp data that can be garbage | 4855 | /* Return true if P might point to Lisp data that can be garbage |
| 4849 | collected, and false otherwise (i.e., false if it is easy to see | 4856 | collected, and false otherwise (i.e., false if it is easy to see |
| 4850 | that P cannot point to Lisp data that can be garbage collected). | 4857 | that P cannot point to Lisp data that can be garbage collected). |
diff --git a/src/eval.c b/src/eval.c index dded16bed55..952a0ec4b46 100644 --- a/src/eval.c +++ b/src/eval.c | |||
| @@ -673,6 +673,7 @@ default_toplevel_binding (Lisp_Object symbol) | |||
| 673 | break; | 673 | break; |
| 674 | 674 | ||
| 675 | case SPECPDL_UNWIND: | 675 | case SPECPDL_UNWIND: |
| 676 | case SPECPDL_UNWIND_ARRAY: | ||
| 676 | case SPECPDL_UNWIND_PTR: | 677 | case SPECPDL_UNWIND_PTR: |
| 677 | case SPECPDL_UNWIND_INT: | 678 | case SPECPDL_UNWIND_INT: |
| 678 | case SPECPDL_UNWIND_EXCURSION: | 679 | case SPECPDL_UNWIND_EXCURSION: |
| @@ -3408,6 +3409,15 @@ record_unwind_protect (void (*function) (Lisp_Object), Lisp_Object arg) | |||
| 3408 | } | 3409 | } |
| 3409 | 3410 | ||
| 3410 | void | 3411 | void |
| 3412 | record_unwind_protect_array (Lisp_Object *array, ptrdiff_t nelts) | ||
| 3413 | { | ||
| 3414 | specpdl_ptr->unwind_array.kind = SPECPDL_UNWIND_ARRAY; | ||
| 3415 | specpdl_ptr->unwind_array.array = array; | ||
| 3416 | specpdl_ptr->unwind_array.nelts = nelts; | ||
| 3417 | grow_specpdl (); | ||
| 3418 | } | ||
| 3419 | |||
| 3420 | void | ||
| 3411 | record_unwind_protect_ptr (void (*function) (void *), void *arg) | 3421 | record_unwind_protect_ptr (void (*function) (void *), void *arg) |
| 3412 | { | 3422 | { |
| 3413 | specpdl_ptr->unwind_ptr.kind = SPECPDL_UNWIND_PTR; | 3423 | specpdl_ptr->unwind_ptr.kind = SPECPDL_UNWIND_PTR; |
| @@ -3469,6 +3479,9 @@ do_one_unbind (union specbinding *this_binding, bool unwinding, | |||
| 3469 | case SPECPDL_UNWIND: | 3479 | case SPECPDL_UNWIND: |
| 3470 | this_binding->unwind.func (this_binding->unwind.arg); | 3480 | this_binding->unwind.func (this_binding->unwind.arg); |
| 3471 | break; | 3481 | break; |
| 3482 | case SPECPDL_UNWIND_ARRAY: | ||
| 3483 | xfree (this_binding->unwind_array.array); | ||
| 3484 | break; | ||
| 3472 | case SPECPDL_UNWIND_PTR: | 3485 | case SPECPDL_UNWIND_PTR: |
| 3473 | this_binding->unwind_ptr.func (this_binding->unwind_ptr.arg); | 3486 | this_binding->unwind_ptr.func (this_binding->unwind_ptr.arg); |
| 3474 | break; | 3487 | break; |
| @@ -3771,6 +3784,7 @@ backtrace_eval_unrewind (int distance) | |||
| 3771 | save_excursion_restore (marker, window); | 3784 | save_excursion_restore (marker, window); |
| 3772 | } | 3785 | } |
| 3773 | break; | 3786 | break; |
| 3787 | case SPECPDL_UNWIND_ARRAY: | ||
| 3774 | case SPECPDL_UNWIND_PTR: | 3788 | case SPECPDL_UNWIND_PTR: |
| 3775 | case SPECPDL_UNWIND_INT: | 3789 | case SPECPDL_UNWIND_INT: |
| 3776 | case SPECPDL_UNWIND_VOID: | 3790 | case SPECPDL_UNWIND_VOID: |
| @@ -3903,6 +3917,7 @@ NFRAMES and BASE specify the activation frame to use, as in `backtrace-frame'. | |||
| 3903 | break; | 3917 | break; |
| 3904 | 3918 | ||
| 3905 | case SPECPDL_UNWIND: | 3919 | case SPECPDL_UNWIND: |
| 3920 | case SPECPDL_UNWIND_ARRAY: | ||
| 3906 | case SPECPDL_UNWIND_PTR: | 3921 | case SPECPDL_UNWIND_PTR: |
| 3907 | case SPECPDL_UNWIND_INT: | 3922 | case SPECPDL_UNWIND_INT: |
| 3908 | case SPECPDL_UNWIND_EXCURSION: | 3923 | case SPECPDL_UNWIND_EXCURSION: |
| @@ -3935,6 +3950,10 @@ mark_specpdl (union specbinding *first, union specbinding *ptr) | |||
| 3935 | mark_object (specpdl_arg (pdl)); | 3950 | mark_object (specpdl_arg (pdl)); |
| 3936 | break; | 3951 | break; |
| 3937 | 3952 | ||
| 3953 | case SPECPDL_UNWIND_ARRAY: | ||
| 3954 | mark_maybe_objects (pdl->unwind_array.array, pdl->unwind_array.nelts); | ||
| 3955 | break; | ||
| 3956 | |||
| 3938 | case SPECPDL_UNWIND_EXCURSION: | 3957 | case SPECPDL_UNWIND_EXCURSION: |
| 3939 | mark_object (pdl->unwind_excursion.marker); | 3958 | mark_object (pdl->unwind_excursion.marker); |
| 3940 | mark_object (pdl->unwind_excursion.window); | 3959 | mark_object (pdl->unwind_excursion.window); |
diff --git a/src/lisp.h b/src/lisp.h index af3f587222d..f02b50bad75 100644 --- a/src/lisp.h +++ b/src/lisp.h | |||
| @@ -3186,6 +3186,8 @@ extern void defvar_kboard (struct Lisp_Kboard_Objfwd *, const char *, int); | |||
| 3186 | 3186 | ||
| 3187 | enum specbind_tag { | 3187 | enum specbind_tag { |
| 3188 | SPECPDL_UNWIND, /* An unwind_protect function on Lisp_Object. */ | 3188 | SPECPDL_UNWIND, /* An unwind_protect function on Lisp_Object. */ |
| 3189 | SPECPDL_UNWIND_ARRAY, /* Likewise, on an array that needs freeing. | ||
| 3190 | Its elements are potential Lisp_Objects. */ | ||
| 3189 | SPECPDL_UNWIND_PTR, /* Likewise, on void *. */ | 3191 | SPECPDL_UNWIND_PTR, /* Likewise, on void *. */ |
| 3190 | SPECPDL_UNWIND_INT, /* Likewise, on int. */ | 3192 | SPECPDL_UNWIND_INT, /* Likewise, on int. */ |
| 3191 | SPECPDL_UNWIND_EXCURSION, /* Likewise, on an execursion. */ | 3193 | SPECPDL_UNWIND_EXCURSION, /* Likewise, on an execursion. */ |
| @@ -3207,6 +3209,12 @@ union specbinding | |||
| 3207 | } unwind; | 3209 | } unwind; |
| 3208 | struct { | 3210 | struct { |
| 3209 | ENUM_BF (specbind_tag) kind : CHAR_BIT; | 3211 | ENUM_BF (specbind_tag) kind : CHAR_BIT; |
| 3212 | void (*func) (Lisp_Object); | ||
| 3213 | Lisp_Object *array; | ||
| 3214 | ptrdiff_t nelts; | ||
| 3215 | } unwind_array; | ||
| 3216 | struct { | ||
| 3217 | ENUM_BF (specbind_tag) kind : CHAR_BIT; | ||
| 3210 | void (*func) (void *); | 3218 | void (*func) (void *); |
| 3211 | void *arg; | 3219 | void *arg; |
| 3212 | } unwind_ptr; | 3220 | } unwind_ptr; |
| @@ -3702,6 +3710,7 @@ extern void refill_memory_reserve (void); | |||
| 3702 | #endif | 3710 | #endif |
| 3703 | extern void alloc_unexec_pre (void); | 3711 | extern void alloc_unexec_pre (void); |
| 3704 | extern void alloc_unexec_post (void); | 3712 | extern void alloc_unexec_post (void); |
| 3713 | extern void mark_maybe_objects (Lisp_Object *, ptrdiff_t); | ||
| 3705 | extern void mark_stack (char *, char *); | 3714 | extern void mark_stack (char *, char *); |
| 3706 | extern void flush_stack_call_func (void (*func) (void *arg), void *arg); | 3715 | extern void flush_stack_call_func (void (*func) (void *arg), void *arg); |
| 3707 | extern const char *pending_malloc_warning; | 3716 | extern const char *pending_malloc_warning; |
| @@ -4016,6 +4025,7 @@ extern struct handler *push_handler (Lisp_Object, enum handlertype); | |||
| 4016 | extern struct handler *push_handler_nosignal (Lisp_Object, enum handlertype); | 4025 | extern struct handler *push_handler_nosignal (Lisp_Object, enum handlertype); |
| 4017 | extern void specbind (Lisp_Object, Lisp_Object); | 4026 | extern void specbind (Lisp_Object, Lisp_Object); |
| 4018 | extern void record_unwind_protect (void (*) (Lisp_Object), Lisp_Object); | 4027 | extern void record_unwind_protect (void (*) (Lisp_Object), Lisp_Object); |
| 4028 | extern void record_unwind_protect_array (Lisp_Object *, ptrdiff_t); | ||
| 4019 | extern void record_unwind_protect_ptr (void (*) (void *), void *); | 4029 | extern void record_unwind_protect_ptr (void (*) (void *), void *); |
| 4020 | extern void record_unwind_protect_int (void (*) (int), int); | 4030 | extern void record_unwind_protect_int (void (*) (int), int); |
| 4021 | extern void record_unwind_protect_void (void (*) (void)); | 4031 | extern void record_unwind_protect_void (void (*) (void)); |
| @@ -4710,11 +4720,9 @@ extern void *record_xmalloc (size_t) ATTRIBUTE_ALLOC_SIZE ((1)); | |||
| 4710 | (buf) = AVAIL_ALLOCA (alloca_nbytes); \ | 4720 | (buf) = AVAIL_ALLOCA (alloca_nbytes); \ |
| 4711 | else \ | 4721 | else \ |
| 4712 | { \ | 4722 | { \ |
| 4713 | Lisp_Object arg_; \ | ||
| 4714 | (buf) = xmalloc (alloca_nbytes); \ | 4723 | (buf) = xmalloc (alloca_nbytes); \ |
| 4715 | arg_ = make_save_memory (buf, nelt); \ | 4724 | record_unwind_protect_array (buf, nelt); \ |
| 4716 | sa_must_free = true; \ | 4725 | sa_must_free = true; \ |
| 4717 | record_unwind_protect (free_save_value, arg_); \ | ||
| 4718 | } \ | 4726 | } \ |
| 4719 | } while (false) | 4727 | } while (false) |
| 4720 | 4728 | ||