* Extend EMIT-FIXED-ALLOC to support stack-allocation.
* Appropriate DEFOPTIMIZER for CONS.
Note: it seems like it should be a simple matter to support stack
allocation of all primitive objects allocated using the :ALLOC-TRANS
framework.
* optimization: UNION and NUNION are now O(N+M) for large
inputs as long as the :TEST function is one of EQ, EQL, EQUAL, or
EQUALP.
+ * enhancement: CONS can now stack-allocate on x86 and
+ x86-64. (Earlier LIST and LIST* supported stack-allocation, but
+ CONS did not:)
* enhancement: DEFINE-MODIFY-MACRO lambda-list information is
now more readable in environments like Slime which display it.
(thanks to Tobias C. Rittweiler)
altogether. The former option is probably easier than the latter.
--------------------------------------------------------------------------------
-#37
-
-Dynamic extent allocation doesn't currently work for one-element lists,
-since there's a source transform from (LIST X) to (CONS X NIL).
-
---------------------------------------------------------------------------------
#38
(setf (subseq s1 start1 end1) (subseq s2 start2 end1))
(define-vop (fixed-alloc)
(:args)
- (:info name words type lowtag)
- (:ignore name)
+ (:info name words type lowtag stack-allocate-p)
+ (:ignore name stack-allocate-p)
(:results (result :scs (descriptor-reg)))
(:temporary (:scs (non-descriptor-reg)) temp)
(:generator 4
(define-primitive-object (value-cell :lowtag other-pointer-lowtag
:widetag value-cell-header-widetag
+ ;; FIXME: We also have an explicit VOP
+ ;; for this. Is this needed as well?
:alloc-trans make-value-cell)
(value :set-trans value-cell-set
:set-known (unsafe)
name slot lowtag))))
(aver (null args)))
-(defun emit-fixed-alloc (node block name words type lowtag result)
- (vop fixed-alloc node block name words type lowtag result))
+(defun emit-fixed-alloc (node block name words type lowtag result lvar)
+ (let ((stack-allocate-p (and lvar (lvar-dynamic-extent lvar))))
+ (when stack-allocate-p
+ (vop current-stack-pointer node block
+ (ir2-lvar-stack-pointer (lvar-info lvar))))
+ (vop fixed-alloc node block name words type lowtag stack-allocate-p result)))
(defoptimizer ir2-convert-fixed-allocation
((&rest args) node block name words type lowtag inits)
(let* ((lvar (node-lvar node))
(locs (lvar-result-tns lvar (list *backend-t-primitive-type*)))
(result (first locs)))
- (emit-fixed-alloc node block name words type lowtag result)
+ (emit-fixed-alloc node block name words type lowtag result lvar)
(emit-inits node block name result lowtag inits args)
(move-lvar-result node block locs lvar)))
(result (first locs)))
(if (constant-lvar-p extra)
(let ((words (+ (lvar-value extra) words)))
- (emit-fixed-alloc node block name words type lowtag result))
+ (emit-fixed-alloc node block name words type lowtag result lvar))
(vop var-alloc node block (lvar-tn node block extra) name words
type lowtag result))
(emit-inits node block name result lowtag inits args)
(define-vop (fixed-alloc)
(:args)
- (:info name words type lowtag)
- (:ignore name)
+ (:info name words type lowtag stack-allocate-p)
+ (:ignore name stack-allocate-p)
(:results (result :scs (descriptor-reg)))
(:temporary (:scs (non-descriptor-reg)) temp)
(:generator 4
(define-vop (fixed-alloc)
(:args)
- (:info name words type lowtag)
- (:ignore name)
+ (:info name words type lowtag stack-allocate-p)
+ (:ignore name stack-allocate-p)
(:results (result :scs (descriptor-reg)))
(:temporary (:scs (non-descriptor-reg)) temp)
(:temporary (:sc non-descriptor-reg :offset nl4-offset) pa-flag)
(define-vop (fixed-alloc)
(:args)
- (:info name words type lowtag)
- (:ignore name)
+ (:info name words type lowtag stack-allocate-p)
+ (:ignore name stack-allocate-p)
(:results (result :scs (descriptor-reg)))
(:temporary (:scs (non-descriptor-reg)) temp)
(:temporary (:sc non-descriptor-reg :offset nl3-offset) pa-flag)
(define-vop (fixed-alloc)
(:args)
- (:info name words type lowtag)
- (:ignore name)
+ (:info name words type lowtag stack-allocate-p)
+ (:ignore name stack-allocate-p)
(:results (result :scs (descriptor-reg)))
(:temporary (:scs (non-descriptor-reg)) temp)
(:generator 4
(in-package "SB!VM")
\f
-;;;; LIST and LIST*
+;;;; CONS, LIST and LIST*
+(defoptimizer (cons stack-allocate-result) ((&rest args))
+ t)
(defoptimizer (list stack-allocate-result) ((&rest args))
(not (null args)))
(defoptimizer (list* stack-allocate-result) ((&rest args))
(define-vop (fixed-alloc)
(:args)
- (:info name words type lowtag)
+ (:info name words type lowtag stack-allocate-p)
(:ignore name)
(:results (result :scs (descriptor-reg)))
(:node-var node)
(:generator 50
(pseudo-atomic
- (allocation result (pad-data-block words) node)
+ (allocation result (pad-data-block words) node stack-allocate-p)
(inst lea result (make-ea :byte :base result :disp lowtag))
(when type
(storew (logior (ash (1- words) n-widetag-bits) type)
(in-package "SB!VM")
\f
-;;;; LIST and LIST*
+;;;; CONS, LIST and LIST*
+(defoptimizer (cons stack-allocate-result) ((&rest args))
+ t)
(defoptimizer (list stack-allocate-result) ((&rest args))
(not (null args)))
(defoptimizer (list* stack-allocate-result) ((&rest args))
(define-vop (fixed-alloc)
(:args)
- (:info name words type lowtag)
+ (:info name words type lowtag stack-allocate-p)
(:ignore name)
(:results (result :scs (descriptor-reg)))
(:node-var node)
;; also check for (< SPEED SPACE) is because we want the space
;; savings that these out-of-line allocation routines bring whilst
;; compiling SBCL itself. --njf, 2006-07-08
- (if (and (= lowtag list-pointer-lowtag) (policy node (< speed 3)))
+ (if (and (not stack-allocate-p)
+ (= lowtag list-pointer-lowtag) (policy node (< speed 3)))
(let ((dst
+ ;; FIXME: out-of-line dx-allocation
#.(loop for offset in *dword-regs*
collect `(,offset
',(intern (format nil "ALLOCATE-CONS-TO-~A"
(aver (null type))
(inst call (make-fixup dst :assembly-routine)))
(pseudo-atomic
- (allocation result (pad-data-block words) node)
+ (allocation result (pad-data-block words) node stack-allocate-p)
(inst lea result (make-ea :byte :base result :disp lowtag))
(when type
(storew (logior (ash (1- words) n-widetag-bits) type)
(declare (dynamic-extent #'f))
(true #'f))))
+;;; CONS
+
+(defun-with-dx cons-on-stack (x)
+ (let ((cons (cons x x)))
+ (declare (dynamic-extent cons))
+ (true cons)
+ nil))
+
;;; with-spinlock should use DX and not cons
(defvar *slock* (sb-thread::make-spinlock :name "slocklock"))
(assert-no-consing (test-let-var-subst2 17))
(assert-no-consing (test-lvar-subst 11))
(assert-no-consing (dx-value-cell 13))
+ (assert-no-consing (cons-on-stack 42))
;; Not strictly DX..
(assert-no-consing (test-hash-table))
#+sb-thread
;;; 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.4"
+"1.0.10.5"