📄 vm-tran.lisp
字号:
;;;; implementation-dependent transforms;;;; This software is part of the SBCL system. See the README file for;;;; more information.;;;;;;;; This software is derived from the CMU CL system, which was;;;; written at Carnegie Mellon University and released into the;;;; public domain. The software is in the public domain and is;;;; provided with absolutely no warranty. See the COPYING and CREDITS;;;; files for more information.(in-package "SB!C");;; We need to define these predicates, since the TYPEP source;;; transform picks whichever predicate was defined last when there;;; are multiple predicates for equivalent types.(define-source-transform short-float-p (x) `(single-float-p ,x))#!-long-float(define-source-transform long-float-p (x) `(double-float-p ,x))(define-source-transform compiled-function-p (x) #!-sb-eval `(functionp ,x) #!+sb-eval (once-only ((x x)) `(and (functionp ,x) (not (sb!eval:interpreted-function-p ,x)))))(define-source-transform char-int (x) `(char-code ,x))(deftransform abs ((x) (rational)) '(if (< x 0) (- x) x));;; We don't want to clutter the bignum code.#!+(or x86 x86-64)(define-source-transform sb!bignum:%bignum-ref (bignum index) ;; KLUDGE: We use TRULY-THE here because even though the bignum code ;; is (currently) compiled with (SAFETY 0), the compiler insists on ;; inserting CAST nodes to ensure that INDEX is of the correct type. ;; These CAST nodes do not generate any type checks, but they do ;; interfere with the operation of FOLD-INDEX-ADDRESSING, below. ;; This scenario is a problem for the more user-visible case of ;; folding as well. --njf, 2006-12-01 `(sb!bignum:%bignum-ref-with-offset ,bignum (truly-the bignum-index ,index) 0))#!+(or x86 x86-64)(defun fold-index-addressing (fun-name element-size lowtag data-offset index offset &optional setter-p) (multiple-value-bind (func index-args) (extract-fun-args index '(+ -) 2) (destructuring-bind (x constant) index-args (declare (ignorable x)) (unless (constant-lvar-p constant) (give-up-ir1-transform)) (let ((value (lvar-value constant))) (unless (and (integerp value) (sb!vm::foldable-constant-offset-p element-size lowtag data-offset (funcall func value (lvar-value offset)))) (give-up-ir1-transform "constant is too large for inlining")) (splice-fun-args index func 2) `(lambda (thing index off1 off2 ,@(when setter-p '(value))) (,fun-name thing index (,func off2 off1) ,@(when setter-p '(value))))))))#!+(or x86 x86-64)(deftransform sb!bignum:%bignum-ref-with-offset ((bignum index offset) * * :node node) (fold-index-addressing 'sb!bignum:%bignum-ref-with-offset sb!vm:n-word-bits sb!vm:other-pointer-lowtag sb!vm:bignum-digits-offset index offset))#!+x86(progn(define-source-transform sb!kernel:%vector-raw-bits (thing index) `(sb!kernel:%raw-bits-with-offset ,thing ,index 2))(define-source-transform sb!kernel:%raw-bits (thing index) `(sb!kernel:%raw-bits-with-offset ,thing ,index 0))(define-source-transform sb!kernel:%set-vector-raw-bits (thing index value) `(sb!kernel:%set-raw-bits-with-offset ,thing ,index 2 ,value))(define-source-transform sb!kernel:%set-raw-bits (thing index value) `(sb!kernel:%set-raw-bits-with-offset ,thing ,index 0 ,value))(deftransform sb!kernel:%raw-bits-with-offset ((thing index offset) * * :node node) (fold-index-addressing 'sb!kernel:%raw-bits-with-offset sb!vm:n-word-bits sb!vm:other-pointer-lowtag 0 index offset))(deftransform sb!kernel:%set-raw-bits-with-offset ((thing index offset value) * *) (fold-index-addressing 'sb!kernel:%set-raw-bits-with-offset sb!vm:n-word-bits sb!vm:other-pointer-lowtag 0 index offset t))) ; PROGN;;; The layout is stored in slot 0.(define-source-transform %instance-layout (x) `(truly-the layout (%instance-ref ,x 0)))(define-source-transform %set-instance-layout (x val) `(%instance-set ,x 0 (the layout ,val)))(define-source-transform %funcallable-instance-layout (x) `(truly-the layout (%funcallable-instance-info ,x 0)))(define-source-transform %set-funcallable-instance-layout (x val) `(setf (%funcallable-instance-info ,x 0) (the layout ,val)));;;; character support;;; In our implementation there are really only BASE-CHARs.#+nil(define-source-transform characterp (obj) `(base-char-p ,obj));;;; simplifying HAIRY-DATA-VECTOR-REF and HAIRY-DATA-VECTOR-SET(deftransform hairy-data-vector-ref ((string index) (simple-string t)) (let ((ctype (lvar-type string))) (if (array-type-p ctype) ;; the other transform will kick in, so that's OK (give-up-ir1-transform) `(etypecase string ((simple-array character (*)) (data-vector-ref string index)) #!+sb-unicode ((simple-array base-char (*)) (data-vector-ref string index)) ((simple-array nil (*)) (data-vector-ref string index))))))(deftransform hairy-data-vector-ref ((array index) (array t) *) "avoid runtime dispatch on array element type" (let ((element-ctype (extract-upgraded-element-type array)) (declared-element-ctype (extract-declared-element-type array))) (declare (type ctype element-ctype)) (when (eq *wild-type* element-ctype) (give-up-ir1-transform "Upgraded element type of array is not known at compile time.")) ;; (The expansion here is basically a degenerate case of ;; WITH-ARRAY-DATA. Since WITH-ARRAY-DATA is implemented as a ;; macro, and macros aren't expanded in transform output, we have ;; to hand-expand it ourselves.) (let* ((element-type-specifier (type-specifier element-ctype))) `(multiple-value-bind (array index) (%data-vector-and-index array index) (declare (type (simple-array ,element-type-specifier 1) array)) ,(let ((bare-form '(data-vector-ref array index))) (if (type= element-ctype declared-element-ctype) bare-form `(the ,(type-specifier declared-element-ctype) ,bare-form)))))));;; Transform multi-dimensional array to one dimensional data vector;;; access.(deftransform data-vector-ref ((array index) (simple-array t)) (let ((array-type (lvar-type array))) (unless (array-type-p array-type) (give-up-ir1-transform)) (let ((dims (array-type-dimensions array-type))) (when (or (atom dims) (= (length dims) 1)) (give-up-ir1-transform)) (let ((el-type (array-type-specialized-element-type array-type)) (total-size (if (member '* dims) '* (reduce #'* dims)))) `(data-vector-ref (truly-the (simple-array ,(type-specifier el-type) (,total-size)) (%array-data-vector array)) index)))));;; Transform data vector access to a form that opens up optimization;;; opportunities. On platforms that support DATA-VECTOR-REF-WITH-OFFSET;;; DATA-VECTOR-REF is not supported at all.#!+(or x86 x86-64)(define-source-transform data-vector-ref (array index) `(data-vector-ref-with-offset ,array ,index 0))#!+(or x86 x86-64)(deftransform data-vector-ref-with-offset ((array index offset)) (let ((array-type (lvar-type array))) (when (or (not (array-type-p array-type)) (eql (array-type-specialized-element-type array-type) *wild-type*)) (give-up-ir1-transform)) ;; It shouldn't be possible to get here with anything but a non-complex ;; vector. (aver (not (array-type-complexp array-type))) (let* ((element-type (type-specifier (array-type-specialized-element-type array-type))) (saetp (find-saetp element-type))) (when (< (sb!vm:saetp-n-bits saetp) sb!vm:n-byte-bits) (give-up-ir1-transform)) (fold-index-addressing 'data-vector-ref-with-offset (sb!vm:saetp-n-bits saetp) sb!vm:other-pointer-lowtag sb!vm:vector-data-offset index offset))))(deftransform hairy-data-vector-set ((string index new-value) (simple-string t t)) (let ((ctype (lvar-type string))) (if (array-type-p ctype) ;; the other transform will kick in, so that's OK (give-up-ir1-transform) `(etypecase string ((simple-array character (*)) (data-vector-set string index new-value)) #!+sb-unicode ((simple-array base-char (*)) (data-vector-set string index new-value)) ((simple-array nil (*)) (data-vector-set string index new-value))))))(deftransform hairy-data-vector-set ((array index new-value) (array t t) *) "avoid runtime dispatch on array element type" (let ((element-ctype (extract-upgraded-element-type array)) (declared-element-ctype (extract-declared-element-type array))) (declare (type ctype element-ctype)) (when (eq *wild-type* element-ctype) (give-up-ir1-transform "Upgraded element type of array is not known at compile time.")) (let ((element-type-specifier (type-specifier element-ctype))) `(multiple-value-bind (array index) (%data-vector-and-index array index) (declare (type (simple-array ,element-type-specifier 1) array) (type ,element-type-specifier new-value)) ,(if (type= element-ctype declared-element-ctype) '(data-vector-set array index new-value) `(truly-the ,(type-specifier declared-element-ctype) (data-vector-set array index (the ,(type-specifier declared-element-ctype) new-value))))))));;; Transform multi-dimensional array to one dimensional data vector;;; access.(deftransform data-vector-set ((array index new-value) (simple-array t t)) (let ((array-type (lvar-type array))) (unless (array-type-p array-type) (give-up-ir1-transform)) (let ((dims (array-type-dimensions array-type))) (when (or (atom dims) (= (length dims) 1)) (give-up-ir1-transform)) (let ((el-type (array-type-specialized-element-type array-type)) (total-size (if (member '* dims) '* (reduce #'* dims)))) `(data-vector-set (truly-the (simple-array ,(type-specifier el-type) (,total-size)) (%array-data-vector array)) index new-value)))))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -