aboutsummaryrefslogtreecommitdiffstats
path: root/src/lisp.h
diff options
context:
space:
mode:
authorStefan Monnier2013-10-03 00:58:56 -0400
committerStefan Monnier2013-10-03 00:58:56 -0400
commitadf2aa61404305e58e71cde0193bb650aff2c4b3 (patch)
treed6e6b4e5ab3b144a94daed2232cab798aadeb20a /src/lisp.h
parent328a8179fec33f5a75e2cfe22e43f4ec0df770b7 (diff)
downloademacs-adf2aa61404305e58e71cde0193bb650aff2c4b3.tar.gz
emacs-adf2aa61404305e58e71cde0193bb650aff2c4b3.zip
Introduce new bytecodes for efficient catch/condition-case in lexbind.
* lisp/emacs-lisp/byte-opt.el (byte-optimize-form-code-walker): Optimize under `condition-case' and `catch' if byte-compile--use-old-handlers is nil. (disassemble-offset): Handle new bytecodes. * lisp/emacs-lisp/bytecomp.el (byte-pushcatch, byte-pushconditioncase) (byte-pophandler): New byte codes. (byte-goto-ops): Adjust accordingly. (byte-compile--use-old-handlers): New var. (byte-compile-catch): Use new byte codes depending on byte-compile--use-old-handlers. (byte-compile-condition-case--old): Rename from byte-compile-condition-case. (byte-compile-condition-case--new): New function. (byte-compile-condition-case): New function that dispatches depending on byte-compile--use-old-handlers. (byte-compile-unwind-protect): Pass a function to byte-unwind-protect when we can. * lisp/emacs-lisp/cconv.el (cconv-convert, cconv-analyse-form): Adjust for the new compilation scheme using the new byte-codes. * src/alloc.c (Fgarbage_collect): Merge scans of handlerlist and catchlist, and make them unconditional now that they're heap-allocated. * src/bytecode.c (BYTE_CODES): Add Bpushcatch, Bpushconditioncase and Bpophandler. (bcall0): New function. (exec_byte_code): Add corresponding cases. Improve error message when encountering an invalid byte-code. Let Bunwind_protect accept a function (rather than a list of expressions) as argument. * src/eval.c (catchlist): Remove (merge with handlerlist). (handlerlist, lisp_eval_depth): Not static any more. (internal_catch, internal_condition_case, internal_condition_case_1) (internal_condition_case_2, internal_condition_case_n): Use PUSH_HANDLER. (unwind_to_catch, Fthrow, Fsignal): Adjust to merged handlerlist/catchlist. (internal_lisp_condition_case): Use PUSH_HANDLER. Adjust to new handlerlist which can only handle a single condition-case handler at a time. (find_handler_clause): Simplify since we only a single branch here any more. * src/lisp.h (struct handler): Merge struct handler and struct catchtag. (PUSH_HANDLER): New macro. (catchlist): Remove. (handlerlist): Always declare.
Diffstat (limited to 'src/lisp.h')
-rw-r--r--src/lisp.h111
1 files changed, 58 insertions, 53 deletions
diff --git a/src/lisp.h b/src/lisp.h
index 63597e86be6..688c89c1eee 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -2635,11 +2635,9 @@ typedef jmp_buf sys_jmp_buf;
2635 - The specpdl stack: keeps track of active unwind-protect and 2635 - The specpdl stack: keeps track of active unwind-protect and
2636 dynamic-let-bindings. Allocated from the `specpdl' array, a manually 2636 dynamic-let-bindings. Allocated from the `specpdl' array, a manually
2637 managed stack. 2637 managed stack.
2638 - The catch stack: keeps track of active catch tags. 2638 - The handler stack: keeps track of active catch tags and condition-case
2639 Allocated on the C stack. This is where the setmp data is kept. 2639 handlers. Allocated in a manually managed stack implemented by a
2640 - The handler stack: keeps track of active condition-case handlers. 2640 doubly-linked list allocated via xmalloc and never freed. */
2641 Allocated on the C stack. Every entry there also uses an entry in
2642 the catch stack. */
2643 2641
2644/* Structure for recording Lisp call stack for backtrace purposes. */ 2642/* Structure for recording Lisp call stack for backtrace purposes. */
2645 2643
@@ -2709,46 +2707,16 @@ SPECPDL_INDEX (void)
2709 return specpdl_ptr - specpdl; 2707 return specpdl_ptr - specpdl;
2710} 2708}
2711 2709
2712/* Everything needed to describe an active condition case. 2710/* This structure helps implement the `catch/throw' and `condition-case/signal'
2711 control structures. A struct handler contains all the information needed to
2712 restore the state of the interpreter after a non-local jump.
2713 2713
2714 Members are volatile if their values need to survive _longjmp when 2714 handler structures are chained together in a doubly linked list; the `next'
2715 a 'struct handler' is a local variable. */ 2715 member points to the next outer catchtag and the `nextfree' member points in
2716struct handler 2716 the other direction to the next inner element (which is typically the next
2717 { 2717 free element since we mostly use it on the deepest handler).
2718 /* The handler clauses and variable from the condition-case form. */
2719 /* For a handler set up in Lisp code, this is always a list.
2720 For an internal handler set up by internal_condition_case*,
2721 this can instead be the symbol t or `error'.
2722 t: handle all conditions.
2723 error: handle all conditions, and errors can run the debugger
2724 or display a backtrace. */
2725 Lisp_Object handler;
2726
2727 Lisp_Object volatile var;
2728
2729 /* Fsignal stores here the condition-case clause that applies,
2730 and Fcondition_case thus knows which clause to run. */
2731 Lisp_Object volatile chosen_clause;
2732
2733 /* Used to effect the longjump out to the handler. */
2734 struct catchtag *tag;
2735
2736 /* The next enclosing handler. */
2737 struct handler *next;
2738 };
2739 2718
2740/* This structure helps implement the `catch' and `throw' control 2719 A call like (throw TAG VAL) searches for a catchtag whose `tag_or_ch'
2741 structure. A struct catchtag contains all the information needed
2742 to restore the state of the interpreter after a non-local jump.
2743
2744 Handlers for error conditions (represented by `struct handler'
2745 structures) just point to a catch tag to do the cleanup required
2746 for their jumps.
2747
2748 catchtag structures are chained together in the C calling stack;
2749 the `next' member points to the next outer catchtag.
2750
2751 A call like (throw TAG VAL) searches for a catchtag whose `tag'
2752 member is TAG, and then unbinds to it. The `val' member is used to 2720 member is TAG, and then unbinds to it. The `val' member is used to
2753 hold VAL while the stack is unwound; `val' is returned as the value 2721 hold VAL while the stack is unwound; `val' is returned as the value
2754 of the catch form. 2722 of the catch form.
@@ -2757,24 +2725,63 @@ struct handler
2757 state. 2725 state.
2758 2726
2759 Members are volatile if their values need to survive _longjmp when 2727 Members are volatile if their values need to survive _longjmp when
2760 a 'struct catchtag' is a local variable. */ 2728 a 'struct handler' is a local variable. */
2761struct catchtag 2729
2730enum handlertype { CATCHER, CONDITION_CASE };
2731
2732struct handler
2762{ 2733{
2763 Lisp_Object tag; 2734 enum handlertype type;
2764 Lisp_Object volatile val; 2735 Lisp_Object tag_or_ch;
2765 struct catchtag *volatile next; 2736 Lisp_Object val;
2737 struct handler *next;
2738 struct handler *nextfree;
2739
2740 /* The bytecode interpreter can have several handlers active at the same
2741 time, so when we longjmp to one of them, it needs to know which handler
2742 this was and what was the corresponding internal state. This is stored
2743 here, and when we longjmp we make sure that handlerlist points to the
2744 proper handler. */
2745 Lisp_Object *bytecode_top;
2746 int bytecode_dest;
2747
2748 /* Most global vars are reset to their value via the specpdl mechanism,
2749 but a few others are handled by storing their value here. */
2766#if 1 /* GC_MARK_STACK == GC_MAKE_GCPROS_NOOPS, but they're defined later. */ 2750#if 1 /* GC_MARK_STACK == GC_MAKE_GCPROS_NOOPS, but they're defined later. */
2767 struct gcpro *gcpro; 2751 struct gcpro *gcpro;
2768#endif 2752#endif
2769 sys_jmp_buf jmp; 2753 sys_jmp_buf jmp;
2770 struct handler *handlerlist;
2771 EMACS_INT lisp_eval_depth; 2754 EMACS_INT lisp_eval_depth;
2772 ptrdiff_t volatile pdlcount; 2755 ptrdiff_t pdlcount;
2773 int poll_suppress_count; 2756 int poll_suppress_count;
2774 int interrupt_input_blocked; 2757 int interrupt_input_blocked;
2775 struct byte_stack *byte_stack; 2758 struct byte_stack *byte_stack;
2776}; 2759};
2777 2760
2761/* Fill in the components of c, and put it on the list. */
2762#define PUSH_HANDLER(c, tag_ch_val, handlertype) \
2763 if (handlerlist && handlerlist->nextfree) \
2764 (c) = handlerlist->nextfree; \
2765 else \
2766 { \
2767 (c) = xmalloc (sizeof (struct handler)); \
2768 (c)->nextfree = NULL; \
2769 if (handlerlist) \
2770 handlerlist->nextfree = (c); \
2771 } \
2772 (c)->type = (handlertype); \
2773 (c)->tag_or_ch = (tag_ch_val); \
2774 (c)->val = Qnil; \
2775 (c)->next = handlerlist; \
2776 (c)->lisp_eval_depth = lisp_eval_depth; \
2777 (c)->pdlcount = SPECPDL_INDEX (); \
2778 (c)->poll_suppress_count = poll_suppress_count; \
2779 (c)->interrupt_input_blocked = interrupt_input_blocked;\
2780 (c)->gcpro = gcprolist; \
2781 (c)->byte_stack = byte_stack_list; \
2782 handlerlist = (c);
2783
2784
2778extern Lisp_Object memory_signal_data; 2785extern Lisp_Object memory_signal_data;
2779 2786
2780/* An address near the bottom of the stack. 2787/* An address near the bottom of the stack.
@@ -3677,10 +3684,8 @@ extern Lisp_Object Qand_rest;
3677extern Lisp_Object Vautoload_queue; 3684extern Lisp_Object Vautoload_queue;
3678extern Lisp_Object Vsignaling_function; 3685extern Lisp_Object Vsignaling_function;
3679extern Lisp_Object inhibit_lisp_code; 3686extern Lisp_Object inhibit_lisp_code;
3680#if BYTE_MARK_STACK
3681extern struct catchtag *catchlist;
3682extern struct handler *handlerlist; 3687extern struct handler *handlerlist;
3683#endif 3688
3684/* To run a normal hook, use the appropriate function from the list below. 3689/* To run a normal hook, use the appropriate function from the list below.
3685 The calling convention: 3690 The calling convention:
3686 3691