Update of /project/movitz/cvsroot/movitz
In directory common-lisp.net:/tmp/cvs-serv22528
Modified Files:
special-operators-cl.lisp
Log Message:
Fixed the block and return-from special-operators to work better in
the non-trivial cases (across function-boundaries, unwind-protects etc.)
Date: Sat Nov 13 15:49:52 2004
Author: ffjeld
Index: movitz/special-operators-cl.lisp
diff -u movitz/special-operators-cl.lisp:1.33 movitz/special-operators-cl.lisp:1.34
--- movitz/special-operators-cl.lisp:1.33 Fri Nov 12 16:13:47 2004
+++ movitz/special-operators-cl.lisp Sat Nov 13 15:49:51 2004
@@ -9,7 +9,7 @@
;;;; Created at: Fri Nov 24 16:31:11 2000
;;;; Distribution: See the accompanying file COPYING.
;;;;
-;;;; $Id: special-operators-cl.lisp,v 1.33 2004/11/12 15:13:47 ffjeld Exp $
+;;;; $Id: special-operators-cl.lisp,v 1.34 2004/11/13 14:49:51 ffjeld Exp $
;;;;
;;;;------------------------------------------------------------------
@@ -629,8 +629,7 @@
:returns last-returns
:functional-p nil))))
-(define-special-operator tagbody
- (&all forward &funobj funobj &form form &env env)
+(define-special-operator tagbody (&all forward &funobj funobj &form form &env env)
(let* ((save-esp-variable (gensym "tagbody-save-esp"))
(lexical-catch-tag-variable (gensym "tagbody-lexical-catch-tag-"))
(label-set-name (gensym "label-set-"))
@@ -744,7 +743,7 @@
;; The target jumper points to the tagbody's label-set.
;; Now, install correct jumper within tagbody as target.
`((:addl ,(* 4 label-id) (:edx 8))))
- (:globally (:call (:edi (:edi-offset dynamic-unwind-next))))
+ (:locally (:call (:edi (:edi-offset dynamic-unwind-next))))
;; have next-continuation in EAX, final-continuation in EDX
(:locally (:movl :edx (:edi (:edi-offset raw-scratch0)))) ; final continuation
(:locally (:movl :esi (:edi (:edi-offset scratch1))))
@@ -767,9 +766,10 @@
((:eax :eax :multiple-values :function :ebx :ecx :ignore)
result-mode)
(t :eax)))
- (block-returns-mode (case block-result-mode
+ (block-returns-mode (case (result-mode-type block-result-mode)
(:function :multiple-values)
(:ignore :nothing)
+ ((:boolean-branch-on-true :boolean-branch-on-false) :eax)
(t block-result-mode)))
(block-env (make-instance 'lexical-exit-point-env
:uplink env
@@ -779,13 +779,10 @@
:exit-label exit-block-label
:exit-result-mode block-result-mode))
(save-esp-binding (make-instance 'located-binding
- :name save-esp-variable))
- (lexical-catch-tag-binding (make-instance 'located-binding
- :name lexical-catch-tag-variable)))
+ :name save-esp-variable)))
(movitz-env-add-binding block-env save-esp-binding)
- (movitz-env-add-binding block-env lexical-catch-tag-binding)
- (movitz-env-load-declarations `((muerte.cl::ignorable ,save-esp-variable ,lexical-catch-tag-variable))
- block-env nil)
+ (movitz-env-load-declarations `((muerte.cl::ignorable ,save-esp-variable))
+ block-env nil)
(setf (movitz-env-get block-name :block-name nil block-env)
block-env)
(compiler-values-bind (&code block-code &functional-p block-no-side-effects-p)
@@ -794,14 +791,15 @@
:result-mode block-result-mode
:form `(muerte.cl:progn ,@body)
:env block-env)
- (let ((maybe-store-esp-code
- (when (and (not (eq block-result-mode :function))
+ (let ((label-set-name (gensym "block-label-set-"))
+ (maybe-store-esp-code
+ (when (and #+ignore (not (eq block-result-mode :function))
(operators-present-in-code-p block-code '(:lexical-control-transfer) nil
:test (lambda (x) (eq block-env (fifth x)))))
`((:init-lexvar ,save-esp-binding
:init-with-register :esp
:init-with-type t)))))
- (if (not (code-uses-binding-p block-code lexical-catch-tag-binding))
+ (if (not (code-uses-binding-p block-code save-esp-binding))
(compiler-values ()
:code (append maybe-store-esp-code
block-code
@@ -810,25 +808,29 @@
:functional-p block-no-side-effects-p)
(multiple-value-bind (new-code new-returns)
(make-result-and-returns-glue :multiple-values block-returns-mode block-code)
- (multiple-value-bind (stack-used wrapped-code)
- (make-compiled-catch-wrapper lexical-catch-tag-variable
- funobj block-env new-returns
- new-code)
- (incf (stack-used block-env) stack-used)
- (setf (num-specials block-env) 1) ; block-env now has one dynamic slot
- (compiler-values ()
- :code (append maybe-store-esp-code
- `((:movl :esp :eax)
- (:addl :eax :eax)
- (:xorl ,(ash (movitz-symbol-hash-key (movitz-read block-name)) 16) :eax)
- (:init-lexvar ,lexical-catch-tag-binding
- :init-with-register :eax
- :init-with-type t))
- wrapped-code
- (list exit-block-label))
- :returns block-returns-mode
- :functional-p block-no-side-effects-p)))))))))
-
+ (assert (eq :multiple-values new-returns))
+ (incf (stack-used block-env) 4)
+ (setf (num-specials block-env) 1) ; block-env now has one dynamic slot
+ (compiler-values ()
+ :code (append `((:declare-label-set ,label-set-name (,exit-block-label))
+ ;; catcher
+ (:locally (:pushl (:edi (:edi-offset dynamic-env))))
+ (:pushl ',label-set-name)
+ (:locally (:pushl (:edi (:edi-offset unbound-value))))
+ (:pushl :ebp)
+ (:locally (:movl :esp (:edi (:edi-offset dynamic-env)))))
+ `((:init-lexvar ,save-esp-binding
+ :init-with-register :esp
+ :init-with-type t))
+ new-code
+ ;; wrapped-code
+ `(,exit-block-label
+ (:movl (:esp 12) :edx)
+ (:locally (:movl :edx (:edi (:edi-offset dynamic-env))))
+ (:popl :ebp)
+ (:leal (:esp 12) :esp)))
+ :returns :multiple-values
+ :functional-p block-no-side-effects-p))))))))
(define-special-operator return-from (&all all &form form &env env &funobj funobj)
(destructuring-bind (block-name &optional result-form)
@@ -837,7 +839,8 @@
(assert block-env (block-name)
"Block-name not found for return-from: ~S." block-name)
(cond
- ((eq funobj (movitz-environment-funobj block-env))
+ ((and (eq funobj (movitz-environment-funobj block-env))
+ (null (nth-value 2 (stack-delta env block-env))))
(compiler-values-bind (&code return-code &returns return-mode)
(compiler-call #'compile-form
:forward all
@@ -847,12 +850,12 @@
:returns :non-local-exit
:code (append return-code
`((:lexical-control-transfer nil ,return-mode ,env ,block-env))))))
- ((not (eq funobj (movitz-environment-funobj block-env)))
+ ((not (and (eq funobj (movitz-environment-funobj block-env))
+ (null (nth-value 2 (stack-delta env block-env)))))
(compiler-call #'compile-form-unprotected
:forward all
- :form `(muerte.cl:throw
- ,(movitz-env-lexical-catch-tag-variable block-env)
- ,result-form)))))))
+ :form `(muerte::exact-throw ,(save-esp-variable block-env)
+ ,result-form)))))))
(define-special-operator require (&form form)
(let ((*require-dependency-chain*