aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Monnier2013-10-03 00:58:56 -0400
committerStefan Monnier2013-10-03 00:58:56 -0400
commitadf2aa61404305e58e71cde0193bb650aff2c4b3 (patch)
treed6e6b4e5ab3b144a94daed2232cab798aadeb20a
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.
-rw-r--r--lisp/ChangeLog24
-rw-r--r--lisp/emacs-lisp/byte-opt.el32
-rw-r--r--lisp/emacs-lisp/bytecomp.el104
-rw-r--r--lisp/emacs-lisp/cconv.el63
-rw-r--r--src/ChangeLog30
-rw-r--r--src/alloc.c20
-rw-r--r--src/bytecode.c79
-rw-r--r--src/eval.c336
-rw-r--r--src/lisp.h111
9 files changed, 484 insertions, 315 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index a0eeb4a47bd..90158b85b4d 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,5 +1,29 @@
12013-10-03 Stefan Monnier <monnier@iro.umontreal.ca> 12013-10-03 Stefan Monnier <monnier@iro.umontreal.ca>
2 2
3 * emacs-lisp/cconv.el (cconv-convert, cconv-analyse-form): Adjust for
4 the new compilation scheme using the new byte-codes.
5
6 * emacs-lisp/bytecomp.el (byte-pushcatch, byte-pushconditioncase)
7 (byte-pophandler): New byte codes.
8 (byte-goto-ops): Adjust accordingly.
9 (byte-compile--use-old-handlers): New var.
10 (byte-compile-catch): Use new byte codes depending on
11 byte-compile--use-old-handlers.
12 (byte-compile-condition-case--old): Rename from
13 byte-compile-condition-case.
14 (byte-compile-condition-case--new): New function.
15 (byte-compile-condition-case): New function that dispatches depending
16 on byte-compile--use-old-handlers.
17 (byte-compile-unwind-protect): Pass a function to byte-unwind-protect
18 when we can.
19
20 * emacs-lisp/byte-opt.el (byte-optimize-form-code-walker):
21 Optimize under `condition-case' and `catch' if
22 byte-compile--use-old-handlers is nil.
23 (disassemble-offset): Handle new bytecodes.
24
252013-10-03 Stefan Monnier <monnier@iro.umontreal.ca>
26
3 * subr.el (error): Use `declare'. 27 * subr.el (error): Use `declare'.
4 (decode-char, encode-char): Use advertised-calling-convention instead 28 (decode-char, encode-char): Use advertised-calling-convention instead
5 of the docstring to discourage use of the `restriction' arg. 29 of the docstring to discourage use of the `restriction' arg.
diff --git a/lisp/emacs-lisp/byte-opt.el b/lisp/emacs-lisp/byte-opt.el
index 9da1a4d1f38..14293e3c0df 100644
--- a/lisp/emacs-lisp/byte-opt.el
+++ b/lisp/emacs-lisp/byte-opt.el
@@ -488,11 +488,22 @@
488 (prin1-to-string form)) 488 (prin1-to-string form))
489 nil) 489 nil)
490 490
491 ((memq fn '(function condition-case)) 491 ((eq fn 'function)
492 ;; These forms are compiled as constants or by breaking out 492 ;; This forms is compiled as constant or by breaking out
493 ;; all the subexpressions and compiling them separately. 493 ;; all the subexpressions and compiling them separately.
494 form) 494 form)
495 495
496 ((eq fn 'condition-case)
497 (if byte-compile--use-old-handlers
498 ;; Will be optimized later.
499 form
500 `(condition-case ,(nth 1 form) ;Not evaluated.
501 ,(byte-optimize-form (nth 2 form) for-effect)
502 ,@(mapcar (lambda (clause)
503 `(,(car clause)
504 ,@(byte-optimize-body (cdr clause) for-effect)))
505 (nthcdr 3 form)))))
506
496 ((eq fn 'unwind-protect) 507 ((eq fn 'unwind-protect)
497 ;; the "protected" part of an unwind-protect is compiled (and thus 508 ;; the "protected" part of an unwind-protect is compiled (and thus
498 ;; optimized) as a top-level form, so don't do it here. But the 509 ;; optimized) as a top-level form, so don't do it here. But the
@@ -504,13 +515,14 @@
504 (cdr (cdr form))))) 515 (cdr (cdr form)))))
505 516
506 ((eq fn 'catch) 517 ((eq fn 'catch)
507 ;; the body of a catch is compiled (and thus optimized) as a
508 ;; top-level form, so don't do it here. The tag is never
509 ;; for-effect. The body should have the same for-effect status
510 ;; as the catch form itself, but that isn't handled properly yet.
511 (cons fn 518 (cons fn
512 (cons (byte-optimize-form (nth 1 form) nil) 519 (cons (byte-optimize-form (nth 1 form) nil)
513 (cdr (cdr form))))) 520 (if byte-compile--use-old-handlers
521 ;; The body of a catch is compiled (and thus
522 ;; optimized) as a top-level form, so don't do it
523 ;; here.
524 (cdr (cdr form))
525 (byte-optimize-body (cdr form) for-effect)))))
514 526
515 ((eq fn 'ignore) 527 ((eq fn 'ignore)
516 ;; Don't treat the args to `ignore' as being 528 ;; Don't treat the args to `ignore' as being
@@ -1292,7 +1304,7 @@
1292 "Don't call this!" 1304 "Don't call this!"
1293 ;; Fetch and return the offset for the current opcode. 1305 ;; Fetch and return the offset for the current opcode.
1294 ;; Return nil if this opcode has no offset. 1306 ;; Return nil if this opcode has no offset.
1295 (cond ((< bytedecomp-op byte-nth) 1307 (cond ((< bytedecomp-op byte-pophandler)
1296 (let ((tem (logand bytedecomp-op 7))) 1308 (let ((tem (logand bytedecomp-op 7)))
1297 (setq bytedecomp-op (logand bytedecomp-op 248)) 1309 (setq bytedecomp-op (logand bytedecomp-op 248))
1298 (cond ((eq tem 6) 1310 (cond ((eq tem 6)
@@ -1311,7 +1323,9 @@
1311 (setq bytedecomp-op byte-constant))) 1323 (setq bytedecomp-op byte-constant)))
1312 ((or (and (>= bytedecomp-op byte-constant2) 1324 ((or (and (>= bytedecomp-op byte-constant2)
1313 (<= bytedecomp-op byte-goto-if-not-nil-else-pop)) 1325 (<= bytedecomp-op byte-goto-if-not-nil-else-pop))
1314 (= bytedecomp-op byte-stack-set2)) 1326 (memq bytedecomp-op (eval-when-compile
1327 (list byte-stack-set2 byte-pushcatch
1328 byte-pushconditioncase))))
1315 ;; Offset in next 2 bytes. 1329 ;; Offset in next 2 bytes.
1316 (setq bytedecomp-ptr (1+ bytedecomp-ptr)) 1330 (setq bytedecomp-ptr (1+ bytedecomp-ptr))
1317 (+ (aref bytes bytedecomp-ptr) 1331 (+ (aref bytes bytedecomp-ptr)
diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el
index 164cdb12952..35c7c391870 100644
--- a/lisp/emacs-lisp/bytecomp.el
+++ b/lisp/emacs-lisp/bytecomp.el
@@ -535,7 +535,13 @@ Each element is (INDEX . VALUE)")
535(byte-defop 40 0 byte-unbind "for unbinding special bindings") 535(byte-defop 40 0 byte-unbind "for unbinding special bindings")
536;; codes 8-47 are consumed by the preceding opcodes 536;; codes 8-47 are consumed by the preceding opcodes
537 537
538;; unused: 48-55 538;; New (in Emacs-24.4) bytecodes for more efficient handling of non-local exits
539;; (especially useful in lexical-binding code).
540(byte-defop 48 0 byte-pophandler)
541(byte-defop 50 -1 byte-pushcatch)
542(byte-defop 49 -1 byte-pushconditioncase)
543
544;; unused: 51-55
539 545
540(byte-defop 56 -1 byte-nth) 546(byte-defop 56 -1 byte-nth)
541(byte-defop 57 0 byte-symbolp) 547(byte-defop 57 0 byte-symbolp)
@@ -707,7 +713,8 @@ otherwise pop it")
707 713
708(defconst byte-goto-ops '(byte-goto byte-goto-if-nil byte-goto-if-not-nil 714(defconst byte-goto-ops '(byte-goto byte-goto-if-nil byte-goto-if-not-nil
709 byte-goto-if-nil-else-pop 715 byte-goto-if-nil-else-pop
710 byte-goto-if-not-nil-else-pop) 716 byte-goto-if-not-nil-else-pop
717 byte-pushcatch byte-pushconditioncase)
711 "List of byte-codes whose offset is a pc.") 718 "List of byte-codes whose offset is a pc.")
712 719
713(defconst byte-goto-always-pop-ops '(byte-goto-if-nil byte-goto-if-not-nil)) 720(defconst byte-goto-always-pop-ops '(byte-goto-if-nil byte-goto-if-not-nil))
@@ -4028,23 +4035,35 @@ binding slots have been popped."
4028;; (byte-defop-compiler-1 with-output-to-temp-buffer) ;Obsolete: now a macro. 4035;; (byte-defop-compiler-1 with-output-to-temp-buffer) ;Obsolete: now a macro.
4029(byte-defop-compiler-1 track-mouse) 4036(byte-defop-compiler-1 track-mouse)
4030 4037
4038(defvar byte-compile--use-old-handlers t
4039 "If nil, use new byte codes introduced in Emacs-24.4.")
4040
4031(defun byte-compile-catch (form) 4041(defun byte-compile-catch (form)
4032 (byte-compile-form (car (cdr form))) 4042 (byte-compile-form (car (cdr form)))
4033 (pcase (cddr form) 4043 (if (not byte-compile--use-old-handlers)
4034 (`(:fun-body ,f) 4044 (let ((endtag (byte-compile-make-tag)))
4035 (byte-compile-form `(list 'funcall ,f))) 4045 (byte-compile-goto 'byte-pushcatch endtag)
4036 (body 4046 (byte-compile-body (cddr form) nil)
4037 (byte-compile-push-constant 4047 (byte-compile-out 'byte-pophandler)
4038 (byte-compile-top-level (cons 'progn body) byte-compile--for-effect)))) 4048 (byte-compile-out-tag endtag))
4039 (byte-compile-out 'byte-catch 0)) 4049 (pcase (cddr form)
4050 (`(:fun-body ,f)
4051 (byte-compile-form `(list 'funcall ,f)))
4052 (body
4053 (byte-compile-push-constant
4054 (byte-compile-top-level (cons 'progn body) byte-compile--for-effect))))
4055 (byte-compile-out 'byte-catch 0)))
4040 4056
4041(defun byte-compile-unwind-protect (form) 4057(defun byte-compile-unwind-protect (form)
4042 (pcase (cddr form) 4058 (pcase (cddr form)
4043 (`(:fun-body ,f) 4059 (`(:fun-body ,f)
4044 (byte-compile-form `(list (list 'funcall ,f)))) 4060 (byte-compile-form
4061 (if byte-compile--use-old-handlers `(list (list 'funcall ,f)) f)))
4045 (handlers 4062 (handlers
4046 (byte-compile-push-constant 4063 (if byte-compile--use-old-handlers
4047 (byte-compile-top-level-body handlers t)))) 4064 (byte-compile-push-constant
4065 (byte-compile-top-level-body handlers t))
4066 (byte-compile-form `#'(lambda () ,@handlers)))))
4048 (byte-compile-out 'byte-unwind-protect 0) 4067 (byte-compile-out 'byte-unwind-protect 0)
4049 (byte-compile-form-do-effect (car (cdr form))) 4068 (byte-compile-form-do-effect (car (cdr form)))
4050 (byte-compile-out 'byte-unbind 1)) 4069 (byte-compile-out 'byte-unbind 1))
@@ -4056,6 +4075,11 @@ binding slots have been popped."
4056 (_ `(eval '(track-mouse ,@(byte-compile-top-level-body (cdr form)))))))) 4075 (_ `(eval '(track-mouse ,@(byte-compile-top-level-body (cdr form))))))))
4057 4076
4058(defun byte-compile-condition-case (form) 4077(defun byte-compile-condition-case (form)
4078 (if byte-compile--use-old-handlers
4079 (byte-compile-condition-case--old form)
4080 (byte-compile-condition-case--new form)))
4081
4082(defun byte-compile-condition-case--old (form)
4059 (let* ((var (nth 1 form)) 4083 (let* ((var (nth 1 form))
4060 (fun-bodies (eq var :fun-body)) 4084 (fun-bodies (eq var :fun-body))
4061 (byte-compile-bound-variables 4085 (byte-compile-bound-variables
@@ -4106,6 +4130,62 @@ binding slots have been popped."
4106 (byte-compile-push-constant compiled-clauses))) 4130 (byte-compile-push-constant compiled-clauses)))
4107 (byte-compile-out 'byte-condition-case 0))) 4131 (byte-compile-out 'byte-condition-case 0)))
4108 4132
4133(defun byte-compile-condition-case--new (form)
4134 (let* ((var (nth 1 form))
4135 (body (nth 2 form))
4136 (depth byte-compile-depth)
4137 (clauses (mapcar (lambda (clause)
4138 (cons (byte-compile-make-tag) clause))
4139 (nthcdr 3 form)))
4140 (endtag (byte-compile-make-tag)))
4141 (byte-compile-set-symbol-position 'condition-case)
4142 (unless (symbolp var)
4143 (byte-compile-warn
4144 "`%s' is not a variable-name or nil (in condition-case)" var))
4145
4146 (dolist (clause (reverse clauses))
4147 (let ((condition (nth 1 clause)))
4148 (unless (consp condition) (setq condition (list condition)))
4149 (dolist (c condition)
4150 (unless (and c (symbolp c))
4151 (byte-compile-warn
4152 "`%S' is not a condition name (in condition-case)" c))
4153 ;; In reality, the `error-conditions' property is only required
4154 ;; for the argument to `signal', not to `condition-case'.
4155 ;;(unless (consp (get c 'error-conditions))
4156 ;; (byte-compile-warn
4157 ;; "`%s' is not a known condition name (in condition-case)"
4158 ;; c))
4159 )
4160 (byte-compile-push-constant condition))
4161 (byte-compile-goto 'byte-pushconditioncase (car clause)))
4162
4163 (byte-compile-form body) ;; byte-compile--for-effect
4164 (dolist (_ clauses) (byte-compile-out 'byte-pophandler))
4165 (byte-compile-goto 'byte-goto endtag)
4166
4167 (while clauses
4168 (let ((clause (pop clauses))
4169 (byte-compile-bound-variables byte-compile-bound-variables)
4170 (byte-compile--lexical-environment
4171 byte-compile--lexical-environment))
4172 (setq byte-compile-depth (1+ depth))
4173 (byte-compile-out-tag (pop clause))
4174 (dolist (_ clauses) (byte-compile-out 'byte-pophandler))
4175 (cond
4176 ((null var) (byte-compile-discard))
4177 (lexical-binding
4178 (push (cons var (1- byte-compile-depth))
4179 byte-compile--lexical-environment))
4180 (t (byte-compile-dynamic-variable-bind var)))
4181 (byte-compile-body (cdr clause)) ;; byte-compile--for-effect
4182 (cond
4183 ((null var) nil)
4184 (lexical-binding (byte-compile-discard 1 'preserve-tos))
4185 (t (byte-compile-out 'byte-unbind 1)))
4186 (byte-compile-goto 'byte-goto endtag)))
4187
4188 (byte-compile-out-tag endtag)))
4109 4189
4110(defun byte-compile-save-excursion (form) 4190(defun byte-compile-save-excursion (form)
4111 (if (and (eq 'set-buffer (car-safe (car-safe (cdr form)))) 4191 (if (and (eq 'set-buffer (car-safe (car-safe (cdr form))))
diff --git a/lisp/emacs-lisp/cconv.el b/lisp/emacs-lisp/cconv.el
index c655c2fff84..f24e503fd6d 100644
--- a/lisp/emacs-lisp/cconv.el
+++ b/lisp/emacs-lisp/cconv.el
@@ -79,8 +79,7 @@
79;; command-history). 79;; command-history).
80;; - canonize code in macro-expand so we don't have to handle (let (var) body) 80;; - canonize code in macro-expand so we don't have to handle (let (var) body)
81;; and other oddities. 81;; and other oddities.
82;; - new byte codes for unwind-protect, catch, and condition-case so that 82;; - new byte codes for unwind-protect so that closures aren't needed at all.
83;; closures aren't needed at all.
84;; - a reference to a var that is known statically to always hold a constant 83;; - a reference to a var that is known statically to always hold a constant
85;; should be turned into a byte-constant rather than a byte-stack-ref. 84;; should be turned into a byte-constant rather than a byte-stack-ref.
86;; Hmm... right, that's called constant propagation and could be done here, 85;; Hmm... right, that's called constant propagation and could be done here,
@@ -421,18 +420,42 @@ places where they originally did not directly appear."
421 forms))) 420 forms)))
422 421
423 ;condition-case 422 ;condition-case
424 (`(condition-case ,var ,protected-form . ,handlers) 423 ((and `(condition-case ,var ,protected-form . ,handlers)
424 (guard byte-compile--use-old-handlers))
425 (let ((newform (cconv--convert-function 425 (let ((newform (cconv--convert-function
426 () (list protected-form) env form))) 426 () (list protected-form) env form)))
427 `(condition-case :fun-body ,newform 427 `(condition-case :fun-body ,newform
428 ,@(mapcar (lambda (handler) 428 ,@(mapcar (lambda (handler)
429 (list (car handler) 429 (list (car handler)
430 (cconv--convert-function 430 (cconv--convert-function
431 (list (or var cconv--dummy-var)) 431 (list (or var cconv--dummy-var))
432 (cdr handler) env form))) 432 (cdr handler) env form)))
433 handlers)))) 433 handlers))))
434 434
435 (`(,(and head (or `catch `unwind-protect)) ,form . ,body) 435 ; condition-case with new byte-codes.
436 (`(condition-case ,var ,protected-form . ,handlers)
437 `(condition-case ,var
438 ,(cconv-convert protected-form env extend)
439 ,@(let* ((cm (and var (member (cons (list var) form)
440 cconv-captured+mutated)))
441 (newenv
442 (cond (cm (cons `(,var . (car-save ,var)) env))
443 ((assq var env) (cons `(,var) env))
444 (t env))))
445 (mapcar
446 (lambda (handler)
447 `(,(car handler)
448 ,@(let ((body
449 (mapcar (lambda (form)
450 (cconv-convert form newenv extend))
451 (cdr handler))))
452 (if (not cm) body
453 `((let ((,var (list ,var))) ,@body))))))
454 handlers))))
455
456 (`(,(and head (or (and `catch (guard byte-compile--use-old-handlers))
457 `unwind-protect))
458 ,form . ,body)
436 `(,head ,(cconv-convert form env extend) 459 `(,head ,(cconv-convert form env extend)
437 :fun-body ,(cconv--convert-function () body env form))) 460 :fun-body ,(cconv--convert-function () body env form)))
438 461
@@ -491,7 +514,7 @@ places where they originally did not directly appear."
491 514
492 (`(,func . ,forms) 515 (`(,func . ,forms)
493 ;; First element is function or whatever function-like forms are: or, and, 516 ;; First element is function or whatever function-like forms are: or, and,
494 ;; if, progn, prog1, prog2, while, until 517 ;; if, catch, progn, prog1, prog2, while, until
495 `(,func . ,(mapcar (lambda (form) 518 `(,func . ,(mapcar (lambda (form)
496 (cconv-convert form env extend)) 519 (cconv-convert form env extend))
497 forms))) 520 forms)))
@@ -646,16 +669,32 @@ and updates the data stored in ENV."
646 (`(quote . ,_) nil) ; quote form 669 (`(quote . ,_) nil) ; quote form
647 (`(function . ,_) nil) ; same as quote 670 (`(function . ,_) nil) ; same as quote
648 671
649 (`(condition-case ,var ,protected-form . ,handlers) 672 ((and `(condition-case ,var ,protected-form . ,handlers)
673 (guard byte-compile--use-old-handlers))
650 ;; FIXME: The bytecode for condition-case forces us to wrap the 674 ;; FIXME: The bytecode for condition-case forces us to wrap the
651 ;; form and handlers in closures (for handlers, it's understandable 675 ;; form and handlers in closures.
652 ;; but not for the protected form).
653 (cconv--analyse-function () (list protected-form) env form) 676 (cconv--analyse-function () (list protected-form) env form)
654 (dolist (handler handlers) 677 (dolist (handler handlers)
655 (cconv--analyse-function (if var (list var)) (cdr handler) env form))) 678 (cconv--analyse-function (if var (list var)) (cdr handler)
679 env form)))
656 680
657 ;; FIXME: The bytecode for catch forces us to wrap the body. 681 (`(condition-case ,var ,protected-form . ,handlers)
658 (`(,(or `catch `unwind-protect) ,form . ,body) 682 (cconv-analyse-form protected-form env)
683 (when (and var (symbolp var) (byte-compile-not-lexical-var-p var))
684 (byte-compile-log-warning
685 (format "Lexical variable shadows the dynamic variable %S" var)))
686 (let* ((varstruct (list var nil nil nil nil)))
687 (if var (push varstruct env))
688 (dolist (handler handlers)
689 (dolist (form (cdr handler))
690 (cconv-analyse-form form env)))
691 (if var (cconv--analyse-use (cons (list var) (cdr varstruct))
692 form "variable"))))
693
694 ;; FIXME: The bytecode for unwind-protect forces us to wrap the unwind.
695 (`(,(or (and `catch (guard byte-compile--use-old-handlers))
696 `unwind-protect)
697 ,form . ,body)
659 (cconv-analyse-form form env) 698 (cconv-analyse-form form env)
660 (cconv--analyse-function () body env form)) 699 (cconv--analyse-function () body env form))
661 700
diff --git a/src/ChangeLog b/src/ChangeLog
index c201df19851..4b1bfc75187 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,5 +1,35 @@
12013-10-03 Stefan Monnier <monnier@iro.umontreal.ca> 12013-10-03 Stefan Monnier <monnier@iro.umontreal.ca>
2 2
3 * lisp.h (struct handler): Merge struct handler and struct catchtag.
4 (PUSH_HANDLER): New macro.
5 (catchlist): Remove.
6 (handlerlist): Always declare.
7
8 * eval.c (catchlist): Remove (merge with handlerlist).
9 (handlerlist, lisp_eval_depth): Not static any more.
10 (internal_catch, internal_condition_case, internal_condition_case_1)
11 (internal_condition_case_2, internal_condition_case_n):
12 Use PUSH_HANDLER.
13 (unwind_to_catch, Fthrow, Fsignal): Adjust to merged
14 handlerlist/catchlist.
15 (internal_lisp_condition_case): Use PUSH_HANDLER. Adjust to new
16 handlerlist which can only handle a single condition-case handler at
17 a time.
18 (find_handler_clause): Simplify since we only a single branch here
19 any more.
20
21 * bytecode.c (BYTE_CODES): Add Bpushcatch, Bpushconditioncase
22 and Bpophandler.
23 (bcall0): New function.
24 (exec_byte_code): Add corresponding cases. Improve error message when
25 encountering an invalid byte-code. Let Bunwind_protect accept
26 a function (rather than a list of expressions) as argument.
27
28 * alloc.c (Fgarbage_collect): Merge scans of handlerlist and catchlist,
29 and make them unconditional now that they're heap-allocated.
30
312013-10-03 Stefan Monnier <monnier@iro.umontreal.ca>
32
3 * charset.c (Fdecode_char, Fencode_char): Remove description of 33 * charset.c (Fdecode_char, Fencode_char): Remove description of
4 `restriction' arg. now that it's hidden by advertised-calling-convention. 34 `restriction' arg. now that it's hidden by advertised-calling-convention.
5 35
diff --git a/src/alloc.c b/src/alloc.c
index 2d9828ffa79..6b07f0bd7b1 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -5370,23 +5370,15 @@ See Info node `(elisp)Garbage Collection'. */)
5370 mark_object (tail->var[i]); 5370 mark_object (tail->var[i]);
5371 } 5371 }
5372 mark_byte_stack (); 5372 mark_byte_stack ();
5373#endif
5373 { 5374 {
5374 struct catchtag *catch;
5375 struct handler *handler; 5375 struct handler *handler;
5376 5376 for (handler = handlerlist; handler; handler = handler->next)
5377 for (catch = catchlist; catch; catch = catch->next) 5377 {
5378 { 5378 mark_object (handler->tag_or_ch);
5379 mark_object (catch->tag); 5379 mark_object (handler->val);
5380 mark_object (catch->val); 5380 }
5381 }
5382 for (handler = handlerlist; handler; handler = handler->next)
5383 {
5384 mark_object (handler->handler);
5385 mark_object (handler->var);
5386 }
5387 } 5381 }
5388#endif
5389
5390#ifdef HAVE_WINDOW_SYSTEM 5382#ifdef HAVE_WINDOW_SYSTEM
5391 mark_fringe_data (); 5383 mark_fringe_data ();
5392#endif 5384#endif
diff --git a/src/bytecode.c b/src/bytecode.c
index 23e50826633..f7ccd35cbba 100644
--- a/src/bytecode.c
+++ b/src/bytecode.c
@@ -141,6 +141,10 @@ DEFINE (Bunbind5, 055) \
141DEFINE (Bunbind6, 056) \ 141DEFINE (Bunbind6, 056) \
142DEFINE (Bunbind7, 057) \ 142DEFINE (Bunbind7, 057) \
143 \ 143 \
144DEFINE (Bpophandler, 060) \
145DEFINE (Bpushconditioncase, 061) \
146DEFINE (Bpushcatch, 062) \
147 \
144DEFINE (Bnth, 070) \ 148DEFINE (Bnth, 070) \
145DEFINE (Bsymbolp, 071) \ 149DEFINE (Bsymbolp, 071) \
146DEFINE (Bconsp, 072) \ 150DEFINE (Bconsp, 072) \
@@ -478,6 +482,12 @@ If the third argument is incorrect, Emacs may crash. */)
478 return exec_byte_code (bytestr, vector, maxdepth, Qnil, 0, NULL); 482 return exec_byte_code (bytestr, vector, maxdepth, Qnil, 0, NULL);
479} 483}
480 484
485static void
486bcall0 (Lisp_Object f)
487{
488 Ffuncall (1, &f);
489}
490
481/* Execute the byte-code in BYTESTR. VECTOR is the constant vector, and 491/* Execute the byte-code in BYTESTR. VECTOR is the constant vector, and
482 MAXDEPTH is the maximum stack depth used (if MAXDEPTH is incorrect, 492 MAXDEPTH is the maximum stack depth used (if MAXDEPTH is incorrect,
483 emacs may crash!). If ARGS_TEMPLATE is non-nil, it should be a lisp 493 emacs may crash!). If ARGS_TEMPLATE is non-nil, it should be a lisp
@@ -506,6 +516,7 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth,
506 struct byte_stack stack; 516 struct byte_stack stack;
507 Lisp_Object *top; 517 Lisp_Object *top;
508 Lisp_Object result; 518 Lisp_Object result;
519 enum handlertype type;
509 520
510#if 0 /* CHECK_FRAME_FONT */ 521#if 0 /* CHECK_FRAME_FONT */
511 { 522 {
@@ -1078,7 +1089,7 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth,
1078 save_restriction_save ()); 1089 save_restriction_save ());
1079 NEXT; 1090 NEXT;
1080 1091
1081 CASE (Bcatch): /* FIXME: ill-suited for lexbind. */ 1092 CASE (Bcatch): /* Obsolete since 24.4. */
1082 { 1093 {
1083 Lisp_Object v1; 1094 Lisp_Object v1;
1084 BEFORE_POTENTIAL_GC (); 1095 BEFORE_POTENTIAL_GC ();
@@ -1088,11 +1099,56 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth,
1088 NEXT; 1099 NEXT;
1089 } 1100 }
1090 1101
1102 CASE (Bpushcatch): /* New in 24.4. */
1103 type = CATCHER;
1104 goto pushhandler;
1105 CASE (Bpushconditioncase): /* New in 24.4. */
1106 {
1107 extern EMACS_INT lisp_eval_depth;
1108 extern int poll_suppress_count;
1109 extern int interrupt_input_blocked;
1110 struct handler *c;
1111 Lisp_Object tag;
1112 int dest;
1113
1114 type = CONDITION_CASE;
1115 pushhandler:
1116 tag = POP;
1117 dest = FETCH2;
1118
1119 PUSH_HANDLER (c, tag, type);
1120 c->bytecode_dest = dest;
1121 c->bytecode_top = top;
1122 if (sys_setjmp (c->jmp))
1123 {
1124 struct handler *c = handlerlist;
1125 top = c->bytecode_top;
1126 int dest = c->bytecode_dest;
1127 handlerlist = c->next;
1128 PUSH (c->val);
1129 CHECK_RANGE (dest);
1130 stack.pc = stack.byte_string_start + dest;
1131 }
1132 NEXT;
1133 }
1134
1135 CASE (Bpophandler): /* New in 24.4. */
1136 {
1137 handlerlist = handlerlist->next;
1138 NEXT;
1139 }
1140
1091 CASE (Bunwind_protect): /* FIXME: avoid closure for lexbind. */ 1141 CASE (Bunwind_protect): /* FIXME: avoid closure for lexbind. */
1092 record_unwind_protect (unwind_body, POP); 1142 {
1093 NEXT; 1143 Lisp_Object handler = POP;
1144 /* Support for a function here is new in 24.4. */
1145 record_unwind_protect (NILP (Ffunctionp (handler))
1146 ? unwind_body : bcall0,
1147 handler);
1148 NEXT;
1149 }
1094 1150
1095 CASE (Bcondition_case): /* FIXME: ill-suited for lexbind. */ 1151 CASE (Bcondition_case): /* Obsolete since 24.4. */
1096 { 1152 {
1097 Lisp_Object handlers, body; 1153 Lisp_Object handlers, body;
1098 handlers = POP; 1154 handlers = POP;
@@ -1884,7 +1940,10 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth,
1884 /* Actually this is Bstack_ref with offset 0, but we use Bdup 1940 /* Actually this is Bstack_ref with offset 0, but we use Bdup
1885 for that instead. */ 1941 for that instead. */
1886 /* CASE (Bstack_ref): */ 1942 /* CASE (Bstack_ref): */
1887 error ("Invalid byte opcode"); 1943 call3 (intern ("error"),
1944 build_string ("Invalid byte opcode: op=%s, ptr=%d"),
1945 make_number (op),
1946 make_number ((stack.pc - 1) - stack.byte_string_start));
1888 1947
1889 /* Handy byte-codes for lexical binding. */ 1948 /* Handy byte-codes for lexical binding. */
1890 CASE (Bstack_ref1): 1949 CASE (Bstack_ref1):
@@ -1957,11 +2016,11 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth,
1957 2016
1958 /* Binds and unbinds are supposed to be compiled balanced. */ 2017 /* Binds and unbinds are supposed to be compiled balanced. */
1959 if (SPECPDL_INDEX () != count) 2018 if (SPECPDL_INDEX () != count)
1960#ifdef BYTE_CODE_SAFE 2019 {
1961 error ("binding stack not balanced (serious byte compiler bug)"); 2020 if (SPECPDL_INDEX () > count)
1962#else 2021 unbind_to (count, Qnil);
1963 emacs_abort (); 2022 error ("binding stack not balanced (serious byte compiler bug)");
1964#endif 2023 }
1965 2024
1966 return result; 2025 return result;
1967} 2026}
diff --git a/src/eval.c b/src/eval.c
index 6e964f6604b..5526b28b2e0 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -32,20 +32,8 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
32#include "xterm.h" 32#include "xterm.h"
33#endif 33#endif
34 34
35#if !BYTE_MARK_STACK 35/* Chain of condition and catch handlers currently in effect. */
36static
37#endif
38struct catchtag *catchlist;
39
40/* Chain of condition handlers currently in effect.
41 The elements of this chain are contained in the stack frames
42 of Fcondition_case and internal_condition_case.
43 When an error is signaled (by calling Fsignal, below),
44 this chain is searched for an element that applies. */
45 36
46#if !BYTE_MARK_STACK
47static
48#endif
49struct handler *handlerlist; 37struct handler *handlerlist;
50 38
51#ifdef DEBUG_GCPRO 39#ifdef DEBUG_GCPRO
@@ -92,7 +80,7 @@ union specbinding *specpdl_ptr;
92 80
93/* Depth in Lisp evaluations and function calls. */ 81/* Depth in Lisp evaluations and function calls. */
94 82
95static EMACS_INT lisp_eval_depth; 83EMACS_INT lisp_eval_depth;
96 84
97/* The value of num_nonmacro_input_events as of the last time we 85/* The value of num_nonmacro_input_events as of the last time we
98 started to enter the debugger. If we decide to enter the debugger 86 started to enter the debugger. If we decide to enter the debugger
@@ -253,8 +241,7 @@ void
253init_eval (void) 241init_eval (void)
254{ 242{
255 specpdl_ptr = specpdl; 243 specpdl_ptr = specpdl;
256 catchlist = 0; 244 handlerlist = NULL;
257 handlerlist = 0;
258 Vquit_flag = Qnil; 245 Vquit_flag = Qnil;
259 debug_on_next_call = 0; 246 debug_on_next_call = 0;
260 lisp_eval_depth = 0; 247 lisp_eval_depth = 0;
@@ -1093,28 +1080,26 @@ Lisp_Object
1093internal_catch (Lisp_Object tag, Lisp_Object (*func) (Lisp_Object), Lisp_Object arg) 1080internal_catch (Lisp_Object tag, Lisp_Object (*func) (Lisp_Object), Lisp_Object arg)
1094{ 1081{
1095 /* This structure is made part of the chain `catchlist'. */ 1082 /* This structure is made part of the chain `catchlist'. */
1096 struct catchtag c; 1083 struct handler *c;
1097 1084
1098 /* Fill in the components of c, and put it on the list. */ 1085 /* Fill in the components of c, and put it on the list. */
1099 c.next = catchlist; 1086 PUSH_HANDLER (c, tag, CATCHER);
1100 c.tag = tag;
1101 c.val = Qnil;
1102 c.handlerlist = handlerlist;
1103 c.lisp_eval_depth = lisp_eval_depth;
1104 c.pdlcount = SPECPDL_INDEX ();
1105 c.poll_suppress_count = poll_suppress_count;
1106 c.interrupt_input_blocked = interrupt_input_blocked;
1107 c.gcpro = gcprolist;
1108 c.byte_stack = byte_stack_list;
1109 catchlist = &c;
1110 1087
1111 /* Call FUNC. */ 1088 /* Call FUNC. */
1112 if (! sys_setjmp (c.jmp)) 1089 if (! sys_setjmp (c->jmp))
1113 c.val = (*func) (arg); 1090 {
1114 1091 Lisp_Object val = (*func) (arg);
1115 /* Throw works by a longjmp that comes right here. */ 1092 eassert (handlerlist == c);
1116 catchlist = c.next; 1093 handlerlist = c->next;
1117 return c.val; 1094 return val;
1095 }
1096 else
1097 { /* Throw works by a longjmp that comes right here. */
1098 Lisp_Object val = handlerlist->val;
1099 eassert (handlerlist == c);
1100 handlerlist = handlerlist->next;
1101 return val;
1102 }
1118} 1103}
1119 1104
1120/* Unwind the specbind, catch, and handler stacks back to CATCH, and 1105/* Unwind the specbind, catch, and handler stacks back to CATCH, and
@@ -1134,7 +1119,7 @@ internal_catch (Lisp_Object tag, Lisp_Object (*func) (Lisp_Object), Lisp_Object
1134 This is used for correct unwinding in Fthrow and Fsignal. */ 1119 This is used for correct unwinding in Fthrow and Fsignal. */
1135 1120
1136static _Noreturn void 1121static _Noreturn void
1137unwind_to_catch (struct catchtag *catch, Lisp_Object value) 1122unwind_to_catch (struct handler *catch, Lisp_Object value)
1138{ 1123{
1139 bool last_time; 1124 bool last_time;
1140 1125
@@ -1148,16 +1133,17 @@ unwind_to_catch (struct catchtag *catch, Lisp_Object value)
1148 1133
1149 do 1134 do
1150 { 1135 {
1151 last_time = catchlist == catch;
1152
1153 /* Unwind the specpdl stack, and then restore the proper set of 1136 /* Unwind the specpdl stack, and then restore the proper set of
1154 handlers. */ 1137 handlers. */
1155 unbind_to (catchlist->pdlcount, Qnil); 1138 unbind_to (handlerlist->pdlcount, Qnil);
1156 handlerlist = catchlist->handlerlist; 1139 last_time = handlerlist == catch;
1157 catchlist = catchlist->next; 1140 if (! last_time)
1141 handlerlist = handlerlist->next;
1158 } 1142 }
1159 while (! last_time); 1143 while (! last_time);
1160 1144
1145 eassert (handlerlist == catch);
1146
1161 byte_stack_list = catch->byte_stack; 1147 byte_stack_list = catch->byte_stack;
1162 gcprolist = catch->gcpro; 1148 gcprolist = catch->gcpro;
1163#ifdef DEBUG_GCPRO 1149#ifdef DEBUG_GCPRO
@@ -1173,12 +1159,12 @@ DEFUN ("throw", Fthrow, Sthrow, 2, 2, 0,
1173Both TAG and VALUE are evalled. */) 1159Both TAG and VALUE are evalled. */)
1174 (register Lisp_Object tag, Lisp_Object value) 1160 (register Lisp_Object tag, Lisp_Object value)
1175{ 1161{
1176 register struct catchtag *c; 1162 struct handler *c;
1177 1163
1178 if (!NILP (tag)) 1164 if (!NILP (tag))
1179 for (c = catchlist; c; c = c->next) 1165 for (c = handlerlist; c; c = c->next)
1180 { 1166 {
1181 if (EQ (c->tag, tag)) 1167 if (c->type == CATCHER && EQ (c->tag_or_ch, tag))
1182 unwind_to_catch (c, value); 1168 unwind_to_catch (c, value);
1183 } 1169 }
1184 xsignal2 (Qno_catch, tag, value); 1170 xsignal2 (Qno_catch, tag, value);
@@ -1244,15 +1230,16 @@ internal_lisp_condition_case (volatile Lisp_Object var, Lisp_Object bodyform,
1244 Lisp_Object handlers) 1230 Lisp_Object handlers)
1245{ 1231{
1246 Lisp_Object val; 1232 Lisp_Object val;
1247 struct catchtag c; 1233 struct handler *c;
1248 struct handler h; 1234 struct handler *oldhandlerlist = handlerlist;
1235 int clausenb = 0;
1249 1236
1250 CHECK_SYMBOL (var); 1237 CHECK_SYMBOL (var);
1251 1238
1252 for (val = handlers; CONSP (val); val = XCDR (val)) 1239 for (val = handlers; CONSP (val); val = XCDR (val))
1253 { 1240 {
1254 Lisp_Object tem; 1241 Lisp_Object tem = XCAR (val);
1255 tem = XCAR (val); 1242 clausenb++;
1256 if (! (NILP (tem) 1243 if (! (NILP (tem)
1257 || (CONSP (tem) 1244 || (CONSP (tem)
1258 && (SYMBOLP (XCAR (tem)) 1245 && (SYMBOLP (XCAR (tem))
@@ -1261,39 +1248,50 @@ internal_lisp_condition_case (volatile Lisp_Object var, Lisp_Object bodyform,
1261 SDATA (Fprin1_to_string (tem, Qt))); 1248 SDATA (Fprin1_to_string (tem, Qt)));
1262 } 1249 }
1263 1250
1264 c.tag = Qnil; 1251 { /* The first clause is the one that should be checked first, so it should
1265 c.val = Qnil; 1252 be added to handlerlist last. So we build in `clauses' a table that
1266 c.handlerlist = handlerlist; 1253 contains `handlers' but in reverse order. */
1267 c.lisp_eval_depth = lisp_eval_depth; 1254 Lisp_Object *clauses = alloca (clausenb * sizeof (Lisp_Object *));
1268 c.pdlcount = SPECPDL_INDEX (); 1255 int i = clausenb;
1269 c.poll_suppress_count = poll_suppress_count; 1256 for (val = handlers; CONSP (val); val = XCDR (val))
1270 c.interrupt_input_blocked = interrupt_input_blocked; 1257 clauses[--i] = XCAR (val);
1271 c.gcpro = gcprolist; 1258 for (i = 0; i < clausenb; i++)
1272 c.byte_stack = byte_stack_list; 1259 {
1273 if (sys_setjmp (c.jmp)) 1260 Lisp_Object clause = clauses[i];
1274 { 1261 Lisp_Object condition = XCAR (clause);
1275 if (!NILP (h.var)) 1262 if (!CONSP (condition))
1276 specbind (h.var, c.val); 1263 condition = Fcons (condition, Qnil);
1277 val = Fprogn (Fcdr (h.chosen_clause)); 1264 PUSH_HANDLER (c, condition, CONDITION_CASE);
1278 1265 if (sys_setjmp (c->jmp))
1279 /* Note that this just undoes the binding of h.var; whoever 1266 {
1280 longjumped to us unwound the stack to c.pdlcount before 1267 ptrdiff_t count = SPECPDL_INDEX ();
1281 throwing. */ 1268 Lisp_Object val = handlerlist->val;
1282 unbind_to (c.pdlcount, Qnil); 1269 Lisp_Object *chosen_clause = clauses;
1283 return val; 1270 for (c = handlerlist->next; c != oldhandlerlist; c = c->next)
1271 chosen_clause++;
1272 handlerlist = oldhandlerlist;
1273 if (!NILP (var))
1274 {
1275 if (!NILP (Vinternal_interpreter_environment))
1276 specbind (Qinternal_interpreter_environment,
1277 Fcons (Fcons (var, val),
1278 Vinternal_interpreter_environment));
1279 else
1280 specbind (var, val);
1281 }
1282 val = Fprogn (XCDR (*chosen_clause));
1283 /* Note that this just undoes the binding of var; whoever
1284 longjumped to us unwound the stack to c.pdlcount before
1285 throwing. */
1286 if (!NILP (var))
1287 unbind_to (count, Qnil);
1288 return val;
1289 }
1290 }
1284 } 1291 }
1285 c.next = catchlist;
1286 catchlist = &c;
1287
1288 h.var = var;
1289 h.handler = handlers;
1290 h.next = handlerlist;
1291 h.tag = &c;
1292 handlerlist = &h;
1293 1292
1294 val = eval_sub (bodyform); 1293 val = eval_sub (bodyform);
1295 catchlist = c.next; 1294 handlerlist = oldhandlerlist;
1296 handlerlist = h.next;
1297 return val; 1295 return val;
1298} 1296}
1299 1297
@@ -1312,33 +1310,20 @@ internal_condition_case (Lisp_Object (*bfun) (void), Lisp_Object handlers,
1312 Lisp_Object (*hfun) (Lisp_Object)) 1310 Lisp_Object (*hfun) (Lisp_Object))
1313{ 1311{
1314 Lisp_Object val; 1312 Lisp_Object val;
1315 struct catchtag c; 1313 struct handler *c;
1316 struct handler h; 1314
1317 1315 PUSH_HANDLER (c, handlers, CONDITION_CASE);
1318 c.tag = Qnil; 1316 if (sys_setjmp (c->jmp))
1319 c.val = Qnil; 1317 {
1320 c.handlerlist = handlerlist; 1318 Lisp_Object val = handlerlist->val;
1321 c.lisp_eval_depth = lisp_eval_depth; 1319 eassert (handlerlist == c);
1322 c.pdlcount = SPECPDL_INDEX (); 1320 handlerlist = handlerlist->next;
1323 c.poll_suppress_count = poll_suppress_count; 1321 return (*hfun) (val);
1324 c.interrupt_input_blocked = interrupt_input_blocked; 1322 }
1325 c.gcpro = gcprolist;
1326 c.byte_stack = byte_stack_list;
1327 if (sys_setjmp (c.jmp))
1328 {
1329 return (*hfun) (c.val);
1330 }
1331 c.next = catchlist;
1332 catchlist = &c;
1333 h.handler = handlers;
1334 h.var = Qnil;
1335 h.next = handlerlist;
1336 h.tag = &c;
1337 handlerlist = &h;
1338 1323
1339 val = (*bfun) (); 1324 val = (*bfun) ();
1340 catchlist = c.next; 1325 eassert (handlerlist == c);
1341 handlerlist = h.next; 1326 handlerlist = c->next;
1342 return val; 1327 return val;
1343} 1328}
1344 1329
@@ -1349,33 +1334,20 @@ internal_condition_case_1 (Lisp_Object (*bfun) (Lisp_Object), Lisp_Object arg,
1349 Lisp_Object handlers, Lisp_Object (*hfun) (Lisp_Object)) 1334 Lisp_Object handlers, Lisp_Object (*hfun) (Lisp_Object))
1350{ 1335{
1351 Lisp_Object val; 1336 Lisp_Object val;
1352 struct catchtag c; 1337 struct handler *c;
1353 struct handler h; 1338
1354 1339 PUSH_HANDLER (c, handlers, CONDITION_CASE);
1355 c.tag = Qnil; 1340 if (sys_setjmp (c->jmp))
1356 c.val = Qnil; 1341 {
1357 c.handlerlist = handlerlist; 1342 Lisp_Object val = handlerlist->val;
1358 c.lisp_eval_depth = lisp_eval_depth; 1343 eassert (handlerlist == c);
1359 c.pdlcount = SPECPDL_INDEX (); 1344 handlerlist = handlerlist->next;
1360 c.poll_suppress_count = poll_suppress_count; 1345 return (*hfun) (val);
1361 c.interrupt_input_blocked = interrupt_input_blocked; 1346 }
1362 c.gcpro = gcprolist;
1363 c.byte_stack = byte_stack_list;
1364 if (sys_setjmp (c.jmp))
1365 {
1366 return (*hfun) (c.val);
1367 }
1368 c.next = catchlist;
1369 catchlist = &c;
1370 h.handler = handlers;
1371 h.var = Qnil;
1372 h.next = handlerlist;
1373 h.tag = &c;
1374 handlerlist = &h;
1375 1347
1376 val = (*bfun) (arg); 1348 val = (*bfun) (arg);
1377 catchlist = c.next; 1349 eassert (handlerlist == c);
1378 handlerlist = h.next; 1350 handlerlist = c->next;
1379 return val; 1351 return val;
1380} 1352}
1381 1353
@@ -1390,33 +1362,20 @@ internal_condition_case_2 (Lisp_Object (*bfun) (Lisp_Object, Lisp_Object),
1390 Lisp_Object (*hfun) (Lisp_Object)) 1362 Lisp_Object (*hfun) (Lisp_Object))
1391{ 1363{
1392 Lisp_Object val; 1364 Lisp_Object val;
1393 struct catchtag c; 1365 struct handler *c;
1394 struct handler h; 1366
1395 1367 PUSH_HANDLER (c, handlers, CONDITION_CASE);
1396 c.tag = Qnil; 1368 if (sys_setjmp (c->jmp))
1397 c.val = Qnil; 1369 {
1398 c.handlerlist = handlerlist; 1370 Lisp_Object val = handlerlist->val;
1399 c.lisp_eval_depth = lisp_eval_depth; 1371 eassert (handlerlist == c);
1400 c.pdlcount = SPECPDL_INDEX (); 1372 handlerlist = handlerlist->next;
1401 c.poll_suppress_count = poll_suppress_count; 1373 return (*hfun) (val);
1402 c.interrupt_input_blocked = interrupt_input_blocked; 1374 }
1403 c.gcpro = gcprolist;
1404 c.byte_stack = byte_stack_list;
1405 if (sys_setjmp (c.jmp))
1406 {
1407 return (*hfun) (c.val);
1408 }
1409 c.next = catchlist;
1410 catchlist = &c;
1411 h.handler = handlers;
1412 h.var = Qnil;
1413 h.next = handlerlist;
1414 h.tag = &c;
1415 handlerlist = &h;
1416 1375
1417 val = (*bfun) (arg1, arg2); 1376 val = (*bfun) (arg1, arg2);
1418 catchlist = c.next; 1377 eassert (handlerlist == c);
1419 handlerlist = h.next; 1378 handlerlist = c->next;
1420 return val; 1379 return val;
1421} 1380}
1422 1381
@@ -1433,33 +1392,20 @@ internal_condition_case_n (Lisp_Object (*bfun) (ptrdiff_t, Lisp_Object *),
1433 Lisp_Object *args)) 1392 Lisp_Object *args))
1434{ 1393{
1435 Lisp_Object val; 1394 Lisp_Object val;
1436 struct catchtag c; 1395 struct handler *c;
1437 struct handler h; 1396
1438 1397 PUSH_HANDLER (c, handlers, CONDITION_CASE);
1439 c.tag = Qnil; 1398 if (sys_setjmp (c->jmp))
1440 c.val = Qnil; 1399 {
1441 c.handlerlist = handlerlist; 1400 Lisp_Object val = handlerlist->val;
1442 c.lisp_eval_depth = lisp_eval_depth; 1401 eassert (handlerlist == c);
1443 c.pdlcount = SPECPDL_INDEX (); 1402 handlerlist = handlerlist->next;
1444 c.poll_suppress_count = poll_suppress_count; 1403 return (*hfun) (val, nargs, args);
1445 c.interrupt_input_blocked = interrupt_input_blocked; 1404 }
1446 c.gcpro = gcprolist;
1447 c.byte_stack = byte_stack_list;
1448 if (sys_setjmp (c.jmp))
1449 {
1450 return (*hfun) (c.val, nargs, args);
1451 }
1452 c.next = catchlist;
1453 catchlist = &c;
1454 h.handler = handlers;
1455 h.var = Qnil;
1456 h.next = handlerlist;
1457 h.tag = &c;
1458 handlerlist = &h;
1459 1405
1460 val = (*bfun) (nargs, args); 1406 val = (*bfun) (nargs, args);
1461 catchlist = c.next; 1407 eassert (handlerlist == c);
1462 handlerlist = h.next; 1408 handlerlist = c->next;
1463 return val; 1409 return val;
1464} 1410}
1465 1411
@@ -1551,7 +1497,9 @@ See also the function `condition-case'. */)
1551 1497
1552 for (h = handlerlist; h; h = h->next) 1498 for (h = handlerlist; h; h = h->next)
1553 { 1499 {
1554 clause = find_handler_clause (h->handler, conditions); 1500 if (h->type != CONDITION_CASE)
1501 continue;
1502 clause = find_handler_clause (h->tag_or_ch, conditions);
1555 if (!NILP (clause)) 1503 if (!NILP (clause))
1556 break; 1504 break;
1557 } 1505 }
@@ -1568,7 +1516,7 @@ See also the function `condition-case'. */)
1568 && !NILP (Fmemq (Qdebug, XCAR (clause)))) 1516 && !NILP (Fmemq (Qdebug, XCAR (clause))))
1569 /* Special handler that means "print a message and run debugger 1517 /* Special handler that means "print a message and run debugger
1570 if requested". */ 1518 if requested". */
1571 || EQ (h->handler, Qerror))) 1519 || EQ (h->tag_or_ch, Qerror)))
1572 { 1520 {
1573 bool debugger_called 1521 bool debugger_called
1574 = maybe_call_debugger (conditions, error_symbol, data); 1522 = maybe_call_debugger (conditions, error_symbol, data);
@@ -1583,12 +1531,11 @@ See also the function `condition-case'. */)
1583 Lisp_Object unwind_data 1531 Lisp_Object unwind_data
1584 = (NILP (error_symbol) ? data : Fcons (error_symbol, data)); 1532 = (NILP (error_symbol) ? data : Fcons (error_symbol, data));
1585 1533
1586 h->chosen_clause = clause; 1534 unwind_to_catch (h, unwind_data);
1587 unwind_to_catch (h->tag, unwind_data);
1588 } 1535 }
1589 else 1536 else
1590 { 1537 {
1591 if (catchlist != 0) 1538 if (handlerlist != 0)
1592 Fthrow (Qtop_level, Qt); 1539 Fthrow (Qtop_level, Qt);
1593 } 1540 }
1594 1541
@@ -1774,29 +1721,8 @@ find_handler_clause (Lisp_Object handlers, Lisp_Object conditions)
1774 for (h = handlers; CONSP (h); h = XCDR (h)) 1721 for (h = handlers; CONSP (h); h = XCDR (h))
1775 { 1722 {
1776 Lisp_Object handler = XCAR (h); 1723 Lisp_Object handler = XCAR (h);
1777 Lisp_Object condit, tem; 1724 if (!NILP (Fmemq (handler, conditions)))
1778 1725 return handlers;
1779 if (!CONSP (handler))
1780 continue;
1781 condit = XCAR (handler);
1782 /* Handle a single condition name in handler HANDLER. */
1783 if (SYMBOLP (condit))
1784 {
1785 tem = Fmemq (Fcar (handler), conditions);
1786 if (!NILP (tem))
1787 return handler;
1788 }
1789 /* Handle a list of condition names in handler HANDLER. */
1790 else if (CONSP (condit))
1791 {
1792 Lisp_Object tail;
1793 for (tail = condit; CONSP (tail); tail = XCDR (tail))
1794 {
1795 tem = Fmemq (XCAR (tail), conditions);
1796 if (!NILP (tem))
1797 return handler;
1798 }
1799 }
1800 } 1726 }
1801 1727
1802 return Qnil; 1728 return Qnil;
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