Enables the use of non-T stack TNs for closed-over dynamic-extent variables.
SB!VM:PRIMITIVE-TYPE-INDIRECT-CELL-TYPE takes a primitive-type and returns
NIL, or a list of 4 values:
- the primitive type of the implicit indirect value cell
- the SC of that cell
- a function that takes the NODE, BLOCK, FP, VALUE and RESULT, and
emits a reference to that cell.
- a function that takes the NODE, BLOCK, FP, NEW-VALUE and VALUE, and
emits a write to that cell.
Some correctness tests to make sure codegen is correct (without verifying
DXness).
"%%POP-DX"
"PREDICATE" "PRIMITIVE-TYPE" "PRIMITIVE-TYPE-OF"
"PRIMITIVE-TYPE-OR-LOSE" "PRIMITIVE-TYPE-VOP"
- "PRIMITIVE-TYPE-NAME" "PUSH-VALUES"
+ "PRIMITIVE-TYPE-NAME"
+ "PRIMITIVE-TYPE-INDIRECT-CELL-TYPE"
+ "PUSH-VALUES"
"READ-PACKED-BIT-VECTOR" "READ-VAR-INTEGER" "READ-VAR-STRING"
#!+inline-constants "REGISTER-INLINE-CONSTANT"
"RESET-STACK-POINTER" "RESTORE-DYNAMIC-STATE"
"PRIMITIVE-OBJECT-LOWTAG" "PRIMITIVE-OBJECT-NAME"
"PRIMITIVE-OBJECT-OPTIONS" "PRIMITIVE-OBJECT-P"
"PRIMITIVE-OBJECT-SIZE" "PRIMITIVE-OBJECT-SLOTS"
- "PRIMITIVE-OBJECT-VARIABLE-LENGTH-P" "PRINT-ALLOCATED-OBJECTS"
+ "PRIMITIVE-OBJECT-VARIABLE-LENGTH-P"
+ "PRINT-ALLOCATED-OBJECTS"
"RANDOM-IMMEDIATE-SC-NUMBER" "RATIO-DENOMINATOR-SLOT"
"RATIO-NUMERATOR-SLOT" "RATIO-SIZE" "RATIO-WIDETAG"
"*READ-ONLY-SPACE-FREE-POINTER*"
(!def-vm-support-routine combination-implementation-style (node)
(declare (type sb!c::combination node) (ignore node))
(values :default nil))
+
+(defun primitive-type-indirect-cell-type (ptype)
+ (declare (ignore ptype))
+ nil)
(declare (type clambda fun))
(dolist (var (lambda-vars fun))
(when (leaf-refs var)
- (let* ((type (if (lambda-var-indirect var)
- *backend-t-primitive-type*
+ (let* (ptype-info
+ (type (if (lambda-var-indirect var)
+ (if (lambda-var-explicit-value-cell var)
+ *backend-t-primitive-type*
+ (or (first
+ (setf ptype-info
+ (primitive-type-indirect-cell-type
+ (primitive-type (leaf-type var)))))
+ *backend-t-primitive-type*))
(primitive-type (leaf-type var))))
(res (make-normal-tn type))
(node (lambda-bind fun))
;; Force closed-over indirect LAMBDA-VARs without explicit
;; VALUE-CELLs to the stack, and make sure that they are
;; live over the dynamic contour of the physenv.
- (setf (tn-sc res) (svref *backend-sc-numbers*
- sb!vm:control-stack-sc-number))
+ (setf (tn-sc res) (if ptype-info
+ (second ptype-info)
+ (sc-or-lose 'sb!vm::control-stack)))
(physenv-live-tn res (lambda-physenv fun)))
(debug-variable-p
(!def-vm-support-routine combination-implementation-style (node)
(declare (type sb!c::combination node) (ignore node))
(values :default nil))
+
+(defun primitive-type-indirect-cell-type (ptype)
+ (declare (ignore ptype))
+ nil)
((and indirect
(not (eq (node-physenv node)
(lambda-physenv (lambda-var-home leaf)))))
- (vop ancestor-frame-ref node block tn (leaf-info leaf) res))
+ (let ((reffer (third (primitive-type-indirect-cell-type
+ (primitive-type (leaf-type leaf))))))
+ (if reffer
+ (funcall reffer node block tn (leaf-info leaf) res)
+ (vop ancestor-frame-ref node block tn (leaf-info leaf) res))))
(t (emit-move node block tn res)))))
(constant
(emit-move node block (constant-tn leaf) res))
((and indirect
(not (eq (node-physenv node)
(lambda-physenv (lambda-var-home leaf)))))
- (vop ancestor-frame-set node block tn val (leaf-info leaf)))
+ (let ((setter (fourth (primitive-type-indirect-cell-type
+ (primitive-type (leaf-type leaf))))))
+ (if setter
+ (funcall setter node block tn val (leaf-info leaf))
+ (vop ancestor-frame-set node block tn val (leaf-info leaf)))))
(t (emit-move node block val tn))))))
(global-var
(aver (symbolp (leaf-source-name leaf)))
(!def-vm-support-routine combination-implementation-style (node)
(declare (type sb!c::combination node) (ignore node))
(values :default nil))
+
+(defun primitive-type-indirect-cell-type (ptype)
+ (declare (ignore ptype))
+ nil)
(%%ldb integer size posn))))
(t (values :default nil))))
(t (values :default nil)))))
+
+(defun primitive-type-indirect-cell-type (ptype)
+ (declare (ignore ptype))
+ nil)
(!def-vm-support-routine combination-implementation-style (node)
(declare (type sb!c::combination node) (ignore node))
(values :default nil))
+
+(defun primitive-type-indirect-cell-type (ptype)
+ (declare (ignore ptype))
+ nil)
(!def-vm-support-routine combination-implementation-style (node)
(declare (type sb!c::combination node) (ignore node))
(values :default nil))
+
+(defun primitive-type-indirect-cell-type (ptype)
+ (declare (ignore ptype))
+ nil)
(%logbitp integer index))))
(t (values :default nil))))
(t (values :default nil)))))
+
+(defun primitive-type-indirect-cell-type (ptype)
+ (declare (ignore ptype))
+ nil)
(assert (eql a 1))
(assert (eql b 2))
(assert (eql c 3)))))
+
+(defun opaque-funcall (function &rest arguments)
+ (apply function arguments))
+
+(with-test (:name :implicit-value-cells)
+ (flet ((test-it (type input output)
+ (let ((f (compile nil `(lambda (x)
+ (declare (type ,type x))
+ (flet ((inc ()
+ (incf x)))
+ (declare (dynamic-extent #'inc))
+ (list (opaque-funcall #'inc) x))))))
+ (assert (equal (funcall f input)
+ (list output output))))))
+ (let ((width sb-vm:n-word-bits))
+ (test-it t (1- most-positive-fixnum) most-positive-fixnum)
+ (test-it `(unsigned-byte ,(1- width)) (ash 1 (- width 2)) (1+ (ash 1 (- width 2))))
+ (test-it `(signed-byte ,width) (ash -1 (- width 2)) (1+ (ash -1 (- width 2))))
+ (test-it `(unsigned-byte ,width) (ash 1 (1- width)) (1+ (ash 1 (1- width))))
+ (test-it 'single-float 3f0 4f0)
+ (test-it 'double-float 3d0 4d0)
+ (test-it '(complex single-float) #c(3f0 4f0) #c(4f0 4f0))
+ (test-it '(complex double-float) #c(3d0 4d0) #c(4d0 4d0)))))
+
+(with-test (:name :sap-implicit-value-cells)
+ (let ((f (compile nil `(lambda (x)
+ (declare (type system-area-pointer x))
+ (flet ((inc ()
+ (setf x (sb-sys:sap+ x 16))))
+ (declare (dynamic-extent #'inc))
+ (list (opaque-funcall #'inc) x)))))
+ (width sb-vm:n-machine-word-bits))
+ (assert (every (lambda (x)
+ (sb-sys:sap= x (sb-sys:int-sap (+ 16 (ash 1 (1- width))))))
+ (funcall f (sb-sys:int-sap (ash 1 (1- width))))))))