fix structure stack allocation for high-debug code
authorNikodemus Siivola <nikodemus@random-state.net>
Thu, 27 Sep 2012 07:18:33 +0000 (10:18 +0300)
committerNikodemus Siivola <nikodemus@random-state.net>
Sat, 6 Oct 2012 08:37:15 +0000 (11:37 +0300)
  * Allow values to flow through casts in good-for-dx analysis.

  * Let-convert main-entry points for already inlined optional
    dispatches.

  * Don't preserve single-use debug vars in system-lambdas, no
    matter what the policy says.

  * Don't add INDEFINITE-EXTENT declarations to hairy entries without
    &REST arguments.

  * SB-C::REST-CONVERSION optimization declaration was pretty
    pointless, take it out.

  * Test our DX stuff in high-debug code as well.

NEWS
src/code/cold-error.lisp
src/compiler/ir1opt.lisp
src/compiler/ir1util.lisp
src/compiler/locall.lisp
src/compiler/policies.lisp
tests/dynamic-extent.impure.lisp

diff --git a/NEWS b/NEWS
index 3b96778..f1a556d 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -4,6 +4,8 @@ changes relative to sbcl-1.1.0:
     COMPILE-FILE still do.)
   * bug fix: SB-CLTL2:MACROEXPAND-ALL correctly handles shadowing of symbol-macros
     by lexical bindings.
+  * bug fix: stack allocation was prevented by high DEBUG declaration in several
+    cases.
 
 changes in sbcl-1.1.0 relative to sbcl-1.0.58:
   * enhancement: New variable, sb-ext:*disassemble-annotate* for controlling
index fb4926c..e4e094c 100644 (file)
   #!+sb-doc
   "Print a message and invoke the debugger without allowing any possibility
 of condition handling occurring."
-  (declare (optimize (sb!c::rest-conversion 0)))
   (let ((*debugger-hook* nil) ; as specifically required by ANSI
         (sb!debug:*stack-top-hint* (or sb!debug:*stack-top-hint* 'break)))
     (apply #'%break 'break datum arguments)))
index 8a4d87e..7d4fdd2 100644 (file)
                               '(optimize
                                 (preserve-single-use-debug-variables 0))
                               (lexenv-policy
-                                   (combination-lexenv call)))))
+                               (combination-lexenv call)))))
   (with-ir1-environment-from-node call
     (with-component-last-block (*current-component*
                                 (block-next (node-block call)))
                            leaf var)))
                  t)))))
         ((and (null (rest (leaf-refs var)))
-              ;; Don't substitute single-ref variables on high-debug /
-              ;; low speed, to improve the debugging experience.
-              (policy call (< preserve-single-use-debug-variables 3))
+              (not (preserve-single-use-debug-var-p call var))
               (substitute-single-use-lvar arg var)))
         (t
          (propagate-to-refs var (lvar-type arg))))))
index 731b8db..2067422 100644 (file)
                    use))))
     (plu lvar)))
 
+(defun principal-lvar-dest (lvar)
+  (labels ((pld (lvar)
+             (declare (type lvar lvar))
+             (let ((dest (lvar-dest lvar)))
+               (if (cast-p dest)
+                   (pld (cast-lvar dest))
+                   dest))))
+    (pld lvar)))
+
 ;;; Update lvar use information so that NODE is no longer a use of its
 ;;; LVAR.
 ;;;
                        (when (lambda-p clambda1)
                          (dolist (var (lambda-vars clambda1) t)
                            (dolist (var-ref (lambda-var-refs var))
-                             (let ((dest (lvar-dest (ref-lvar var-ref))))
+                             (let ((dest (principal-lvar-dest (ref-lvar var-ref))))
                                (unless (and (combination-p dest) (recurse dest))
                                  (return-from combination-args-flow-cleanly-p nil)))))))))))
     (recurse combination1)))
@@ -2296,3 +2305,21 @@ is :ANY, the function name is not checked."
                (and ok (member name fun-names :test #'eq))))
          (or (not arg-count)
              (= arg-count (length (combination-args use)))))))
+
+;;; True if the optional has a rest-argument.
+(defun optional-rest-p (opt)
+  (dolist (var (optional-dispatch-arglist opt) nil)
+    (let* ((info (when (lambda-var-p var)
+                   (lambda-var-arg-info var)))
+           (kind (when info
+                   (arg-info-kind info))))
+      (when (eq :rest kind)
+        (return t)))))
+
+;;; Don't substitute single-ref variables on high-debug / low speed, to
+;;; improve the debugging experience. ...but don't bother keeping those
+;;; from system lambdas.
+(defun preserve-single-use-debug-var-p (call var)
+  (and (policy call (eql preserve-single-use-debug-variables 3))
+       (or (not (lambda-var-p var))
+           (not (lambda-system-lambda-p (lambda-var-home var))))))
index 2df985b..97372d3 100644 (file)
         (convert-hairy-fun-entry ref call (optional-dispatch-main-entry fun)
                                  (append temps more-temps)
                                  (ignores) (call-args)
-                                 more-temps))))
+                                 (when (optional-rest-p fun)
+                                   more-temps)))))
 
   (values))
 \f
   ;; with anonymous things, and suppressing inlining
   ;; for such things can easily give Python acute indigestion, so
   ;; we don't.)
-  (when (leaf-has-source-name-p clambda)
+  ;;
+  ;; A functional that is already inline-expanded in this componsne definitely
+  ;; deserves let-conversion -- and in case of main entry points for inline
+  ;; expanded optional dispatch, the main-etry isn't explicitly marked :INLINE
+  ;; even if the function really is.
+  (when (and (leaf-has-source-name-p clambda)
+             (not (functional-inline-expanded clambda)))
     ;; ANSI requires that explicit NOTINLINE be respected.
     (or (eq (lambda-inlinep clambda) :notinline)
         ;; If (= LET-CONVERSION 0) we can guess that inlining
index 043e375..7e3aaaf 100644 (file)
@@ -45,12 +45,6 @@ Enabling this option can increase heap consing of closures.")
   ("off" "maybe" "on" "on")
   "Control inline-substitution of used-once local functions.")
 
-(define-optimization-quality rest-conversion
-    (if (= debug 3) 0 3)
-  ("off" "maybe" "on" "on")
-  "Control conversion of &REST argments to &MORE arguments when
-only used as the final argument to APPLY.")
-
 (define-optimization-quality alien-funcall-saves-fp-and-pc
     (if (<= speed debug) 3 0)
   ("no" "maybe" "yes" "yes")
index 6c83f8a..6841e4d 100644 (file)
       sb-ext:*stack-allocate-dynamic-extent* t)
 
 (defmacro defun-with-dx (name arglist &body body)
-  `(defun ,name ,arglist
-     ,@body))
+  (let ((debug-name (sb-int:symbolicate name "-HIGH-DEBUG"))
+        (default-name (sb-int:symbolicate name "-DEFAULT")))
+    `(progn
+       (defun ,debug-name ,arglist
+         (declare (optimize debug))
+         ,@body)
+       (defun ,default-name ,arglist
+        ,@body)
+       (defun ,name (&rest args)
+         (apply #',debug-name args)
+         (apply #',default-name args)))))
 
 (declaim (notinline opaque-identity))
 (defun opaque-identity (x)
   (bdowning-2005-iv-16))
 
 (declaim (inline my-nconc))
-(defun-with-dx my-nconc (&rest lists)
+(defun my-nconc (&rest lists)
   (declare (dynamic-extent lists))
   (apply #'nconc lists))
 (defun-with-dx my-nconc-caller (a b c)