diff options
| author | Stefan Monnier | 2022-02-19 14:55:39 -0500 |
|---|---|---|
| committer | Stefan Monnier | 2022-02-19 14:55:39 -0500 |
| commit | ecaedf2117cb015ad4028e4d6fc7058608c98096 (patch) | |
| tree | 41e49c535e70a67f8842f61b7acc5ce8dcb741a4 /src | |
| parent | 43237f3d27897e2a0c6de745770802d0ba40e3a5 (diff) | |
| download | emacs-ecaedf2117cb015ad4028e4d6fc7058608c98096.tar.gz emacs-ecaedf2117cb015ad4028e4d6fc7058608c98096.zip | |
(specpdl_unrewind): Fix corner case
* src/lisp.h (enum specbind_tag): New elem SPECPDL_NOP.
* src/eval.c (specpdl_unrewind): Zap entries that can't be applied any more,
and simplify.
(default_toplevel_binding, lexbound_p, Fbacktrace__locals): Simplify.
(do_one_unbind, mark_specpdl): Handle SPECPDL_NOP.
Diffstat (limited to 'src')
| -rw-r--r-- | src/eval.c | 83 | ||||
| -rw-r--r-- | src/lisp.h | 1 |
2 files changed, 17 insertions, 67 deletions
diff --git a/src/eval.c b/src/eval.c index d3342289fbb..294d79e67a0 100644 --- a/src/eval.c +++ b/src/eval.c | |||
| @@ -664,23 +664,7 @@ default_toplevel_binding (Lisp_Object symbol) | |||
| 664 | binding = pdl; | 664 | binding = pdl; |
| 665 | break; | 665 | break; |
| 666 | 666 | ||
| 667 | case SPECPDL_UNWIND: | 667 | default: break; |
| 668 | case SPECPDL_UNWIND_ARRAY: | ||
| 669 | case SPECPDL_UNWIND_PTR: | ||
| 670 | case SPECPDL_UNWIND_INT: | ||
| 671 | case SPECPDL_UNWIND_INTMAX: | ||
| 672 | case SPECPDL_UNWIND_EXCURSION: | ||
| 673 | case SPECPDL_UNWIND_VOID: | ||
| 674 | case SPECPDL_BACKTRACE: | ||
| 675 | #ifdef HAVE_MODULES | ||
| 676 | case SPECPDL_MODULE_RUNTIME: | ||
| 677 | case SPECPDL_MODULE_ENVIRONMENT: | ||
| 678 | #endif | ||
| 679 | case SPECPDL_LET_LOCAL: | ||
| 680 | break; | ||
| 681 | |||
| 682 | default: | ||
| 683 | emacs_abort (); | ||
| 684 | } | 668 | } |
| 685 | } | 669 | } |
| 686 | return binding; | 670 | return binding; |
| @@ -707,23 +691,7 @@ lexbound_p (Lisp_Object symbol) | |||
| 707 | } | 691 | } |
| 708 | break; | 692 | break; |
| 709 | 693 | ||
| 710 | case SPECPDL_UNWIND: | 694 | default: break; |
| 711 | case SPECPDL_UNWIND_ARRAY: | ||
| 712 | case SPECPDL_UNWIND_PTR: | ||
| 713 | case SPECPDL_UNWIND_INT: | ||
| 714 | case SPECPDL_UNWIND_INTMAX: | ||
| 715 | case SPECPDL_UNWIND_EXCURSION: | ||
| 716 | case SPECPDL_UNWIND_VOID: | ||
| 717 | case SPECPDL_BACKTRACE: | ||
| 718 | #ifdef HAVE_MODULES | ||
| 719 | case SPECPDL_MODULE_RUNTIME: | ||
| 720 | case SPECPDL_MODULE_ENVIRONMENT: | ||
| 721 | #endif | ||
| 722 | case SPECPDL_LET_LOCAL: | ||
| 723 | break; | ||
| 724 | |||
| 725 | default: | ||
| 726 | emacs_abort (); | ||
| 727 | } | 695 | } |
| 728 | } | 696 | } |
| 729 | return false; | 697 | return false; |
| @@ -3721,6 +3689,7 @@ do_one_unbind (union specbinding *this_binding, bool unwinding, | |||
| 3721 | this_binding->unwind_excursion.window); | 3689 | this_binding->unwind_excursion.window); |
| 3722 | break; | 3690 | break; |
| 3723 | case SPECPDL_BACKTRACE: | 3691 | case SPECPDL_BACKTRACE: |
| 3692 | case SPECPDL_NOP: | ||
| 3724 | break; | 3693 | break; |
| 3725 | #ifdef HAVE_MODULES | 3694 | #ifdef HAVE_MODULES |
| 3726 | case SPECPDL_MODULE_RUNTIME: | 3695 | case SPECPDL_MODULE_RUNTIME: |
| @@ -4044,17 +4013,6 @@ specpdl_unrewind (union specbinding *pdl, int distance, bool vars_only) | |||
| 4044 | save_excursion_restore (marker, window); | 4013 | save_excursion_restore (marker, window); |
| 4045 | } | 4014 | } |
| 4046 | break; | 4015 | break; |
| 4047 | case SPECPDL_UNWIND_ARRAY: | ||
| 4048 | case SPECPDL_UNWIND_PTR: | ||
| 4049 | case SPECPDL_UNWIND_INT: | ||
| 4050 | case SPECPDL_UNWIND_INTMAX: | ||
| 4051 | case SPECPDL_UNWIND_VOID: | ||
| 4052 | case SPECPDL_BACKTRACE: | ||
| 4053 | #ifdef HAVE_MODULES | ||
| 4054 | case SPECPDL_MODULE_RUNTIME: | ||
| 4055 | case SPECPDL_MODULE_ENVIRONMENT: | ||
| 4056 | #endif | ||
| 4057 | break; | ||
| 4058 | case SPECPDL_LET: | 4016 | case SPECPDL_LET: |
| 4059 | { /* If variable has a trivial value (no forwarding), we can | 4017 | { /* If variable has a trivial value (no forwarding), we can |
| 4060 | just set it. No need to check for constant symbols here, | 4018 | just set it. No need to check for constant symbols here, |
| @@ -4097,14 +4055,16 @@ specpdl_unrewind (union specbinding *pdl, int distance, bool vars_only) | |||
| 4097 | SET_INTERNAL_THREAD_SWITCH); | 4055 | SET_INTERNAL_THREAD_SWITCH); |
| 4098 | } | 4056 | } |
| 4099 | else | 4057 | else |
| 4100 | /* FIXME: If the var is not local any more, we failed | 4058 | /* If the var is not local any more, it can't be undone nor |
| 4101 | to swap the old and new values. As long as the var remains | 4059 | redone, so just zap it. |
| 4102 | non-local, this is fine, but if it ever reverts to being | 4060 | This is important in case the buffer re-gains a local value |
| 4103 | local we may end up using this entry "in the wrong | 4061 | before we unrewind again, in which case we'd risk applying |
| 4104 | direction". */ | 4062 | this entry in the wrong direction. */ |
| 4105 | {} | 4063 | tmp->kind = SPECPDL_NOP; |
| 4106 | } | 4064 | } |
| 4107 | break; | 4065 | break; |
| 4066 | |||
| 4067 | default: break; | ||
| 4108 | } | 4068 | } |
| 4109 | } | 4069 | } |
| 4110 | } | 4070 | } |
| @@ -4195,22 +4155,7 @@ NFRAMES and BASE specify the activation frame to use, as in `backtrace-frame'. | |||
| 4195 | } | 4155 | } |
| 4196 | break; | 4156 | break; |
| 4197 | 4157 | ||
| 4198 | case SPECPDL_UNWIND: | 4158 | default: break; |
| 4199 | case SPECPDL_UNWIND_ARRAY: | ||
| 4200 | case SPECPDL_UNWIND_PTR: | ||
| 4201 | case SPECPDL_UNWIND_INT: | ||
| 4202 | case SPECPDL_UNWIND_INTMAX: | ||
| 4203 | case SPECPDL_UNWIND_EXCURSION: | ||
| 4204 | case SPECPDL_UNWIND_VOID: | ||
| 4205 | case SPECPDL_BACKTRACE: | ||
| 4206 | #ifdef HAVE_MODULES | ||
| 4207 | case SPECPDL_MODULE_RUNTIME: | ||
| 4208 | case SPECPDL_MODULE_ENVIRONMENT: | ||
| 4209 | #endif | ||
| 4210 | break; | ||
| 4211 | |||
| 4212 | default: | ||
| 4213 | emacs_abort (); | ||
| 4214 | } | 4159 | } |
| 4215 | } | 4160 | } |
| 4216 | } | 4161 | } |
| @@ -4274,8 +4219,12 @@ mark_specpdl (union specbinding *first, union specbinding *ptr) | |||
| 4274 | case SPECPDL_UNWIND_INT: | 4219 | case SPECPDL_UNWIND_INT: |
| 4275 | case SPECPDL_UNWIND_INTMAX: | 4220 | case SPECPDL_UNWIND_INTMAX: |
| 4276 | case SPECPDL_UNWIND_VOID: | 4221 | case SPECPDL_UNWIND_VOID: |
| 4222 | case SPECPDL_NOP: | ||
| 4277 | break; | 4223 | break; |
| 4278 | 4224 | ||
| 4225 | /* While other loops that scan the specpdl use "default: break;" | ||
| 4226 | for simplicity, here we explicitly list all cases and abort | ||
| 4227 | if we find an unexpected value, as a sanity check. */ | ||
| 4279 | default: | 4228 | default: |
| 4280 | emacs_abort (); | 4229 | emacs_abort (); |
| 4281 | } | 4230 | } |
diff --git a/src/lisp.h b/src/lisp.h index 19788ef07cc..deeca9bc86b 100644 --- a/src/lisp.h +++ b/src/lisp.h | |||
| @@ -3284,6 +3284,7 @@ enum specbind_tag { | |||
| 3284 | SPECPDL_UNWIND_EXCURSION, /* Likewise, on an excursion. */ | 3284 | SPECPDL_UNWIND_EXCURSION, /* Likewise, on an excursion. */ |
| 3285 | SPECPDL_UNWIND_VOID, /* Likewise, with no arg. */ | 3285 | SPECPDL_UNWIND_VOID, /* Likewise, with no arg. */ |
| 3286 | SPECPDL_BACKTRACE, /* An element of the backtrace. */ | 3286 | SPECPDL_BACKTRACE, /* An element of the backtrace. */ |
| 3287 | SPECPDL_NOP, /* A filler. */ | ||
| 3287 | #ifdef HAVE_MODULES | 3288 | #ifdef HAVE_MODULES |
| 3288 | SPECPDL_MODULE_RUNTIME, /* A live module runtime. */ | 3289 | SPECPDL_MODULE_RUNTIME, /* A live module runtime. */ |
| 3289 | SPECPDL_MODULE_ENVIRONMENT, /* A live module environment. */ | 3290 | SPECPDL_MODULE_ENVIRONMENT, /* A live module environment. */ |