Update of /project/movitz/cvsroot/movitz In directory common-lisp.net:/tmp/cvs-serv26448
Modified Files: compiler.lisp Log Message: Re-worked several aspects of binding/environments: assignment, type-inference, etc.
Date: Sat Aug 20 22:30:44 2005 Author: ffjeld
Index: movitz/compiler.lisp diff -u movitz/compiler.lisp:1.149 movitz/compiler.lisp:1.150 --- movitz/compiler.lisp:1.149 Mon Aug 15 23:44:23 2005 +++ movitz/compiler.lisp Sat Aug 20 22:30:40 2005 @@ -8,7 +8,7 @@ ;;;; Created at: Wed Oct 25 12:30:49 2000 ;;;; Distribution: See the accompanying file COPYING. ;;;; -;;;; $Id: compiler.lisp,v 1.149 2005/08/15 21:44:23 ffjeld Exp $ +;;;; $Id: compiler.lisp,v 1.150 2005/08/20 20:30:40 ffjeld Exp $ ;;;; ;;;;------------------------------------------------------------------
@@ -473,7 +473,7 @@ (assert (or (typep type 'binding) (eql 1 (type-specifier-num-values type))) () "store-lexical with multiple-valued type: ~S for ~S" type binding) - ;; (warn "store ~S type ~S, thunk ~S" binding type thunk) + #+ignore (warn "store ~S type ~S, thunk ~S" binding type thunk) (let ((analysis (or (gethash binding binding-usage) (setf (gethash binding binding-usage) (make-type-analysis-with-declaration binding))))) @@ -492,14 +492,14 @@ (values-list (type-analysis-encoded-type analysis)) (type-specifier-encode type)))))))) (analyze-code (code) + #+ignore (print-code 'analyze code) (dolist (instruction code) (when (listp instruction) (multiple-value-bind (store-binding store-type thunk thunk-args) (find-written-binding-and-type instruction) (when store-binding - #+ignore - (warn "store: ~S binding ~S type ~S thunk ~S" - instruction store-binding store-type thunk) + #+ignore (warn "store: ~S binding ~S type ~S thunk ~S" + instruction store-binding store-type thunk) (analyze-store store-binding store-type thunk thunk-args))) (analyze-code (instruction-sub-program instruction))))) (analyze-funobj (funobj) @@ -617,6 +617,8 @@ ;; Binding is local to this funobj (typecase binding (forwarding-binding + (process-binding funobj (forwarding-binding-target binding) usages) + #+ignore (setf (forwarding-binding-target binding) (process-binding funobj (forwarding-binding-target binding) usages))) (function-binding @@ -2377,7 +2379,14 @@ :accessor binding-env) (declarations :initarg :declarations - :accessor binding-declarations))) + :accessor binding-declarations) + (extent-env + :accessor binding-extent-env + :initform nil))) + +(defmethod (setf binding-env) :after (env (binding binding)) + (unless (binding-extent-env binding) + (setf (binding-extent-env binding) env)))
(defmethod print-object ((object binding) stream) (print-unreadable-object (object stream :type t :identity t) @@ -2387,12 +2396,13 @@ (binding-name object)) (when (and (binding-target object) (not (eq object (binding-target object)))) - (binding-name (binding-target object))) + (binding-name (forwarding-binding-target object))) (when (and #+ignore (slot-exists-p object 'store-type) #+ignore (slot-boundp object 'store-type) (binding-store-type object)) - (apply #'encoded-type-decode - (binding-store-type object))))))) + (or (apply #'encoded-type-decode + (binding-store-type object)) + 'empty))))))
(defclass constant-object-binding (binding) ((object @@ -2653,11 +2663,11 @@ '((:int 100)) :test #'equalp)))
-(defun sub-environment-p (env1 env2) - (cond - ((eq env1 env2) t) - ((null env1) nil) - (t (sub-environment-p (movitz-environment-uplink env1) env2)))) +#+ignore (defun sub-environment-p (env1 env2) + (cond + ((eq env1 env2) t) + ((null env1) nil) + (t (sub-environment-p (movitz-environment-uplink env1) env2))))
(defun find-code-constants-and-jumpers (code &key include-programs) "Return code's constants (a plist of constants and their usage-counts) and jumper-sets." @@ -3006,7 +3016,7 @@ sub-environments found in CODE. A frame-map which is an assoc from bindings to stack-frame locations." ;; Then assign them to locations in the stack-frame. - ;; (warn "assigning code:~%~{~& ~A~}" code) + #+ignore (warn "assigning code:~%~{~& ~A~}" code) (check-type function-env function-env) (assert (= initial-stack-frame-position (1+ (frame-map-size frame-map)))) @@ -3022,10 +3032,42 @@ (error "SEFEW: ~S" function-env)) ;; The floor of this env is the roof of its extent-uplink. (t (assign-env-bindings (movitz-environment-extent-uplink env))))) + ;; PROMOTE FORW-BINDINGS TO UPPER ENV!! (assign-env-bindings (env) (or (getf env-roof-map env nil) (let* ((stack-frame-position (env-floor env)) (bindings-to-locate + (loop for binding being the hash-keys of var-counts + when (eq env (binding-extent-env binding)) + unless (let ((variable (binding-name binding))) + (cond + ((not (typep binding 'lexical-binding))) + ((typep binding 'lambda-binding)) + ((typep binding 'constant-object-binding)) + ((typep binding 'forwarding-binding) + ;; Immediately "assign" to target. + (when (plusp (or (car (gethash binding var-counts)) 0)) + (setf (new-binding-location binding frame-map) + (forwarding-binding-target binding))) + t) + ((typep binding 'borrowed-binding)) + ((typep binding 'funobj-binding)) + ((and (typep binding 'fixed-required-function-argument) + (plusp (or (car (gethash binding var-counts)) 0))) + (prog1 nil ; may need lending-cons + (setf (new-binding-location binding frame-map) + `(:argument-stack ,(function-argument-argnum binding))))) + ((unless (or (movitz-env-get variable 'ignore nil + (binding-env binding) nil) + (movitz-env-get variable 'ignorable nil + (binding-env binding) nil) + (typep binding 'hidden-rest-function-argument) + (third (gethash binding var-counts))) + (warn "Unused variable: ~S" + (binding-name binding)))) + ((not (plusp (or (car (gethash binding var-counts)) 0)))))) + collect binding) + #+ignore (loop for (variable . binding) in (movitz-environment-bindings env) unless (cond ((not (typep binding 'lexical-binding))) @@ -3087,6 +3129,22 @@ (cdr init-pc)) 15) count))))))))) + #+ignore (labels ((dox (env upper) + (if (or (not env) + (not (sub-env-p env function-env))) + 0 + (let ((level (dox (funcall upper env) upper))) + (format t "~%~v{ ~}~S" level t env) + (+ level 4))))) + (warn "At ~S binding ~S:~{ ~S~}: Extent: ~A~%Bind: ~A" + stack-frame-position + env bindings-to-locate + (with-output-to-string (*standard-output*) + (dox env #'movitz-environment-extent-uplink)) + (with-output-to-string (*standard-output*) + (when bindings-to-locate + (dox (binding-env (first bindings-to-locate)) + #'movitz-environment-uplink))))) ;; First, make several passes while trying to locate bindings ;; into registers. (loop repeat 100 with try-again = t and did-assign = t @@ -3181,6 +3239,8 @@ (setf (new-binding-location binding frame-map) `(:argument-stack ,(function-argument-argnum binding)))) (located-binding + #+ignore (warn "Assigning ~S at ~S" + binding stack-frame-position) (setf (new-binding-location binding frame-map) (post-incf stack-frame-position)))))) (setf (getf env-roof-map env) @@ -3190,7 +3250,7 @@ ;; do (warn "bind: ~S: ~S" binding (eq function-env (find-function-env env funobj))) when (sub-env-p env function-env) do (assign-env-bindings (binding-env binding))) - ;; (warn "Frame-map:~{ ~A~}" frame-map) + #+ignore (warn "Frame-map:~{ ~A~}" frame-map) frame-map)))
@@ -3269,7 +3329,7 @@ "Resolve a binding in terms of forwarding." (etypecase binding (forwarding-binding - (forwarding-binding-target binding)) + (binding-target (forwarding-binding-target binding))) (binding binding)))
@@ -3460,8 +3520,8 @@ ;;; :untagged-fixnum-ecx)) ((and binding-type (type-specifier-singleton decoded-type)) - (warn "Immloadlex: ~S" - (type-specifier-singleton decoded-type)) + #+ignore (warn "Immloadlex: ~S" + (type-specifier-singleton decoded-type)) (make-immediate-move (movitz-immediate-value (car (type-specifier-singleton decoded-type))) :ecx)) @@ -3571,6 +3631,7 @@ (located-binding (let ((binding-type (binding-store-type binding)) (binding-location (new-binding-location binding frame-map))) + #+ignore (warn "~S type: ~S" binding binding-type) (cond ((and (binding-lended-p binding) (not shared-reference-p)) @@ -5349,13 +5410,32 @@ :result-mode :eax :forward form-info)))))
-(define-compiler compile-form-unprotected (&all all &form form &result-mode result-mode) +(define-compiler compile-form-unprotected (&all downstream &form form &result-mode result-mode + &extent extent) "3.1.2.1 Form Evaluation. May not honor RESULT-MODE. That is, RESULT-MODE is taken to be a suggestion, not an imperative." - (typecase form - (symbol (compiler-call #'compile-symbol :forward all)) - (cons (compiler-call #'compile-cons :forward all)) - (t (compiler-call #'compile-self-evaluating :forward all)))) + (compiler-values-bind (&all upstream) + (typecase form + (symbol (compiler-call #'compile-symbol :forward downstream)) + (cons (compiler-call #'compile-cons :forward downstream)) + (t (compiler-call #'compile-self-evaluating :forward downstream))) + (when (typep (upstream :final-form) 'lexical-binding) + (labels ((fix-extent (binding) + (cond + ((sub-env-p extent (binding-extent-env binding)) + #+ignore (warn "Binding ~S OK in ~S wrt. ~S." + binding + (binding-extent-env binding) + (downstream :env))) + (t #+ignore (break "Binding ~S escapes from ~S to ~S" + binding (binding-extent-env binding) + extent) + (setf (binding-extent-env binding) extent))) + (when (typep binding 'forwarding-binding) + (fix-extent (forwarding-binding-target binding))))) + (when extent + (fix-extent (upstream :final-form))))) + (compiler-values (upstream))))
(defun lambda-form-p (form) (and (listp form) @@ -6092,17 +6172,20 @@ (:jne ',push-values-loop) ,push-values-done)))
+(defun stack-add (x y) + (if (and (integerp x) (integerp y)) + (+ x y) + t)) + +(define-modify-macro stack-incf (&optional (delta 1)) stack-add) + (defun stack-delta (inner-env outer-env) "Calculate the amount of stack-space used (in 32-bit stack slots) at the time of <inner-env> since <outer-env>, the number of intervening dynamic-slots (special bindings, unwind-protects, and catch-tags), and a list of any intervening unwind-protect environment-slots." (labels - ((stack-distance-add (x y) - (if (and (integerp x) (integerp y)) - (+ x y) - t)) - (find-stack-delta (env stack-distance num-dynamic-slots unwind-protects) + ((find-stack-delta (env stack-distance num-dynamic-slots unwind-protects) #+ignore (warn "find-stack-delta: ~S dist ~S, slots ~S" env (stack-used env) (num-dynamic-slots env)) (cond @@ -6116,8 +6199,8 @@ ((null env) (values nil 0 nil)) (t (find-stack-delta (movitz-environment-uplink env) - (stack-distance-add stack-distance (stack-used env)) - (stack-distance-add num-dynamic-slots (num-dynamic-slots env)) + (stack-add stack-distance (stack-used env)) + (stack-add num-dynamic-slots (num-dynamic-slots env)) (if (typep env 'unwind-protect-env) (cons env unwind-protects) unwind-protects)))))) @@ -6334,6 +6417,8 @@ ((not (typep init-with-register 'binding)) (assert init-with-type) (values binding init-with-type) ) + ((and init-with-type (not (bindingp init-with-type))) + (values binding init-with-type)) (t (values binding t (lambda (x) x) (list init-with-register))))) @@ -6701,12 +6786,18 @@ (warn "Add for lend0: ~S" destination)) (let ((loc0 (new-binding-location (binding-target term0) frame-map :default nil)) (loc1 (new-binding-location (binding-target term1) frame-map :default nil))) -;;; (warn "add: ~A" instruction) + #+ignore + (warn "add: ~A for ~A" instruction result-type) #+ignore (warn "add for: ~S is ~A, from ~A/~A and ~A/~A." destination result-type term0 loc0 term1 loc1) + #+ignore + (when (eql loc0 loc1) + (warn "add for:~%~A/~A in ~S~&~A/~A in ~S." + term0 loc0 (binding-extent-env (binding-target term0)) + term1 loc1 (binding-extent-env (binding-target term1)))) (cond ((type-specifier-singleton result-type) ;; (break "constant add: ~S" instruction) @@ -6744,7 +6835,7 @@ ((and (movitz-subtypep type0 'fixnum) (movitz-subtypep type1 'fixnum) (movitz-subtypep result-type 'fixnum)) - ;; (warn "ADDX: ~S" instruction) + #+ignore (warn "ADDX: ~S" instruction) (cond ((and (type-specifier-singleton type0) (eq loc1 destination-location)) @@ -6752,10 +6843,14 @@ ((member destination-location '(:eax :ebx :ecx :edx)) `((:addl ,(movitz-immediate-value (car (type-specifier-singleton type0))) ,destination))) - (t (assert (integerp loc1)) - (break "check that this is correct..") - `((:addl ,(movitz-immediate-value (car (type-specifier-singleton type0))) - (:ebp ,(stack-frame-offset loc1))))))) + ((integerp loc1) + ;; (break "check that this is correct..") + `((:addl ,(movitz-immediate-value (car (type-specifier-singleton type0))) + (:ebp ,(stack-frame-offset loc1))))) + ((eq :argument-stack (operator loc1)) + `((:addl ,(movitz-immediate-value (car (type-specifier-singleton type0))) + (:ebp ,(argument-stack-offset (binding-target term1)))))) + (t (error "Don't know how to add this for loc1 ~S" loc1)))) ((and (type-specifier-singleton type0) (eq term1 destination) (integerp destination-location)) @@ -6768,41 +6863,44 @@ (append `((:addl ,(movitz-immediate-value (car (type-specifier-singleton type0))) ,loc1)) (make-store-lexical destination loc1 nil funobj frame-map))) - (t #+ignore (warn "ADD: ~A/~S = ~A/~S + ~A/~S,~%~A ~A" - destination-location - destination - loc0 term0 - loc1 term1 - (type-specifier-singleton type0) - (eq loc1 destination)) + ((and (integerp loc0) (integerp loc1) + (member destination-location '(:eax :ebx :ecx :edx))) + (append `((:movl (:ebp ,(stack-frame-offset loc0)) ,destination-location) + (:addl (:ebp ,(stack-frame-offset loc1)) ,destination-location)))) + (t (warn "ADD: ~A/~S = ~A/~S + ~A/~S" + destination-location + destination + loc0 term0 + loc1 term1) + #+ignore (warn "map: ~A" frame-map) ;;; (warn "ADDI: ~S" instruction) - (append (cond - ((type-specifier-singleton type0) - (append (make-load-lexical term1 :eax funobj nil frame-map) - (make-load-constant (car (type-specifier-singleton type0)) - :ebx funobj frame-map))) - ((type-specifier-singleton type1) - (append (make-load-lexical term0 :eax funobj nil frame-map) - (make-load-constant (car (type-specifier-singleton type1)) - :ebx funobj frame-map))) - ((and (eq :eax loc0) (eq :ebx loc1)) - nil) - ((and (eq :ebx loc0) (eq :eax loc1)) - nil) ; terms order isn't important - ((eq :eax loc1) - (append - (make-load-lexical term0 :ebx funobj nil frame-map))) - (t (append - (make-load-lexical term0 :eax funobj nil frame-map) - (make-load-lexical term1 :ebx funobj nil frame-map)))) - `((:movl (:edi ,(global-constant-offset '+)) :esi)) - (make-compiled-funcall-by-esi 2) - (etypecase destination - (symbol - (unless (eq destination :eax) - `((:movl :eax ,destination)))) - (binding - (make-store-lexical destination :eax nil funobj frame-map))))))) + (append (cond + ((type-specifier-singleton type0) + (append (make-load-lexical term1 :eax funobj nil frame-map) + (make-load-constant (car (type-specifier-singleton type0)) + :ebx funobj frame-map))) + ((type-specifier-singleton type1) + (append (make-load-lexical term0 :eax funobj nil frame-map) + (make-load-constant (car (type-specifier-singleton type1)) + :ebx funobj frame-map))) + ((and (eq :eax loc0) (eq :ebx loc1)) + nil) + ((and (eq :ebx loc0) (eq :eax loc1)) + nil) ; terms order isn't important + ((eq :eax loc1) + (append + (make-load-lexical term0 :ebx funobj nil frame-map))) + (t (append + (make-load-lexical term0 :eax funobj nil frame-map) + (make-load-lexical term1 :ebx funobj nil frame-map)))) + `((:movl (:edi ,(global-constant-offset '+)) :esi)) + (make-compiled-funcall-by-esi 2) + (etypecase destination + (symbol + (unless (eq destination :eax) + `((:movl :eax ,destination)))) + (binding + (make-store-lexical destination :eax nil funobj frame-map))))))) (t (append (cond ((type-specifier-singleton type0) (append (make-load-lexical term1 :eax funobj nil frame-map) @@ -6848,12 +6946,13 @@ (rotatef x y) (rotatef x-type y-type) (rotatef x-singleton y-singleton)) - (let (;; (x-loc (new-binding-location (binding-target x) frame-map :default nil)) + (let (#+ignore (x-loc (new-binding-location (binding-target x) frame-map :default nil)) (y-loc (new-binding-location (binding-target y) frame-map :default nil))) #+ignore - (warn "eql ~S/~S ~S/~S" - x x-loc - y y-loc) + (warn "eql ~S/~S xx~Xxx ~S/~S: ~S" + x x-loc (binding-target y) + y y-loc + instruction) (flet ((make-branch () (ecase (operator return-mode) (:boolean-branch-on-false