aboutsummaryrefslogtreecommitdiffstats
path: root/src/eval.c
diff options
context:
space:
mode:
authorEli Zaretskii2016-12-04 19:59:17 +0200
committerEli Zaretskii2016-12-04 19:59:17 +0200
commitde4624c99ea5bbe38ad5aff7b6461cc5c740d0be (patch)
tree1b57de9e769cdb695cb2cecf157b50f7dea9cfe5 /src/eval.c
parenta486fabb41cdbaa5813c2687fd4008945297d71d (diff)
parente7bde34e939451d87fb42a36195086bdbe48b5e1 (diff)
downloademacs-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.c249
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
35struct 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. */
47Lisp_Object Vrun_hooks; 47Lisp_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
52ptrdiff_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
57union 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
61union 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
65static 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
124static Lisp_Object 126static Lisp_Object
127specpdl_saved_value (union specbinding *pdl)
128{
129 eassert (pdl->kind >= SPECPDL_LET);
130 return pdl->let.saved_value;
131}
132
133static Lisp_Object
125specpdl_arg (union specbinding *pdl) 134specpdl_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
221static struct handler handlerlist_sentinel; 230/* static struct handler handlerlist_sentinel; */
222 231
223void 232void
224init_eval (void) 233init_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
3160void
3161do_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
3316void
3317rebind_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
3266static void 3333static void
3334do_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
3393void
3267do_nothing (void) 3394do_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
3470void
3471unbind_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
3393DEFUN ("special-variable-p", Fspecial_variable_p, Sspecial_variable_p, 1, 1, 0, 3485DEFUN ("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.
3395A special variable is one that will be bound dynamically, even in a 3487A 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
3714void 3806void
3715mark_specpdl (void) 3807mark_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: