1.0.10.6: nested DX allocation
authorNikodemus Siivola <nikodemus@random-state.net>
Wed, 26 Sep 2007 15:54:58 +0000 (15:54 +0000)
committerNikodemus Siivola <nikodemus@random-state.net>
Wed, 26 Sep 2007 15:54:58 +0000 (15:54 +0000)
* RECOGNIZE-DYNAMIC-EXTENT-LVARS needs to propagate DX information to
  combination arguments, so that

  (LET ((X (LIST (LIST 1 2) (LIST 3 4))))
    (DECLARE (DYNAMIC-EXTENT X))
    (FOO X))

  does the right thing.

NEWS
OPTIMIZATIONS
src/compiler/locall.lisp
tests/dynamic-extent.impure.lisp
version.lisp-expr

diff --git a/NEWS b/NEWS
index d5d51ba..6d94097 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -24,6 +24,8 @@ changes in sbcl-1.0.10 relative to sbcl-1.0.9:
   * enhancement: CONS can now stack-allocate on x86 and
     x86-64. (Earlier LIST and LIST* supported stack-allocation, but
     CONS did not:)
+  * enhancement: nested lists can now be stack allocated on
+    platforms providing stack allocation support.
   * enhancement: DEFINE-MODIFY-MACRO lambda-list information is
     now more readable in environments like Slime which display it.
     (thanks to Tobias C. Rittweiler)  
index 44663ef..47a7e41 100644 (file)
@@ -185,14 +185,6 @@ DX is not allocated on stack.
 Result of MAKE is not stack allocated, which means that
 stack-allocation of structures is impossible.
 --------------------------------------------------------------------------------
-#21
-(defun-with-dx foo ()
-  (let ((dx (list (list 1 2) (list 3 4))))
-    (declare (dynamic-extent dx))
-    ...))
-
-External list in DX is allocated on stack, but internal are not.
---------------------------------------------------------------------------------
 #22
 IR2 does not perform unused code flushing.
 --------------------------------------------------------------------------------
index 2c41365..4fe1a0e 100644 (file)
              (setf (car args) nil)))
   (values))
 
+
+(defun handle-nested-dynamic-extent-lvars (arg)
+  (let ((use (lvar-uses arg)))
+    ;; Stack analysis wants DX value generators to end their
+    ;; blocks. Uses of mupltiple used LVARs already end their blocks,
+    ;; so we just need to process used-once LVARs.
+    (when (node-p use)
+      (node-ends-block use))
+    ;; If the function result is DX, so are its arguments... This
+    ;; assumes that all our DX functions do not store their arguments
+    ;; anywhere -- just use, and maybe return.
+    (if (basic-combination-p use)
+        (cons arg (funcall (lambda (lists)
+                             (reduce #'append lists))
+                         (mapcar #'handle-nested-dynamic-extent-lvars (basic-combination-args use))))
+        (list arg))))
+
 (defun recognize-dynamic-extent-lvars (call fun)
   (declare (type combination call) (type clambda fun))
   (loop for arg in (basic-combination-args call)
         and var in (lambda-vars fun)
-        when (and arg
-                  (lambda-var-dynamic-extent var)
+        when (and arg (lambda-var-dynamic-extent var)
                   (not (lvar-dynamic-extent arg)))
-        collect arg into dx-lvars
-        and do (let ((use (lvar-uses arg)))
-                 ;; Stack analysis wants DX value generators to end
-                 ;; their blocks. Uses of mupltiple used LVARs already
-                 ;; end their blocks, so we just need to process
-                 ;; used-once LVARs.
-                 (when (node-p use)
-                   (node-ends-block use)))
+        append (handle-nested-dynamic-extent-lvars arg) into dx-lvars
         finally (when dx-lvars
                   (binding* ((before-ctran (node-prev call))
                              (nil (ensure-block-start before-ctran))
index 704a55d..4ec3d4d 100644 (file)
     (true cons)
     nil))
 
+;;; Nested DX
+
+(defun-with-dx nested-dx-lists ()
+  (let ((dx (list (list 1 2) (list 3 4))))
+    (declare (dynamic-extent dx))
+    (true dx)
+    nil))
+
+(defun-with-dx nested-dx-conses ()
+  (let ((dx (cons 1 (cons 2 (cons 3 (cons (cons t t) nil))))))
+    (declare (dynamic-extent dx))
+    (true dx)
+    nil))
+
 ;;; with-spinlock should use DX and not cons
 
 (defvar *slock* (sb-thread::make-spinlock :name "slocklock"))
   (assert-no-consing (test-lvar-subst 11))
   (assert-no-consing (dx-value-cell 13))
   (assert-no-consing (cons-on-stack 42))
+  (assert-no-consing (nested-dx-conses))
+  (assert-no-consing (nested-dx-lists))
   ;; Not strictly DX..
   (assert-no-consing (test-hash-table))
   #+sb-thread
index 758220a..61760db 100644 (file)
@@ -17,4 +17,4 @@
 ;;; checkins which aren't released. (And occasionally for internal
 ;;; versions, especially for internal versions off the main CVS
 ;;; branch, it gets hairier, e.g. "0.pre7.14.flaky4.13".)
-"1.0.10.5"
+"1.0.10.6"