From 6d69dfcc438b3530fa922e518919158ccf1af497 Mon Sep 17 00:00:00 2001 From: Nikodemus Siivola Date: Wed, 26 Sep 2007 15:54:58 +0000 Subject: [PATCH] 1.0.10.6: nested DX allocation * 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 | 2 ++ OPTIMIZATIONS | 8 -------- src/compiler/locall.lisp | 29 +++++++++++++++++++---------- tests/dynamic-extent.impure.lisp | 16 ++++++++++++++++ version.lisp-expr | 2 +- 5 files changed, 38 insertions(+), 19 deletions(-) diff --git a/NEWS b/NEWS index d5d51ba30..6d940979c 100644 --- 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) diff --git a/OPTIMIZATIONS b/OPTIMIZATIONS index 44663eff6..47a7e4141 100644 --- a/OPTIMIZATIONS +++ b/OPTIMIZATIONS @@ -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. -------------------------------------------------------------------------------- diff --git a/src/compiler/locall.lisp b/src/compiler/locall.lisp index 2c413654b..4fe1a0e3c 100644 --- a/src/compiler/locall.lisp +++ b/src/compiler/locall.lisp @@ -43,21 +43,30 @@ (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)) diff --git a/tests/dynamic-extent.impure.lisp b/tests/dynamic-extent.impure.lisp index 704a55d18..4ec3d4d05 100644 --- a/tests/dynamic-extent.impure.lisp +++ b/tests/dynamic-extent.impure.lisp @@ -146,6 +146,20 @@ (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")) @@ -185,6 +199,8 @@ (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 diff --git a/version.lisp-expr b/version.lisp-expr index 758220a31..61760dbac 100644 --- a/version.lisp-expr +++ b/version.lisp-expr @@ -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" -- 2.11.4.GIT