[movitz-cvs] CVS update: movitz/compiler.lisp

Frode Vatvedt Fjeld ffjeld at common-lisp.net
Mon Jan 3 11:55:07 UTC 2005


Update of /project/movitz/cvsroot/movitz
In directory common-lisp.net:/tmp/cvs-serv9077

Modified Files:
	compiler.lisp 
Log Message:
Started support for stack-allocating functions (of dynamic
extent). Primary purpose is to evaluate e.g. handler-case without
having to cons up a function for each handler.

Date: Mon Jan  3 12:55:05 2005
Author: ffjeld

Index: movitz/compiler.lisp
diff -u movitz/compiler.lisp:1.123 movitz/compiler.lisp:1.124
--- movitz/compiler.lisp:1.123	Tue Dec 21 15:23:49 2004
+++ movitz/compiler.lisp	Mon Jan  3 12:55:04 2005
@@ -1,6 +1,6 @@
 ;;;;------------------------------------------------------------------
 ;;;; 
-;;;;    Copyright (C) 2001,2000, 2002-2004,
+;;;;    Copyright (C) 2001,2000, 2002-2005,
 ;;;;    Department of Computer Science, University of Tromso, Norway
 ;;;; 
 ;;;; Description:   A simple lisp compiler.
@@ -8,7 +8,7 @@
 ;;;; Created at:    Wed Oct 25 12:30:49 2000
 ;;;; Distribution:  See the accompanying file COPYING.
 ;;;;                
-;;;; $Id: compiler.lisp,v 1.123 2004/12/21 14:23:49 ffjeld Exp $
+;;;; $Id: compiler.lisp,v 1.124 2005/01/03 11:55:04 ffjeld Exp $
 ;;;;                
 ;;;;------------------------------------------------------------------
 
@@ -96,7 +96,7 @@
     (make-hash-table :test #'eq))
 
 
-(defconstant +enter-stack-frame-code+
+(defparameter +enter-stack-frame-code+
     '((:pushl :ebp)
       (:movl :esp :ebp)
       (:pushl :esi)))
@@ -189,6 +189,13 @@
    (funobj-env
     :initarg :funobj-env
     :accessor funobj-env)
+   (extent
+    :initarg :extent
+    :initform :unused
+    :accessor movitz-funobj-extent)
+   (allocation
+    :initform nil
+    :accessor movitz-allocation)
    (entry-protocol
     :initform :default
     :initarg :entry-protocol
@@ -643,18 +650,30 @@
 		     (:call-lexical
 		      (process-binding funobj (second instruction) '(:call)))
 		     (:load-lambda
-		      (let ((lambda-binding (second instruction)))
+		      (destructuring-bind (lambda-binding lambda-result-mode capture-env)
+			  (cdr instruction)
+			(declare (ignore lambda-result-mode))
 			(assert (eq funobj (binding-funobj lambda-binding)) ()
 			  "A non-local lambda doesn't make sense. There must be a bug.")
-			(resolve-sub-funobj funobj (function-binding-funobj lambda-binding))
-			(process-binding funobj lambda-binding '(:read))
-			;; This funobj is effectively using every binding that the lambda
-			;; is borrowing..
-			(map nil (lambda (borrowed-binding)
-				   (process-binding funobj
-						    (borrowed-binding-target borrowed-binding)
-						    '(:read)))
-			     (borrowed-bindings (function-binding-funobj lambda-binding)))))
+			(let ((lambda-funobj (function-binding-funobj lambda-binding)))
+			  (let ((dynamic-extent (dynamic-extent-allocation capture-env)))
+			    (when dynamic-extent
+			      (let ((dynamic-scope (allocation-env-scope dynamic-extent)))
+				;; (warn "Adding ~S to ~S/~S" lambda-funobj dynamic-extent dynamic-scope)
+				(setf (movitz-funobj-extent lambda-funobj) :dynamic-extent
+				      (movitz-allocation lambda-funobj) dynamic-scope)
+				(push lambda-funobj
+				      (dynamic-extent-scope-members (allocation-env-scope dynamic-extent)))
+				(process-binding funobj (base-binding dynamic-scope) '(:read)))))
+			  (resolve-sub-funobj funobj lambda-funobj)
+			  (process-binding funobj lambda-binding '(:read))
+			  ;; This funobj is effectively using every binding that the lambda
+			  ;; is borrowing..
+			  (map nil (lambda (borrowed-binding)
+				     (process-binding funobj
+						      (borrowed-binding-target borrowed-binding)
+						      '(:read)))
+			       (borrowed-bindings (function-binding-funobj lambda-binding))))))
 		     (:local-function-init
 		      (let ((function-binding (second instruction)))
 			(assert (eq funobj (binding-funobj function-binding)) ()
@@ -696,6 +715,7 @@
 		 do (pushnew borrowed-binding
 			     (getf (binding-lending (borrowed-binding-target borrowed-binding))
 				   :lended-to)))
+	     ;; (warn "old extent: ~S" (movitz-funobj-extent sub-funobj))
 	     (cond
 	      ((or (null usage)
 		   (null (borrowed-bindings sub-funobj)))
@@ -708,12 +728,16 @@
 	       (change-class function-binding 'closure-binding)
 	       (setf (movitz-funobj-extent sub-funobj)
 		 :lexical-extent))
+	      ((eq :dynamic-extent (movitz-funobj-extent sub-funobj))
+	       (change-class function-binding 'closure-binding))
 	      (t (change-class function-binding 'closure-binding)
 		 (setf (movitz-funobj-extent sub-funobj)
 		   :indefinite-extent))) ; XXX
-	     #+ignore (warn "extent: ~S => ~S"
-			    sub-funobj
-			    (movitz-funobj-extent sub-funobj)))))
+	     #+ignore
+	     (warn "extent usage ~S: ~S => ~S"
+		   usage
+		   sub-funobj
+		   (movitz-funobj-extent sub-funobj)))))
   (loop for function-binding in function-binding-usage by #'cddr
       do (finalize-funobj (function-binding-funobj function-binding)))
   (finalize-funobj toplevel-funobj))
@@ -1003,8 +1027,18 @@
 (defun check-locate-concistency (code-vector)
   (loop for x from 0 below (length code-vector) by 8
       do (when (and (= (tag :basic-vector) (aref code-vector x))
-		    (= (enum-value 'movitz-vector-element-type :code) (aref code-vector (1+ x))))
-	   (break "Code-vector can break %find-code-vector at offset ~D." x)))
+		    (= (enum-value 'movitz-vector-element-type :code) (aref code-vector (1+ x)))
+		    (or (<= #x4000 (length code-vector))
+			(and (= (ldb (byte 8 0) (length code-vector))
+				(aref code-vector (+ x 2)))
+			     (= (ldb (byte 8 8) (length code-vector))
+				(aref code-vector (+ x 3))))))
+	   (break "Code-vector (length #x~X) can break %find-code-vector at ~D: #x~2,'0X~2,'0X ~2,'0X~2,'0X."
+		  (length code-vector) x
+		  (aref code-vector (+ x 0))
+		  (aref code-vector (+ x 1))
+		  (aref code-vector (+ x 2))
+		  (aref code-vector (+ x 3)))))
   (values))
 
 #+ignore
@@ -1585,10 +1619,10 @@
 	       (0 nil)
 	       (1 (cadr c))
 	       (2 (twop-dst c)))))
-	 (non-destructuve-p (c)
+	 (non-destructive-p (c)
 	   (let ((c (ignore-instruction-prefixes c)))
 	     (and (consp c)
-		  (member (car c) '(:testl :testb :pushl :cmpl :cmpb :frame-map :std)))))
+		  (member (car c) '(:testl :testb :cmpl :cmpb :frame-map :std)))))
 	 (simple-instruction-p (c)
 	   (let ((c (ignore-instruction-prefixes c)))
 	     (and (listp c)
@@ -1627,7 +1661,7 @@
 		  (or (global-funcall-p i)
 		      (instruction-is i :frame-map)
 		      (branch-instruction-label i)
-		      (non-destructuve-p i)
+		      (non-destructive-p i)
 		      (and (simple-instruction-p i)
 			   (not (eql stack-location (stack-frame-operand (idst i)))))))))
 	 (preserves-register-p (i register)
@@ -1637,10 +1671,12 @@
 			   (not (eq register (idst i))))
 		      (instruction-is i :frame-map)
 		      (branch-instruction-label i)
-		      (non-destructuve-p i)
+		      (non-destructive-p i)
 		      (and (member register '(:edx))
 			   (member (global-funcall-p i)
-				   '(fast-car fast-cdr fast-car-ebx fast-cdr-ebx)))))))
+				   '(fast-car fast-cdr fast-car-ebx fast-cdr-ebx)))
+		      (and (not (eq register :esp))
+			   (instruction-is i :pushl))))))
 	 (operand-register-indirect-p (operand register)
 	   (and (consp operand)
 		(tree-search operand register)))
@@ -1811,7 +1847,7 @@
 					     (twop-src ii))
 				    (pushnew (store-stack-frame-p ii)
 					     modifieds))
-				   ((non-destructuve-p ii))
+				   ((non-destructive-p ii))
 				   ((branch-instruction-label ii))
 				   ((simple-instruction-p ii)
 				    (let ((op (idst ii)))
@@ -2813,14 +2849,16 @@
 	  (cdr (first init-pc))
 	(declare (ignore protect-registers protect-carry init-with-type))
 	(assert (eq binding init-binding))
-	(let* ((load-instruction
-		(find-if (lambda (i)
-			   (and (not (instruction-is i :init-lexvar))
-				(member binding (find-read-bindings i)
-					:test #'binding-eql)))
-			 (cdr init-pc)))
-	       (binding-destination (third load-instruction))
-	       (distance (position load-instruction (cdr init-pc))))
+	(multiple-value-bind (load-instruction binding-destination distance)
+	    (loop for i in (cdr init-pc) as distance upfrom 0
+		do (when (not (instruction-is i :init-lexvar))
+		     (multiple-value-bind (read-bindings read-destinations)
+			 (find-read-bindings i)
+		       (let ((pos (position binding read-bindings :test #'binding-eql)))
+			 (when pos
+			   (return (values i (nth pos read-destinations) distance)))))))
+	  (declare (ignore load-instruction))
+	  ;; (warn "load: ~S, dist: ~S, dest: ~S" load-instruction distance binding-destination)
 	  (multiple-value-bind (free-registers more-later-p)
 	      (and distance (compute-free-registers (cdr init-pc) distance funobj frame-map))
 	    (let ((free-registers-no-ecx (remove :ecx free-registers)))
@@ -2912,6 +2950,15 @@
 			  ((:local-function-init :load-lambda)
 			   (let ((function-binding (second instruction)))
 			     (take-note-of-binding function-binding)
+			     (let ((sub-funobj (function-binding-funobj function-binding)))
+			       #+ignore
+			       (warn "fun-ext: ~S ~S ~S"
+				     sub-funobj
+				     (movitz-funobj-extent sub-funobj)
+				     (movitz-allocation sub-funobj))
+			       (when (typep (movitz-allocation sub-funobj)
+					    'with-dynamic-extent-scope-env)
+				 (take-note-of-binding (base-binding (movitz-allocation sub-funobj)))))
 			     (let ((closure-funobj (function-binding-funobj function-binding)))
 			       (dolist (borrowing-binding (borrowed-bindings closure-funobj))
 				 (lend-lexical borrowing-binding nil)))))
@@ -3189,6 +3236,11 @@
 				(:load-lambda
 				 (or (when load
 				       (binding-eql binding (second instruction)))
+				     (let ((allocation (movitz-allocation
+							(function-binding-funobj (second instruction)))))
+				       (when (and load
+						  (typep allocation 'with-dynamic-extent-scope-env))
+					 (binding-eql binding (base-binding allocation))))
 				     (search-funobj (function-binding-funobj (second instruction))
 						    binding load store call)))
 				(:call-lexical
@@ -3321,9 +3373,6 @@
 			   code)
 		   env stack-frame-position frame-map))
 
-(defconstant +dynamic-frame-marker+ #xd193)
-(defconstant +dynamic-catch-marker+ #xd293)
-
 (defun single-value-register (mode)
   (ecase mode
     ((:eax :single-value :multiple-values :function) :eax)
@@ -3670,10 +3719,19 @@
 	       (assert (eq funobj-register :edx))
 	       (when (getf (binding-lending lended-binding) :dynamic-extent-p)
 		 (assert dynamic-extent-p))
-	       ;; (warn "lending: ~W" lended-binding)
+	       #+ignore
+	       (warn "lending: ~W: ~S"
+		     lended-binding
+		     (mapcar #'movitz-funobj-extent
+			     (mapcar #'binding-funobj 
+				     (getf (binding-lending lended-binding) :lended-to))))
 	       (append (make-load-lexical lended-binding :eax funobj t frame-map)
 		       (unless (or (typep lended-binding 'borrowed-binding)
-				   (getf (binding-lending lended-binding) :dynamic-extent-p))
+				   (getf (binding-lending lended-binding) :dynamic-extent-p)
+				   (every (lambda (borrower)
+					    (member (movitz-funobj-extent (binding-funobj borrower))
+						    '(:lexical-extent :dynamic-extent)))
+					  (getf (binding-lending lended-binding) :lended-to)))
 			 (append `((:pushl :edx)
 				   (:globally (:call (:edi (:edi-offset ensure-heap-cons-variable))))
 				   (:popl :edx))
@@ -3754,8 +3812,23 @@
 			nil)
 		       ((typep function-binding 'funobj-binding)
 			nil)
-		       (t (when (null (borrowed-bindings sub-funobj))
-			    (warn "null lending for ~S" sub-funobj))
+		       #+ignore
+		       ((member (movitz-funobj-extent sub-funobj)
+				'(:dynamic-extent :lexical-extent))
+			(check-type function-binding closure-binding)
+			(when (plusp (movitz-funobj-num-jumpers sub-funobj))
+			  (break "Don't know yet how to stack a funobj with jumpers."))
+			(let ((words (+ (movitz-funobj-num-constants sub-funobj)
+					(/ (sizeof 'movitz-funobj) 4))))
+			  (break "words for ~S: ~S" words sub-funobj)
+			  (append `((:movl :esp :eax)
+				    (:testl 4 :eax)
+				    (:jz 'no-alignment-needed)
+				    (:pushl :edi)
+				    no-alignment-needed)
+				  (make-load-constant sub-funobj :eax funobj frame-map)
+				  )))
+		       (t (assert (not (null (borrowed-bindings sub-funobj))))
 			  (append (make-load-constant sub-funobj :eax funobj frame-map)
 				  `((:movl (:edi ,(global-constant-offset 'copy-funobj)) :esi)
 				    (:call (:esi ,(bt:slot-offset 'movitz-funobj 'code-vector%1op)))
@@ -3765,8 +3838,9 @@
 				      append (make-lend-lexical bb :edx nil))))))
 		    funobj frame-map)))
 		(:load-lambda
-		 (destructuring-bind (function-binding register)
+		 (destructuring-bind (function-binding register capture-env)
 		     (operands instruction)
+		   (declare (ignore capture-env))
 		   ;; (warn "load-lambda not completed for ~S" function-binding)
 		   (finalize-code
 		    (let* ((sub-funobj (function-binding-funobj function-binding))
@@ -3777,6 +3851,17 @@
 		       ((null lend-code)
 			;; (warn "null lambda lending")
 			(append (make-load-constant sub-funobj register funobj frame-map)))
+		       ((typep (movitz-allocation sub-funobj)
+			       'with-dynamic-extent-scope-env)
+			(let ((dynamic-scope (movitz-allocation sub-funobj)))
+			  (append (make-load-lexical (base-binding dynamic-scope) :edx
+						     funobj nil frame-map)
+				  `((:leal (:edx ,(tag :other)
+						 ,(dynamic-extent-object-offset dynamic-scope
+										sub-funobj))
+					   :edx))
+				  lend-code
+				  `((:movl :edx ,register)))))
 		       (t (append (make-load-constant sub-funobj :eax funobj frame-map)
 				  `((:movl (:edi ,(global-constant-offset 'copy-funobj)) :esi)
 				    (:call (:esi ,(bt:slot-offset 'movitz-funobj 'code-vector%1op)))
@@ -3921,7 +4006,7 @@
 	    `((,op ,(new-make-compiled-constant-reference movitz-obj funobj)
 		   ,result-mode))))))))
 
-(defconstant +movitz-lambda-list-keywords+
+(defparameter +movitz-lambda-list-keywords+
     '(muerte.cl:&OPTIONAL
       muerte.cl:&REST
       muerte.cl:&KEY
@@ -5825,16 +5910,18 @@
     (assert (null unwind-protects) ()
       "Lexical unwind-protect not implemented, to-env: ~S. (this is not supposed to happen)"
       to-env)
+    ;; (warn "dist: ~S, slots: ~S" stack-distance num-dynamic-slots)
     (cond
      ((and (eq t stack-distance)
-	   (zerop num-dynamic-slots))
+	   (eql 0 num-dynamic-slots))
       (compiler-values ()
 	:returns :non-local-exit
 	:code (append return-code
 		      (unless (eq :function (exit-result-mode to-env))
-			`((:load-lexical ,(save-esp-variable to-env) :esp)))
+			`((:load-lexical ,(movitz-binding (save-esp-variable to-env) to-env nil) :esp)))
 		      `((:jmp ',to-label)))))
-     ((eq t stack-distance)
+     ((or (eq t stack-distance)
+	  (eq t num-dynamic-slots))
       (compiler-values ()
 	:returns :non-local-exit
 	:code (append return-code
@@ -5850,7 +5937,7 @@
 				   (:locally (:call (:edi (:edi-offset dynamic-unwind-next))))
 				   (:locally (:movl :eax (:edi (:edi-offset dynamic-env))))
 				   (:jc '(:sub-program () (:int 63))))))
-		      `((:load-lexical ,(save-esp-variable to-env) :esp)
+		      `((:load-lexical ,(movitz-binding (save-esp-variable to-env) to-env nil) :esp)
 			(:jmp ',to-label)))))
      ((zerop num-dynamic-slots)
       (compiler-values ()
@@ -5923,6 +6010,8 @@
 	     (+ x y)
 	   t))
        (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
 	  ((eq outer-env env)
 	   ;; Each dynamic-slot is 4 stack-distances, so let's check that..
@@ -5935,7 +6024,7 @@
 	   (values nil 0 nil))
 	  (t (find-stack-delta (movitz-environment-uplink env)
 			       (stack-distance-add stack-distance (stack-used env))
-			       (+ num-dynamic-slots (num-dynamic-slots env))
+			       (stack-distance-add num-dynamic-slots (num-dynamic-slots env))
 			       (if (typep env 'unwind-protect-env)
 				   (cons env unwind-protects)
 				 unwind-protects))))))
@@ -6000,9 +6089,7 @@
     (let* ((operator (car extended-instruction))
 	   (finder (gethash operator *extended-code-find-read-binding*)))
       (when finder
-	(let ((result (funcall finder extended-instruction)))
-	  (check-type result list "a list of read bindings")
-	  result)))))
+	(funcall finder extended-instruction)))))
 
 (defmacro define-find-write-binding-and-type (name lambda-list &body body)
   (let ((defun-name (intern
@@ -6098,9 +6185,9 @@
 	      (list source)))))
 
 (define-find-read-bindings :load-lexical (source destination &key &allow-other-keys)
-  (declare (ignore destination))
   (check-type source binding)
-  (list source))
+  (values (list source)
+	  (list destination)))
 
 (define-extended-code-expander :load-lexical (instruction funobj frame-map)
   (destructuring-bind (source destination &key shared-reference-p tmp-register protect-registers)
@@ -6781,3 +6868,67 @@
 			(:call (:esi ,(bt:slot-offset 'movitz-funobj 'code-vector%2op)))
 			,eql-done))))
 	   (t (error "unknown eql: ~S" instruction))))))))
+
+(define-find-read-bindings :load-lambda (lambda-binding result-mode capture-env)
+  (declare (ignore result-mode capture-env))
+  (let ((allocation (movitz-allocation (function-binding-funobj lambda-binding))))
+    (when (typep allocation 'with-dynamic-extent-scope-env)
+      (values (list (base-binding allocation))
+	      (list :edx)))))
+
+(define-find-write-binding-and-type :enter-dynamic-scope (instruction)
+  (destructuring-bind (scope-env)
+      (cdr instruction)
+    (if (null (dynamic-extent-scope-members scope-env))
+	(values nil)
+      (values (base-binding scope-env) 'fixnum))))
+
+(define-extended-code-expander :enter-dynamic-scope (instruction funobj frame-map)
+  (declare (ignore funobj frame-map))
+  (destructuring-bind (scope-env)
+      (cdr instruction)
+    (if (null (dynamic-extent-scope-members scope-env))
+	nil
+      (append `((:pushl :edi)
+		(:movl :esp :eax)
+		(:andl 4 :eax)
+		(:addl :eax :esp))
+	      (loop for object in (reverse (dynamic-extent-scope-members scope-env))
+		  appending
+		    (etypecase object
+		      (movitz-funobj
+		       (append (unless (zerop (mod (sizeof object) 8))
+				 `((:pushl :edi)))
+			       `((:load-constant ,object :eax))
+			       (loop for i from (1- (movitz-funobj-num-constants object))
+				   downto (movitz-funobj-num-jumpers object)
+				   collect `(:pushl (:eax ,(slot-offset 'movitz-funobj 'constant0)
+							  ,(* 4 i))))
+			       (loop repeat (movitz-funobj-num-jumpers object)
+				   do (error "Can't handle jumpers.")
+				   collect `(:pushl 0))
+			       `((:pushl (:eax ,(slot-offset 'movitz-funobj 'num-jumpers)))
+				 (:pushl (:eax ,(slot-offset 'movitz-funobj 'name)))
+				 (:pushl (:eax ,(slot-offset 'movitz-funobj 'lambda-list)))
+				 
+;;;				 (:pushl 0) ; %3op
+;;;				 (:pushl 0) ; %2op
+;;;				 (:pushl 0) ; %1op
+;;;				 (:pushl 0) ; (default)
+				 (:pushl (:eax ,(slot-offset 'movitz-funobj 'code-vector%3op)))
+				 (:pushl (:eax ,(slot-offset 'movitz-funobj 'code-vector%2op)))
+				 (:pushl (:eax ,(slot-offset 'movitz-funobj 'code-vector%1op)))
+				 (:pushl (:eax ,(slot-offset 'movitz-funobj 'code-vector)))
+				 
+				 (:pushl (:eax ,(slot-offset 'movitz-funobj 'type))))))))))))
+
+;;;(define-extended-code-expander :exit-dynamic-scope (instruction funobj frame-map)
+;;;  nil)
+
+(define-find-read-bindings :lexical-control-transfer (return-code return-mode from-env to-env
+								  &optional to-label)
+  (declare (ignore return-code return-mode to-label))
+  (let ((distance (stack-delta from-env to-env)))
+    (when (eq t distance)
+      (values (list (movitz-binding (save-esp-variable to-env) to-env nil))
+	      (list :esp)))))




More information about the Movitz-cvs mailing list