aboutsummaryrefslogtreecommitdiffstats
path: root/src/bytecode.c
diff options
context:
space:
mode:
authorEli Zaretskii2016-12-10 18:54:43 +0200
committerEli Zaretskii2016-12-10 18:54:43 +0200
commit2412a1fc05fe9f89b171d0781c2d530923f48adc (patch)
treed42a5d2608e65a10b1cc23c6b4609d54bef25d49 /src/bytecode.c
parentfc0fd24c105bde4c001ebebe4b8b7e1f96cd2871 (diff)
parent828b4560cd4a0d8cb9b7a7a3e20ff0c53ba86cfa (diff)
downloademacs-2412a1fc05fe9f89b171d0781c2d530923f48adc.tar.gz
emacs-2412a1fc05fe9f89b171d0781c2d530923f48adc.zip
Support concurrency in Emacs Lisp
Merge branch 'test-concurrency' * src/thread.c: * src/thread.h: * src/systhread.c: * src/systhread.h: New files. * src/xgselect.c (xg_select): Avoid using SAFE_NALLOCA and use xnmalloc unconditionally. * src/window.c (struct save_window_data): Rename current_buffer to f_current_buffer. * src/w32proc.c (sys_select): Change the function signature to closer fit 'pselect' on Posix hosts. * src/search.c: * src/regex.h: Convert some globals to macros that reference thread-specific values. * src/process.c (pset_thread, add_non_keyboard_read_fd) (add_process_read_fd, add_non_blocking_write_fd) (recompute_input_desc, compute_input_wait_mask) (compute_non_process_wait_mask, compute_non_keyboard_wait_mask) (compute_write_mask, clear_waiting_thread_info) (update_processes_for_thread_death, Fset_process_thread) (Fprocess_thread): New functions. (enum fd_bits): New enumeration. (fd_callback_data): Add 'thread' and 'waiting_thread', rename 'condition' to 'flags'. (set_process_filter_masks, create_process, create_pty) (Fmake_serial_process, finish_after_tls_connection) (connect_network_socket, deactivate_process) (server_accept_connection, wait_reading_process_output) (Fcontinue_process, Fstop_process, keyboard_bit_set) (add_timer_wait_descriptor, add_keyboard_wait_descriptor) (delete_keyboard_wait_descriptor): Use the new functions instead of manipulating fd flags and masks directly. (syms_of_process): Defsubr the new primitives. * src/print.c (print_object): Print threads, mutexes, and conditional variables. * src/lisp.h (enum pvec_type): New values PVEC_THREAD, PVEC_MUTEX, and PVEC_CONDVAR. (XTHREAD, XMUTEX, XCONDVAR, THREADP, MUTEXP, CONDVARP) (CHECK_THREAD, CHECK_MUTEX, CHECK_CONDVAR): New inline functions. (XSETTHREAD, XSETMUTEX, XSETCONDVAR): New macros. (struct handler): Add back byte_stack. Rename lisp_eval_depth to f_lisp_eval_depth. * src/eval.c (specpdl_kind, specpdl_arg, do_specbind) (rebind_for_thread_switch, do_one_unbind) (unbind_for_thread_switch): New functions. (init_eval): 'handlerlist' is not malloc'ed. (specbind): Call do_specbind. (unbind_to): Call do_one_unbind. (mark_specpdl): Accept 2 arguments. (mark_specpdl): Mark the saved value in a let-binding. * src/emacs.c (main): Call init_threads_once, init_threads, and syms_of_threads. * src/data.c (Ftype_of): Support thread, mutex, and condvar objects. (Fthreadp, Fmutexp, Fcondition_variable_p): New functions. (syms_of_data): DEFSYM and defsubr new symbols and primitives. * src/bytecode.c (struct byte_stack, FETCH, CHECK_RANGE) (BYTE_CODE_QUIT): Add back. (exec_byte_code): Add back byte stack manipulation. * src/alloc.c (cleanup_vector): Handle threads, mutexes, and conditional variables. (mark_stack): Now extern; accept additional argument 'bottom'. (flush_stack_call_func): New function. (garbage_collect_1): Call mark_threads and unmark_threads. Don't mark handlers. * src/.gdbinit (xbytecode): Add back. * test/src/thread-tests.el: New tests. * test/src/data-tests.el (binding-test-manual) (binding-test-setq-default, binding-test-makunbound) (binding-test-defvar-bool, binding-test-defvar-int) (binding-test-set-constant-t, binding-test-set-constant-nil) (binding-test-set-constant-keyword) (binding-test-set-constant-nil): New tests. * doc/lispref/processes.texi (Processes and Threads): New subsection. * doc/lispref/threads.texi: New file * doc/lispref/elisp.texi (Top): Include it. * doc/lispref/objects.texi (Thread Type, Mutex Type) (Condition Variable Type): New subsections. (Type Predicates): Add thread-related predicates. * doc/lispref/objects.texi (Editing Types): * doc/lispref/elisp.texi (Top): Update higher-level menus. * etc/NEWS: Mention concurrency features.
Diffstat (limited to 'src/bytecode.c')
-rw-r--r--src/bytecode.c203
1 files changed, 155 insertions, 48 deletions
diff --git a/src/bytecode.c b/src/bytecode.c
index 71ecdbf2cc0..c581ed6d982 100644
--- a/src/bytecode.c
+++ b/src/bytecode.c
@@ -280,10 +280,68 @@ enum byte_code_op
280 Bset_mark = 0163, /* this loser is no longer generated as of v18 */ 280 Bset_mark = 0163, /* this loser is no longer generated as of v18 */
281#endif 281#endif
282}; 282};
283
284/* Whether to maintain a `top' and `bottom' field in the stack frame. */
285#define BYTE_MAINTAIN_TOP BYTE_CODE_SAFE
283 286
284/* Fetch the next byte from the bytecode stream. */ 287/* Structure describing a value stack used during byte-code execution
288 in Fbyte_code. */
289
290struct byte_stack
291{
292 /* Program counter. This points into the byte_string below
293 and is relocated when that string is relocated. */
294 const unsigned char *pc;
295
296 /* Top and bottom of stack. The bottom points to an area of memory
297 allocated with alloca in Fbyte_code. */
298#if BYTE_MAINTAIN_TOP
299 Lisp_Object *top, *bottom;
300#endif
301
302 /* The string containing the byte-code, and its current address.
303 Storing this here protects it from GC because mark_byte_stack
304 marks it. */
305 Lisp_Object byte_string;
306 const unsigned char *byte_string_start;
307
308 /* Next entry in byte_stack_list. */
309 struct byte_stack *next;
310};
311
312/* A list of currently active byte-code execution value stacks.
313 Fbyte_code adds an entry to the head of this list before it starts
314 processing byte-code, and it removes the entry again when it is
315 done. Signaling an error truncates the list.
316
317 byte_stack_list is a macro defined in thread.h. */
318/* struct byte_stack *byte_stack_list; */
319
320
321/* Relocate program counters in the stacks on byte_stack_list. Called
322 when GC has completed. */
323
324void
325relocate_byte_stack (struct byte_stack *stack)
326{
327 for (; stack; stack = stack->next)
328 {
329 if (stack->byte_string_start != SDATA (stack->byte_string))
330 {
331 ptrdiff_t offset = stack->pc - stack->byte_string_start;
332 stack->byte_string_start = SDATA (stack->byte_string);
333 stack->pc = stack->byte_string_start + offset;
334 }
335 }
336}
285 337
286#define FETCH (*pc++) 338
339/* Fetch the next byte from the bytecode stream. */
340#ifdef BYTE_CODE_SAFE
341#define FETCH (eassert (stack.byte_string_start == SDATA (stack.byte_string)), *stack.pc++)
342#else
343#define FETCH *stack.pc++
344#endif
287 345
288/* Fetch two bytes from the bytecode stream and make a 16-bit number 346/* Fetch two bytes from the bytecode stream and make a 16-bit number
289 out of them. */ 347 out of them. */
@@ -308,6 +366,29 @@ enum byte_code_op
308 366
309#define TOP (*top) 367#define TOP (*top)
310 368
369#define CHECK_RANGE(ARG) \
370 (BYTE_CODE_SAFE && bytestr_length <= (ARG) ? emacs_abort () : (void) 0)
371
372/* A version of the QUIT macro which makes sure that the stack top is
373 set before signaling `quit'. */
374#define BYTE_CODE_QUIT \
375 do { \
376 if (quitcounter++) \
377 break; \
378 maybe_gc (); \
379 if (!NILP (Vquit_flag) && NILP (Vinhibit_quit)) \
380 { \
381 Lisp_Object flag = Vquit_flag; \
382 Vquit_flag = Qnil; \
383 if (EQ (Vthrow_on_input, flag)) \
384 Fthrow (Vthrow_on_input, Qt); \
385 quit (); \
386 } \
387 else if (pending_signals) \
388 process_pending_signals (); \
389 } while (0)
390
391
311DEFUN ("byte-code", Fbyte_code, Sbyte_code, 3, 3, 0, 392DEFUN ("byte-code", Fbyte_code, Sbyte_code, 3, 3, 0,
312 doc: /* Function used internally in byte-compiled code. 393 doc: /* Function used internally in byte-compiled code.
313The first argument, BYTESTR, is a string of byte code; 394The first argument, BYTESTR, is a string of byte code;
@@ -357,18 +438,19 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth,
357 438
358 ptrdiff_t bytestr_length = SBYTES (bytestr); 439 ptrdiff_t bytestr_length = SBYTES (bytestr);
359 Lisp_Object *vectorp = XVECTOR (vector)->contents; 440 Lisp_Object *vectorp = XVECTOR (vector)->contents;
441 struct byte_stack stack;
360 442
361 unsigned char quitcounter = 1; 443 stack.byte_string = bytestr;
444 stack.pc = stack.byte_string_start = SDATA (bytestr);
445 unsigned char quitcounter = 0;
362 EMACS_INT stack_items = XFASTINT (maxdepth) + 1; 446 EMACS_INT stack_items = XFASTINT (maxdepth) + 1;
363 USE_SAFE_ALLOCA; 447 USE_SAFE_ALLOCA;
364 Lisp_Object *stack_base; 448 Lisp_Object *stack_base;
365 SAFE_ALLOCA_LISP_EXTRA (stack_base, stack_items, bytestr_length); 449 SAFE_ALLOCA_LISP (stack_base, stack_items);
366 Lisp_Object *stack_lim = stack_base + stack_items; 450 Lisp_Object *stack_lim = stack_base + stack_items;
367 Lisp_Object *top = stack_base; 451 Lisp_Object *top = stack_base;
368 memcpy (stack_lim, SDATA (bytestr), bytestr_length); 452 stack.next = byte_stack_list;
369 void *void_stack_lim = stack_lim; 453 byte_stack_list = &stack;
370 unsigned char const *bytestr_data = void_stack_lim;
371 unsigned char const *pc = bytestr_data;
372 ptrdiff_t count = SPECPDL_INDEX (); 454 ptrdiff_t count = SPECPDL_INDEX ();
373 455
374 if (!NILP (args_template)) 456 if (!NILP (args_template))
@@ -508,10 +590,15 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth,
508 590
509 CASE (Bgotoifnil): 591 CASE (Bgotoifnil):
510 { 592 {
511 Lisp_Object v1 = POP; 593 Lisp_Object v1;
512 op = FETCH2; 594 op = FETCH2;
595 v1 = POP;
513 if (NILP (v1)) 596 if (NILP (v1))
514 goto op_branch; 597 {
598 BYTE_CODE_QUIT;
599 CHECK_RANGE (op);
600 stack.pc = stack.byte_string_start + op;
601 }
515 NEXT; 602 NEXT;
516 } 603 }
517 604
@@ -569,7 +656,7 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth,
569 if (SYMBOLP (sym) 656 if (SYMBOLP (sym)
570 && !EQ (val, Qunbound) 657 && !EQ (val, Qunbound)
571 && !XSYMBOL (sym)->redirect 658 && !XSYMBOL (sym)->redirect
572 && !SYMBOL_TRAPPED_WRITE_P (sym)) 659 && !SYMBOL_TRAPPED_WRITE_P (sym))
573 SET_SYMBOL_VAL (XSYMBOL (sym), val); 660 SET_SYMBOL_VAL (XSYMBOL (sym), val);
574 else 661 else
575 set_internal (sym, val, Qnil, SET_INTERNAL_SET); 662 set_internal (sym, val, Qnil, SET_INTERNAL_SET);
@@ -666,72 +753,86 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth,
666 NEXT; 753 NEXT;
667 754
668 CASE (Bgoto): 755 CASE (Bgoto):
669 op = FETCH2; 756 BYTE_CODE_QUIT;
670 op_branch: 757 op = FETCH2; /* pc = FETCH2 loses since FETCH2 contains pc++ */
671 op -= pc - bytestr_data; 758 CHECK_RANGE (op);
672 op_relative_branch: 759 stack.pc = stack.byte_string_start + op;
673 if (BYTE_CODE_SAFE
674 && ! (bytestr_data - pc <= op
675 && op < bytestr_data + bytestr_length - pc))
676 emacs_abort ();
677 quitcounter += op < 0;
678 if (!quitcounter)
679 {
680 quitcounter = 1;
681 maybe_gc ();
682 QUIT;
683 }
684 pc += op;
685 NEXT; 760 NEXT;
686 761
687 CASE (Bgotoifnonnil): 762 CASE (Bgotoifnonnil):
688 op = FETCH2; 763 op = FETCH2;
689 if (!NILP (POP)) 764 Lisp_Object v1 = POP;
690 goto op_branch; 765 if (!NILP (v1))
766 {
767 BYTE_CODE_QUIT;
768 CHECK_RANGE (op);
769 stack.pc = stack.byte_string_start + op;
770 }
691 NEXT; 771 NEXT;
692 772
693 CASE (Bgotoifnilelsepop): 773 CASE (Bgotoifnilelsepop):
694 op = FETCH2; 774 op = FETCH2;
695 if (NILP (TOP)) 775 if (NILP (TOP))
696 goto op_branch; 776 {
697 DISCARD (1); 777 BYTE_CODE_QUIT;
778 CHECK_RANGE (op);
779 stack.pc = stack.byte_string_start + op;
780 }
781 else DISCARD (1);
698 NEXT; 782 NEXT;
699 783
700 CASE (Bgotoifnonnilelsepop): 784 CASE (Bgotoifnonnilelsepop):
701 op = FETCH2; 785 op = FETCH2;
702 if (!NILP (TOP)) 786 if (!NILP (TOP))
703 goto op_branch; 787 {
704 DISCARD (1); 788 BYTE_CODE_QUIT;
789 CHECK_RANGE (op);
790 stack.pc = stack.byte_string_start + op;
791 }
792 else DISCARD (1);
705 NEXT; 793 NEXT;
706 794
707 CASE (BRgoto): 795 CASE (BRgoto):
708 op = FETCH - 128; 796 BYTE_CODE_QUIT;
709 goto op_relative_branch; 797 stack.pc += (int) *stack.pc - 127;
798 NEXT;
710 799
711 CASE (BRgotoifnil): 800 CASE (BRgotoifnil):
712 op = FETCH - 128;
713 if (NILP (POP)) 801 if (NILP (POP))
714 goto op_relative_branch; 802 {
803 BYTE_CODE_QUIT;
804 stack.pc += (int) *stack.pc - 128;
805 }
806 stack.pc++;
715 NEXT; 807 NEXT;
716 808
717 CASE (BRgotoifnonnil): 809 CASE (BRgotoifnonnil):
718 op = FETCH - 128;
719 if (!NILP (POP)) 810 if (!NILP (POP))
720 goto op_relative_branch; 811 {
812 BYTE_CODE_QUIT;
813 stack.pc += (int) *stack.pc - 128;
814 }
815 stack.pc++;
721 NEXT; 816 NEXT;
722 817
723 CASE (BRgotoifnilelsepop): 818 CASE (BRgotoifnilelsepop):
724 op = FETCH - 128; 819 op = *stack.pc++;
725 if (NILP (TOP)) 820 if (NILP (TOP))
726 goto op_relative_branch; 821 {
727 DISCARD (1); 822 BYTE_CODE_QUIT;
823 stack.pc += op - 128;
824 }
825 else DISCARD (1);
728 NEXT; 826 NEXT;
729 827
730 CASE (BRgotoifnonnilelsepop): 828 CASE (BRgotoifnonnilelsepop):
731 op = FETCH - 128; 829 op = *stack.pc++;
732 if (!NILP (TOP)) 830 if (!NILP (TOP))
733 goto op_relative_branch; 831 {
734 DISCARD (1); 832 BYTE_CODE_QUIT;
833 stack.pc += op - 128;
834 }
835 else DISCARD (1);
735 NEXT; 836 NEXT;
736 837
737 CASE (Breturn): 838 CASE (Breturn):
@@ -791,11 +892,15 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth,
791 if (sys_setjmp (c->jmp)) 892 if (sys_setjmp (c->jmp))
792 { 893 {
793 struct handler *c = handlerlist; 894 struct handler *c = handlerlist;
895 int dest;
794 top = c->bytecode_top; 896 top = c->bytecode_top;
795 op = c->bytecode_dest; 897 dest = c->bytecode_dest;
796 handlerlist = c->next; 898 handlerlist = c->next;
797 PUSH (c->val); 899 PUSH (c->val);
798 goto op_branch; 900 CHECK_RANGE (dest);
901 /* Might have been re-set by longjmp! */
902 stack.byte_string_start = SDATA (stack.byte_string);
903 stack.pc = stack.byte_string_start + dest;
799 } 904 }
800 905
801 NEXT; 906 NEXT;
@@ -1363,7 +1468,7 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth,
1363 call3 (Qerror, 1468 call3 (Qerror,
1364 build_string ("Invalid byte opcode: op=%s, ptr=%d"), 1469 build_string ("Invalid byte opcode: op=%s, ptr=%d"),
1365 make_number (op), 1470 make_number (op),
1366 make_number (pc - 1 - bytestr_data)); 1471 make_number (stack.pc - 1 - stack.byte_string_start));
1367 1472
1368 /* Handy byte-codes for lexical binding. */ 1473 /* Handy byte-codes for lexical binding. */
1369 CASE (Bstack_ref1): 1474 CASE (Bstack_ref1):
@@ -1423,6 +1528,8 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth,
1423 1528
1424 exit: 1529 exit:
1425 1530
1531 byte_stack_list = byte_stack_list->next;
1532
1426 /* Binds and unbinds are supposed to be compiled balanced. */ 1533 /* Binds and unbinds are supposed to be compiled balanced. */
1427 if (SPECPDL_INDEX () != count) 1534 if (SPECPDL_INDEX () != count)
1428 { 1535 {