diff options
| author | Eli Zaretskii | 2016-12-04 19:59:17 +0200 |
|---|---|---|
| committer | Eli Zaretskii | 2016-12-04 19:59:17 +0200 |
| commit | de4624c99ea5bbe38ad5aff7b6461cc5c740d0be (patch) | |
| tree | 1b57de9e769cdb695cb2cecf157b50f7dea9cfe5 /src/eval.c | |
| parent | a486fabb41cdbaa5813c2687fd4008945297d71d (diff) | |
| parent | e7bde34e939451d87fb42a36195086bdbe48b5e1 (diff) | |
| download | emacs-de4624c99ea5bbe38ad5aff7b6461cc5c740d0be.tar.gz emacs-de4624c99ea5bbe38ad5aff7b6461cc5c740d0be.zip | |
Merge branch 'concurrency'
Conflicts (resolved):
configure.ac
src/Makefile.in
src/alloc.c
src/bytecode.c
src/emacs.c
src/eval.c
src/lisp.h
src/process.c
src/regex.c
src/regex.h
Diffstat (limited to 'src/eval.c')
| -rw-r--r-- | src/eval.c | 249 |
1 files changed, 171 insertions, 78 deletions
diff --git a/src/eval.c b/src/eval.c index 724f0018a58..c08f93aee0c 100644 --- a/src/eval.c +++ b/src/eval.c | |||
| @@ -32,7 +32,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 32 | 32 | ||
| 33 | /* Chain of condition and catch handlers currently in effect. */ | 33 | /* Chain of condition and catch handlers currently in effect. */ |
| 34 | 34 | ||
| 35 | struct handler *handlerlist; | 35 | /* struct handler *handlerlist; */ |
| 36 | 36 | ||
| 37 | /* Non-nil means record all fset's and provide's, to be undone | 37 | /* Non-nil means record all fset's and provide's, to be undone |
| 38 | if the file being autoloaded is not fully loaded. | 38 | if the file being autoloaded is not fully loaded. |
| @@ -46,23 +46,25 @@ Lisp_Object Vautoload_queue; | |||
| 46 | is shutting down. */ | 46 | is shutting down. */ |
| 47 | Lisp_Object Vrun_hooks; | 47 | Lisp_Object Vrun_hooks; |
| 48 | 48 | ||
| 49 | /* The commented-out variables below are macros defined in thread.h. */ | ||
| 50 | |||
| 49 | /* Current number of specbindings allocated in specpdl, not counting | 51 | /* Current number of specbindings allocated in specpdl, not counting |
| 50 | the dummy entry specpdl[-1]. */ | 52 | the dummy entry specpdl[-1]. */ |
| 51 | 53 | ||
| 52 | ptrdiff_t specpdl_size; | 54 | /* ptrdiff_t specpdl_size; */ |
| 53 | 55 | ||
| 54 | /* Pointer to beginning of specpdl. A dummy entry specpdl[-1] exists | 56 | /* Pointer to beginning of specpdl. A dummy entry specpdl[-1] exists |
| 55 | only so that its address can be taken. */ | 57 | only so that its address can be taken. */ |
| 56 | 58 | ||
| 57 | union specbinding *specpdl; | 59 | /* union specbinding *specpdl; */ |
| 58 | 60 | ||
| 59 | /* Pointer to first unused element in specpdl. */ | 61 | /* Pointer to first unused element in specpdl. */ |
| 60 | 62 | ||
| 61 | union specbinding *specpdl_ptr; | 63 | /* union specbinding *specpdl_ptr; */ |
| 62 | 64 | ||
| 63 | /* Depth in Lisp evaluations and function calls. */ | 65 | /* Depth in Lisp evaluations and function calls. */ |
| 64 | 66 | ||
| 65 | static EMACS_INT lisp_eval_depth; | 67 | /* static EMACS_INT lisp_eval_depth; */ |
| 66 | 68 | ||
| 67 | /* The value of num_nonmacro_input_events as of the last time we | 69 | /* The value of num_nonmacro_input_events as of the last time we |
| 68 | started to enter the debugger. If we decide to enter the debugger | 70 | started to enter the debugger. If we decide to enter the debugger |
| @@ -122,6 +124,13 @@ specpdl_where (union specbinding *pdl) | |||
| 122 | } | 124 | } |
| 123 | 125 | ||
| 124 | static Lisp_Object | 126 | static Lisp_Object |
| 127 | specpdl_saved_value (union specbinding *pdl) | ||
| 128 | { | ||
| 129 | eassert (pdl->kind >= SPECPDL_LET); | ||
| 130 | return pdl->let.saved_value; | ||
| 131 | } | ||
| 132 | |||
| 133 | static Lisp_Object | ||
| 125 | specpdl_arg (union specbinding *pdl) | 134 | specpdl_arg (union specbinding *pdl) |
| 126 | { | 135 | { |
| 127 | eassert (pdl->kind == SPECPDL_UNWIND); | 136 | eassert (pdl->kind == SPECPDL_UNWIND); |
| @@ -218,20 +227,22 @@ init_eval_once (void) | |||
| 218 | Vrun_hooks = Qnil; | 227 | Vrun_hooks = Qnil; |
| 219 | } | 228 | } |
| 220 | 229 | ||
| 221 | static struct handler handlerlist_sentinel; | 230 | /* static struct handler handlerlist_sentinel; */ |
| 222 | 231 | ||
| 223 | void | 232 | void |
| 224 | init_eval (void) | 233 | init_eval (void) |
| 225 | { | 234 | { |
| 235 | byte_stack_list = 0; | ||
| 226 | specpdl_ptr = specpdl; | 236 | specpdl_ptr = specpdl; |
| 227 | { /* Put a dummy catcher at top-level so that handlerlist is never NULL. | 237 | { /* Put a dummy catcher at top-level so that handlerlist is never NULL. |
| 228 | This is important since handlerlist->nextfree holds the freelist | 238 | This is important since handlerlist->nextfree holds the freelist |
| 229 | which would otherwise leak every time we unwind back to top-level. */ | 239 | which would otherwise leak every time we unwind back to top-level. */ |
| 230 | handlerlist = handlerlist_sentinel.nextfree = &handlerlist_sentinel; | 240 | handlerlist_sentinel = xzalloc (sizeof (struct handler)); |
| 241 | handlerlist = handlerlist_sentinel->nextfree = handlerlist_sentinel; | ||
| 231 | struct handler *c = push_handler (Qunbound, CATCHER); | 242 | struct handler *c = push_handler (Qunbound, CATCHER); |
| 232 | eassert (c == &handlerlist_sentinel); | 243 | eassert (c == handlerlist_sentinel); |
| 233 | handlerlist_sentinel.nextfree = NULL; | 244 | handlerlist_sentinel->nextfree = NULL; |
| 234 | handlerlist_sentinel.next = NULL; | 245 | handlerlist_sentinel->next = NULL; |
| 235 | } | 246 | } |
| 236 | Vquit_flag = Qnil; | 247 | Vquit_flag = Qnil; |
| 237 | debug_on_next_call = 0; | 248 | debug_on_next_call = 0; |
| @@ -1138,7 +1149,8 @@ unwind_to_catch (struct handler *catch, Lisp_Object value) | |||
| 1138 | 1149 | ||
| 1139 | eassert (handlerlist == catch); | 1150 | eassert (handlerlist == catch); |
| 1140 | 1151 | ||
| 1141 | lisp_eval_depth = catch->lisp_eval_depth; | 1152 | byte_stack_list = catch->byte_stack; |
| 1153 | lisp_eval_depth = catch->f_lisp_eval_depth; | ||
| 1142 | 1154 | ||
| 1143 | sys_longjmp (catch->jmp, 1); | 1155 | sys_longjmp (catch->jmp, 1); |
| 1144 | } | 1156 | } |
| @@ -1432,6 +1444,7 @@ push_handler_nosignal (Lisp_Object tag_ch_val, enum handlertype handlertype) | |||
| 1432 | c->pdlcount = SPECPDL_INDEX (); | 1444 | c->pdlcount = SPECPDL_INDEX (); |
| 1433 | c->poll_suppress_count = poll_suppress_count; | 1445 | c->poll_suppress_count = poll_suppress_count; |
| 1434 | c->interrupt_input_blocked = interrupt_input_blocked; | 1446 | c->interrupt_input_blocked = interrupt_input_blocked; |
| 1447 | c->byte_stack = byte_stack_list; | ||
| 1435 | handlerlist = c; | 1448 | handlerlist = c; |
| 1436 | return c; | 1449 | return c; |
| 1437 | } | 1450 | } |
| @@ -1581,7 +1594,7 @@ signal_or_quit (Lisp_Object error_symbol, Lisp_Object data, bool keyboard_quit) | |||
| 1581 | } | 1594 | } |
| 1582 | else | 1595 | else |
| 1583 | { | 1596 | { |
| 1584 | if (handlerlist != &handlerlist_sentinel) | 1597 | if (handlerlist != handlerlist_sentinel) |
| 1585 | /* FIXME: This will come right back here if there's no `top-level' | 1598 | /* FIXME: This will come right back here if there's no `top-level' |
| 1586 | catcher. A better solution would be to abort here, and instead | 1599 | catcher. A better solution would be to abort here, and instead |
| 1587 | add a catch-all condition handler so we never come here. */ | 1600 | add a catch-all condition handler so we never come here. */ |
| @@ -3144,6 +3157,44 @@ let_shadows_global_binding_p (Lisp_Object symbol) | |||
| 3144 | return 0; | 3157 | return 0; |
| 3145 | } | 3158 | } |
| 3146 | 3159 | ||
| 3160 | void | ||
| 3161 | do_specbind (struct Lisp_Symbol *sym, union specbinding *bind, | ||
| 3162 | Lisp_Object value) | ||
| 3163 | { | ||
| 3164 | switch (sym->redirect) | ||
| 3165 | { | ||
| 3166 | case SYMBOL_PLAINVAL: | ||
| 3167 | if (!sym->trapped_write) | ||
| 3168 | SET_SYMBOL_VAL (sym, value); | ||
| 3169 | else | ||
| 3170 | set_internal (specpdl_symbol (bind), value, Qnil, SET_INTERNAL_BIND); | ||
| 3171 | break; | ||
| 3172 | |||
| 3173 | case SYMBOL_LOCALIZED: | ||
| 3174 | case SYMBOL_FORWARDED: | ||
| 3175 | if ((sym->redirect == SYMBOL_LOCALIZED | ||
| 3176 | || BUFFER_OBJFWDP (SYMBOL_FWD (sym))) | ||
| 3177 | && CONSP (specpdl_symbol (bind))) | ||
| 3178 | { | ||
| 3179 | Lisp_Object where; | ||
| 3180 | |||
| 3181 | where = XCAR (XCDR (specpdl_symbol (bind))); | ||
| 3182 | if (NILP (where) | ||
| 3183 | && sym->redirect == SYMBOL_FORWARDED) | ||
| 3184 | { | ||
| 3185 | Fset_default (XCAR (specpdl_symbol (bind)), value); | ||
| 3186 | return; | ||
| 3187 | } | ||
| 3188 | } | ||
| 3189 | |||
| 3190 | set_internal (specpdl_symbol (bind), value, Qnil, SET_INTERNAL_BIND); | ||
| 3191 | break; | ||
| 3192 | |||
| 3193 | default: | ||
| 3194 | emacs_abort (); | ||
| 3195 | } | ||
| 3196 | } | ||
| 3197 | |||
| 3147 | /* `specpdl_ptr' describes which variable is | 3198 | /* `specpdl_ptr' describes which variable is |
| 3148 | let-bound, so it can be properly undone when we unbind_to. | 3199 | let-bound, so it can be properly undone when we unbind_to. |
| 3149 | It can be either a plain SPECPDL_LET or a SPECPDL_LET_LOCAL/DEFAULT. | 3200 | It can be either a plain SPECPDL_LET or a SPECPDL_LET_LOCAL/DEFAULT. |
| @@ -3175,11 +3226,9 @@ specbind (Lisp_Object symbol, Lisp_Object value) | |||
| 3175 | specpdl_ptr->let.kind = SPECPDL_LET; | 3226 | specpdl_ptr->let.kind = SPECPDL_LET; |
| 3176 | specpdl_ptr->let.symbol = symbol; | 3227 | specpdl_ptr->let.symbol = symbol; |
| 3177 | specpdl_ptr->let.old_value = SYMBOL_VAL (sym); | 3228 | specpdl_ptr->let.old_value = SYMBOL_VAL (sym); |
| 3229 | specpdl_ptr->let.saved_value = Qnil; | ||
| 3178 | grow_specpdl (); | 3230 | grow_specpdl (); |
| 3179 | if (!sym->trapped_write) | 3231 | do_specbind (sym, specpdl_ptr - 1, value); |
| 3180 | SET_SYMBOL_VAL (sym, value); | ||
| 3181 | else | ||
| 3182 | set_internal (symbol, value, Qnil, SET_INTERNAL_BIND); | ||
| 3183 | break; | 3232 | break; |
| 3184 | case SYMBOL_LOCALIZED: | 3233 | case SYMBOL_LOCALIZED: |
| 3185 | if (SYMBOL_BLV (sym)->frame_local) | 3234 | if (SYMBOL_BLV (sym)->frame_local) |
| @@ -3191,6 +3240,7 @@ specbind (Lisp_Object symbol, Lisp_Object value) | |||
| 3191 | specpdl_ptr->let.symbol = symbol; | 3240 | specpdl_ptr->let.symbol = symbol; |
| 3192 | specpdl_ptr->let.old_value = ovalue; | 3241 | specpdl_ptr->let.old_value = ovalue; |
| 3193 | specpdl_ptr->let.where = Fcurrent_buffer (); | 3242 | specpdl_ptr->let.where = Fcurrent_buffer (); |
| 3243 | specpdl_ptr->let.saved_value = Qnil; | ||
| 3194 | 3244 | ||
| 3195 | eassert (sym->redirect != SYMBOL_LOCALIZED | 3245 | eassert (sym->redirect != SYMBOL_LOCALIZED |
| 3196 | || (EQ (SYMBOL_BLV (sym)->where, Fcurrent_buffer ()))); | 3246 | || (EQ (SYMBOL_BLV (sym)->where, Fcurrent_buffer ()))); |
| @@ -3211,7 +3261,7 @@ specbind (Lisp_Object symbol, Lisp_Object value) | |||
| 3211 | { | 3261 | { |
| 3212 | specpdl_ptr->let.kind = SPECPDL_LET_DEFAULT; | 3262 | specpdl_ptr->let.kind = SPECPDL_LET_DEFAULT; |
| 3213 | grow_specpdl (); | 3263 | grow_specpdl (); |
| 3214 | Fset_default (symbol, value); | 3264 | do_specbind (sym, specpdl_ptr - 1, value); |
| 3215 | return; | 3265 | return; |
| 3216 | } | 3266 | } |
| 3217 | } | 3267 | } |
| @@ -3219,7 +3269,7 @@ specbind (Lisp_Object symbol, Lisp_Object value) | |||
| 3219 | specpdl_ptr->let.kind = SPECPDL_LET; | 3269 | specpdl_ptr->let.kind = SPECPDL_LET; |
| 3220 | 3270 | ||
| 3221 | grow_specpdl (); | 3271 | grow_specpdl (); |
| 3222 | set_internal (symbol, value, Qnil, SET_INTERNAL_BIND); | 3272 | do_specbind (sym, specpdl_ptr - 1, value); |
| 3223 | break; | 3273 | break; |
| 3224 | } | 3274 | } |
| 3225 | default: emacs_abort (); | 3275 | default: emacs_abort (); |
| @@ -3263,7 +3313,84 @@ record_unwind_protect_void (void (*function) (void)) | |||
| 3263 | grow_specpdl (); | 3313 | grow_specpdl (); |
| 3264 | } | 3314 | } |
| 3265 | 3315 | ||
| 3316 | void | ||
| 3317 | rebind_for_thread_switch (void) | ||
| 3318 | { | ||
| 3319 | union specbinding *bind; | ||
| 3320 | |||
| 3321 | for (bind = specpdl; bind != specpdl_ptr; ++bind) | ||
| 3322 | { | ||
| 3323 | if (bind->kind >= SPECPDL_LET) | ||
| 3324 | { | ||
| 3325 | Lisp_Object value = specpdl_saved_value (bind); | ||
| 3326 | |||
| 3327 | bind->let.saved_value = Qnil; | ||
| 3328 | do_specbind (XSYMBOL (specpdl_symbol (bind)), bind, value); | ||
| 3329 | } | ||
| 3330 | } | ||
| 3331 | } | ||
| 3332 | |||
| 3266 | static void | 3333 | static void |
| 3334 | do_one_unbind (union specbinding *this_binding, int unwinding) | ||
| 3335 | { | ||
| 3336 | eassert (unwinding || this_binding->kind >= SPECPDL_LET); | ||
| 3337 | switch (this_binding->kind) | ||
| 3338 | { | ||
| 3339 | case SPECPDL_UNWIND: | ||
| 3340 | this_binding->unwind.func (this_binding->unwind.arg); | ||
| 3341 | break; | ||
| 3342 | case SPECPDL_UNWIND_PTR: | ||
| 3343 | this_binding->unwind_ptr.func (this_binding->unwind_ptr.arg); | ||
| 3344 | break; | ||
| 3345 | case SPECPDL_UNWIND_INT: | ||
| 3346 | this_binding->unwind_int.func (this_binding->unwind_int.arg); | ||
| 3347 | break; | ||
| 3348 | case SPECPDL_UNWIND_VOID: | ||
| 3349 | this_binding->unwind_void.func (); | ||
| 3350 | break; | ||
| 3351 | case SPECPDL_BACKTRACE: | ||
| 3352 | break; | ||
| 3353 | case SPECPDL_LET: | ||
| 3354 | { /* If variable has a trivial value (no forwarding), and isn't | ||
| 3355 | trapped we can just set it. No need to check for constant | ||
| 3356 | symbols here, since that was already done by specbind. */ | ||
| 3357 | struct Lisp_Symbol sym = specpdl_symbol (this_binding); | ||
| 3358 | if (SYMBOLP (sym) && XSYMBOL (sym)->redirect == SYMBOL_PLAINVAL) | ||
| 3359 | { | ||
| 3360 | if (XSYMBOL (sym)->trapped_write == SYMBOL_UNTRAPPED_WRITE) | ||
| 3361 | SET_SYMBOL_VAL (XSYMBOL (sym), specpdl_old_value (this_binding)); | ||
| 3362 | else | ||
| 3363 | set_internal (sym, specpdl_old_value (this_binding), | ||
| 3364 | Qnil, SET_INTERNAL_UNBIND); | ||
| 3365 | break; | ||
| 3366 | } | ||
| 3367 | else | ||
| 3368 | { /* FALLTHROUGH!! | ||
| 3369 | NOTE: we only ever come here if make_local_foo was used for | ||
| 3370 | the first time on this var within this let. */ | ||
| 3371 | } | ||
| 3372 | } | ||
| 3373 | case SPECPDL_LET_DEFAULT: | ||
| 3374 | Fset_default (specpdl_symbol (this_binding), | ||
| 3375 | specpdl_old_value (this_binding)); | ||
| 3376 | break; | ||
| 3377 | case SPECPDL_LET_LOCAL: | ||
| 3378 | { | ||
| 3379 | Lisp_Object symbol = specpdl_symbol (this_binding); | ||
| 3380 | Lisp_Object where = specpdl_where (this_binding); | ||
| 3381 | Lisp_Object old_value = specpdl_old_value (this_binding); | ||
| 3382 | eassert (BUFFERP (where)); | ||
| 3383 | |||
| 3384 | /* If this was a local binding, reset the value in the appropriate | ||
| 3385 | buffer, but only if that buffer's binding still exists. */ | ||
| 3386 | if (!NILP (Flocal_variable_p (symbol, where))) | ||
| 3387 | set_internal (symbol, old_value, where, SET_INTERNAL_UNBIND); | ||
| 3388 | } | ||
| 3389 | break; | ||
| 3390 | } | ||
| 3391 | } | ||
| 3392 | |||
| 3393 | void | ||
| 3267 | do_nothing (void) | 3394 | do_nothing (void) |
| 3268 | {} | 3395 | {} |
| 3269 | 3396 | ||
| @@ -3322,66 +3449,16 @@ unbind_to (ptrdiff_t count, Lisp_Object value) | |||
| 3322 | 3449 | ||
| 3323 | while (specpdl_ptr != specpdl + count) | 3450 | while (specpdl_ptr != specpdl + count) |
| 3324 | { | 3451 | { |
| 3325 | /* Decrement specpdl_ptr before we do the work to unbind it, so | 3452 | /* Copy the binding, and decrement specpdl_ptr, before we do |
| 3326 | that an error in unbinding won't try to unbind the same entry | 3453 | the work to unbind it. We decrement first |
| 3327 | again. Take care to copy any parts of the binding needed | 3454 | so that an error in unbinding won't try to unbind |
| 3328 | before invoking any code that can make more bindings. */ | 3455 | the same entry again, and we copy the binding first |
| 3456 | in case more bindings are made during some of the code we run. */ | ||
| 3329 | 3457 | ||
| 3330 | specpdl_ptr--; | 3458 | union specbinding this_binding; |
| 3459 | this_binding = *--specpdl_ptr; | ||
| 3331 | 3460 | ||
| 3332 | switch (specpdl_ptr->kind) | 3461 | do_one_unbind (&this_binding, 1); |
| 3333 | { | ||
| 3334 | case SPECPDL_UNWIND: | ||
| 3335 | specpdl_ptr->unwind.func (specpdl_ptr->unwind.arg); | ||
| 3336 | break; | ||
| 3337 | case SPECPDL_UNWIND_PTR: | ||
| 3338 | specpdl_ptr->unwind_ptr.func (specpdl_ptr->unwind_ptr.arg); | ||
| 3339 | break; | ||
| 3340 | case SPECPDL_UNWIND_INT: | ||
| 3341 | specpdl_ptr->unwind_int.func (specpdl_ptr->unwind_int.arg); | ||
| 3342 | break; | ||
| 3343 | case SPECPDL_UNWIND_VOID: | ||
| 3344 | specpdl_ptr->unwind_void.func (); | ||
| 3345 | break; | ||
| 3346 | case SPECPDL_BACKTRACE: | ||
| 3347 | break; | ||
| 3348 | case SPECPDL_LET: | ||
| 3349 | { /* If variable has a trivial value (no forwarding), and | ||
| 3350 | isn't trapped, we can just set it. */ | ||
| 3351 | Lisp_Object sym = specpdl_symbol (specpdl_ptr); | ||
| 3352 | if (SYMBOLP (sym) && XSYMBOL (sym)->redirect == SYMBOL_PLAINVAL) | ||
| 3353 | { | ||
| 3354 | if (XSYMBOL (sym)->trapped_write == SYMBOL_UNTRAPPED_WRITE) | ||
| 3355 | SET_SYMBOL_VAL (XSYMBOL (sym), specpdl_old_value (specpdl_ptr)); | ||
| 3356 | else | ||
| 3357 | set_internal (sym, specpdl_old_value (specpdl_ptr), | ||
| 3358 | Qnil, SET_INTERNAL_UNBIND); | ||
| 3359 | break; | ||
| 3360 | } | ||
| 3361 | else | ||
| 3362 | { /* FALLTHROUGH!! | ||
| 3363 | NOTE: we only ever come here if make_local_foo was used for | ||
| 3364 | the first time on this var within this let. */ | ||
| 3365 | } | ||
| 3366 | } | ||
| 3367 | case SPECPDL_LET_DEFAULT: | ||
| 3368 | Fset_default (specpdl_symbol (specpdl_ptr), | ||
| 3369 | specpdl_old_value (specpdl_ptr)); | ||
| 3370 | break; | ||
| 3371 | case SPECPDL_LET_LOCAL: | ||
| 3372 | { | ||
| 3373 | Lisp_Object symbol = specpdl_symbol (specpdl_ptr); | ||
| 3374 | Lisp_Object where = specpdl_where (specpdl_ptr); | ||
| 3375 | Lisp_Object old_value = specpdl_old_value (specpdl_ptr); | ||
| 3376 | eassert (BUFFERP (where)); | ||
| 3377 | |||
| 3378 | /* If this was a local binding, reset the value in the appropriate | ||
| 3379 | buffer, but only if that buffer's binding still exists. */ | ||
| 3380 | if (!NILP (Flocal_variable_p (symbol, where))) | ||
| 3381 | set_internal (symbol, old_value, where, SET_INTERNAL_UNBIND); | ||
| 3382 | } | ||
| 3383 | break; | ||
| 3384 | } | ||
| 3385 | } | 3462 | } |
| 3386 | 3463 | ||
| 3387 | if (NILP (Vquit_flag) && !NILP (quitf)) | 3464 | if (NILP (Vquit_flag) && !NILP (quitf)) |
| @@ -3390,6 +3467,21 @@ unbind_to (ptrdiff_t count, Lisp_Object value) | |||
| 3390 | return value; | 3467 | return value; |
| 3391 | } | 3468 | } |
| 3392 | 3469 | ||
| 3470 | void | ||
| 3471 | unbind_for_thread_switch (struct thread_state *thr) | ||
| 3472 | { | ||
| 3473 | union specbinding *bind; | ||
| 3474 | |||
| 3475 | for (bind = thr->m_specpdl_ptr; bind > thr->m_specpdl;) | ||
| 3476 | { | ||
| 3477 | if ((--bind)->kind >= SPECPDL_LET) | ||
| 3478 | { | ||
| 3479 | bind->let.saved_value = find_symbol_value (specpdl_symbol (bind)); | ||
| 3480 | do_one_unbind (bind, 0); | ||
| 3481 | } | ||
| 3482 | } | ||
| 3483 | } | ||
| 3484 | |||
| 3393 | DEFUN ("special-variable-p", Fspecial_variable_p, Sspecial_variable_p, 1, 1, 0, | 3485 | DEFUN ("special-variable-p", Fspecial_variable_p, Sspecial_variable_p, 1, 1, 0, |
| 3394 | doc: /* Return non-nil if SYMBOL's global binding has been declared special. | 3486 | doc: /* Return non-nil if SYMBOL's global binding has been declared special. |
| 3395 | A special variable is one that will be bound dynamically, even in a | 3487 | A special variable is one that will be bound dynamically, even in a |
| @@ -3712,10 +3804,10 @@ NFRAMES and BASE specify the activation frame to use, as in `backtrace-frame'. | |||
| 3712 | 3804 | ||
| 3713 | 3805 | ||
| 3714 | void | 3806 | void |
| 3715 | mark_specpdl (void) | 3807 | mark_specpdl (union specbinding *first, union specbinding *ptr) |
| 3716 | { | 3808 | { |
| 3717 | union specbinding *pdl; | 3809 | union specbinding *pdl; |
| 3718 | for (pdl = specpdl; pdl != specpdl_ptr; pdl++) | 3810 | for (pdl = first; pdl != ptr; pdl++) |
| 3719 | { | 3811 | { |
| 3720 | switch (pdl->kind) | 3812 | switch (pdl->kind) |
| 3721 | { | 3813 | { |
| @@ -3741,6 +3833,7 @@ mark_specpdl (void) | |||
| 3741 | case SPECPDL_LET: | 3833 | case SPECPDL_LET: |
| 3742 | mark_object (specpdl_symbol (pdl)); | 3834 | mark_object (specpdl_symbol (pdl)); |
| 3743 | mark_object (specpdl_old_value (pdl)); | 3835 | mark_object (specpdl_old_value (pdl)); |
| 3836 | mark_object (specpdl_saved_value (pdl)); | ||
| 3744 | break; | 3837 | break; |
| 3745 | 3838 | ||
| 3746 | case SPECPDL_UNWIND_PTR: | 3839 | case SPECPDL_UNWIND_PTR: |