cs & schemify: cptypes-nice inline of authentic access and mutate

Change schemify to inline accessors and mutators of authentic
structure types in a way that lets cptypes eliminate checks for
subsequent operations.
This commit is contained in:
Matthew Flatt 2021-03-07 19:09:14 -07:00
parent 9651b45c83
commit 87d84a59c1
3 changed files with 148 additions and 82 deletions

View File

@ -22,6 +22,12 @@
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define saved-top-level-modules (make-hasheq))
(define-syntax-rule (register-top-level-module m)
(begin
(hash-set! saved-top-level-modules (cadr 'm) 'm)
m))
;; For CS: ;; For CS:
(define compile/optimize (define compile/optimize
(let () (let ()
@ -106,18 +112,30 @@
(define mpi (replace-self (module-use-module mu))) (define mpi (replace-self (module-use-module mu)))
(define mp (module-path-index-resolve mpi #f)) (define mp (module-path-index-resolve mpi #f))
(define path (resolved-module-path-name mp)) (define path (resolved-module-path-name mp))
(define (handle-linklet lnkl)
(define bundle (if (linkl-directory? lnkl)
(hash-ref (linkl-directory-table lnkl) '() #f)
lnkl))
(define code (hash-ref (linkl-bundle-table bundle) (module-use-phase mu) #f))
(define-values (new-keys new-mod-uses) (bundle->keys+uses bundle))
(for ([(k mu) (in-hash new-mod-uses)])
(set! mod-uses (hash-set mod-uses k mu)))
(values code (list->vector (append '(#f #f) new-keys))))
(cond (cond
[(path? path) [(path? path)
(define zo-path (get-compilation-bytecode-file path)) (define zo-path (get-compilation-bytecode-file path))
(define lnkl (call-with-input-file* zo-path zo-parse)) (handle-linklet (call-with-input-file* zo-path zo-parse))]
(define bundle (if (linkl-directory? lnkl) [(hash-ref saved-top-level-modules path #f)
(hash-ref (linkl-directory-table lnkl) '() #f) => (lambda (m)
lnkl)) (handle-linklet
(define code (hash-ref (linkl-bundle-table bundle) (module-use-phase mu) #f)) (cond
(define-values (new-keys new-mod-uses) (bundle->keys+uses bundle)) [(list? m)
(for ([(k mu) (in-hash new-mod-uses)]) (define o (open-output-bytes))
(set! mod-uses (hash-set mod-uses k mu))) (write (compile m) o)
(values code (list->vector (append '(#f #f) new-keys)))] (define linkl (zo-parse (open-input-bytes (get-output-bytes o))))
(hash-set! saved-top-level-modules path linkl)
linkl]
[else m])))]
[else [else
(values #f #f)])] (values #f #f)])]
[else (values #f #f)])) [else (values #f #f)]))
@ -3416,17 +3434,18 @@
c c
c))) c)))
(module check-inline-request racket/base (register-top-level-module
(require racket/performance-hint) (module check-inline-request racket/base
(provide loop) (require racket/performance-hint)
(begin-encourage-inline (provide loop)
(define loop (begin-encourage-inline
;; large enough that the compiler wouldn't infer inlining: (define loop
(lambda (f n) ;; large enough that the compiler wouldn't infer inlining:
(let loop ([i n]) (lambda (f n)
(if (zero? i) (let loop ([i n])
10 (if (zero? i)
(cons (f i) (loop (sub1 n))))))))) 10
(cons (f i) (loop (sub1 n))))))))))
(test-comp `(module m racket/base (test-comp `(module m racket/base
(require 'check-inline-request) (require 'check-inline-request)
@ -3524,37 +3543,43 @@
(displayln (list expr 3 '!)) (displayln (list expr 3 '!))
) )
(map check-omit-ok (map check-omit-ok
'((unsafe-vector*-ref x y) (append
(unsafe-struct*-ref x y) '((unsafe-vector*-ref x y)
(unsafe-mcar x) (unsafe-struct*-ref x y)
(unsafe-mcdr x) (unsafe-mcar x)
(unsafe-unbox* x) (unsafe-mcdr x)
(unsafe-bytes-ref x y) (unsafe-unbox* x)
(unsafe-string-ref x y) (unsafe-bytes-ref x y)
(unsafe-flvector-ref x y) (unsafe-string-ref x y)
(unsafe-fxvector-ref x y) (unsafe-flvector-ref x y)
(unsafe-f64vector-ref x y) (unsafe-fxvector-ref x y))
(unsafe-s16vector-ref x y) (if (eq? 'chez-scheme (system-type 'vm))
(unsafe-u16vector-ref x y))) '()
'((unsafe-f64vector-ref x y)
(unsafe-s16vector-ref x y)
(unsafe-u16vector-ref x y)))))
(map (lambda (x) (check-omit-ok x #f)) (map (lambda (x) (check-omit-ok x #f))
'((unsafe-vector-ref x y) (append
(unsafe-struct-ref x y) '((unsafe-vector-ref x y)
(unsafe-vector-set! x y z) (unsafe-struct-ref x y)
(unsafe-vector*-set! x y z) (unsafe-vector-set! x y z)
(unsafe-struct-set! x y z) (unsafe-vector*-set! x y z)
(unsafe-struct*-set! x y z) (unsafe-struct-set! x y z)
(unsafe-set-mcar! x y) (unsafe-struct*-set! x y z)
(unsafe-set-mcdr! x y) (unsafe-set-mcar! x y)
(unsafe-unbox y) (unsafe-set-mcdr! x y)
(unsafe-set-box! x y) (unsafe-unbox y)
(unsafe-set-box*! x y) (unsafe-set-box! x y)
(unsafe-bytes-set! x y z) (unsafe-set-box*! x y)
(unsafe-string-set! x y z) (unsafe-bytes-set! x y z)
(unsafe-flvector-set! x y z) (unsafe-string-set! x y z)
(unsafe-fxvector-set! x y z) (unsafe-flvector-set! x y z)
(unsafe-f64vector-set! x y z) (unsafe-fxvector-set! x y z))
(unsafe-s16vector-set! x y z) (if (eq? 'chez-scheme (system-type 'vm))
(unsafe-u16vector-set! x y z))) '()
'((unsafe-f64vector-set! x y z)
(unsafe-s16vector-set! x y z)
(unsafe-u16vector-set! x y z)))))
(when (extflonum-available?) (when (extflonum-available?)
(map check-omit-ok (map check-omit-ok
@ -3567,11 +3592,13 @@
)) ))
)) ))
(test-comp '(lambda (x) (test-comp #:except 'chez-scheme
'(lambda (x)
(hash-ref '#hash((x . y)) x (lambda () 10))) (hash-ref '#hash((x . y)) x (lambda () 10)))
'(lambda (x) '(lambda (x)
(hash-ref '#hash((x . y)) x 10))) (hash-ref '#hash((x . y)) x 10)))
(test-comp '(lambda (x) (test-comp #:except 'chez-scheme
'(lambda (x)
(hash-ref x x (lambda () 10))) (hash-ref x x (lambda () 10)))
'(lambda (x) '(lambda (x)
(hash-ref x x 10)) (hash-ref x x 10))
@ -3582,7 +3609,8 @@
(hash-ref '#hash((x . y)) x add1)) (hash-ref '#hash((x . y)) x add1))
#f) #f)
(test-comp '(lambda () (test-comp #:except 'chez-scheme
'(lambda ()
(hash-ref #hash() (hash-ref #hash()
'missing 'missing
(λ () (λ ()
@ -3602,7 +3630,7 @@
'UNEXPECTED!)) 'UNEXPECTED!))
#f) #f)
(let () (unless (eq? 'chez-scheme (system-type 'vm))
(define (check-empty-allocation hash-sym) (define (check-empty-allocation hash-sym)
(test-comp `(lambda () (,hash-sym) 5) (test-comp `(lambda () (,hash-sym) 5)
'(lambda () 5)) '(lambda () 5))
@ -3664,16 +3692,18 @@
(define (check-discard-iterate op-name) (define (check-discard-iterate op-name)
(test-comp `(lambda (ht i) (,op-name ht i) 5) (test-comp `(lambda (ht i) (,op-name ht i) 5)
`(lambda (ht i) 5))) `(lambda (ht i) 5)))
(check-discard-iterate 'unsafe-immutable-hash-iterate-next) (unless (eq? 'chez-scheme (system-type 'vm))
(check-discard-iterate 'unsafe-immutable-hash-iterate-key) (check-discard-iterate 'unsafe-immutable-hash-iterate-next)
(check-discard-iterate 'unsafe-immutable-hash-iterate-value) (check-discard-iterate 'unsafe-immutable-hash-iterate-key)
(check-discard-iterate 'unsafe-immutable-hash-iterate-key+value) (check-discard-iterate 'unsafe-immutable-hash-iterate-value)
(check-discard-iterate 'unsafe-immutable-hash-iterate-pair)) (check-discard-iterate 'unsafe-immutable-hash-iterate-key+value)
(check-discard-iterate 'unsafe-immutable-hash-iterate-pair)))
;; Check elimination of ignored structure predicate ;; Check elimination of ignored structure predicate
;; and constructor applications: ;; and constructor applications:
(test-comp '(module m racket/base (test-comp #:except 'chez-scheme ; schemify doesn't specialize raw accessor+mutator form
'(module m racket/base
(define-values (struct:a a a? a-ref a-set!) (define-values (struct:a a a? a-ref a-set!)
(make-struct-type 'a #f 2 0)) (make-struct-type 'a #f 2 0))
(begin0 (begin0
@ -3694,7 +3724,7 @@
(test-comp '(module m racket/base (test-comp '(module m racket/base
(define-values (struct:a a a? a-x a-y) (define-values (struct:a a a? a-x a-y)
(let-values ([(struct:a a a? a-ref a-set!) (let-values ([(struct:a a a? a-ref a-set!)
(make-struct-type 'a #f 2 0)]) (make-struct-type 'a #f 2 0 #f)])
(values struct:a a a? (values struct:a a a?
(make-struct-field-accessor a-ref 0) (make-struct-field-accessor a-ref 0)
(make-struct-field-accessor a-ref 1)))) (make-struct-field-accessor a-ref 1))))
@ -3709,7 +3739,7 @@
'(module m racket/base '(module m racket/base
(define-values (struct:a a a? a-x a-y) (define-values (struct:a a a? a-x a-y)
(let-values ([(struct:a a a? a-ref a-set!) (let-values ([(struct:a a a? a-ref a-set!)
(make-struct-type 'a #f 2 0)]) (make-struct-type 'a #f 2 0 #f)])
(values struct:a a a? (values struct:a a a?
(make-struct-field-accessor a-ref 0) (make-struct-field-accessor a-ref 0)
(make-struct-field-accessor a-ref 1)))) (make-struct-field-accessor a-ref 1))))
@ -3816,16 +3846,18 @@
(a? (a-x (a 1 2))) (a? (a-x (a 1 2)))
5))) 5)))
(module struct-a-for-optimize racket/base (register-top-level-module
(provide (struct-out a) (module struct-a-for-optimize racket/base
(struct-out b)) (provide (struct-out a)
(struct a (x y)) (struct-out b))
(struct b a (z))) (struct a (x y))
(struct b a (z))))
(module struct-c-for-optimize racket/base (register-top-level-module
(require 'struct-a-for-optimize) (module struct-c-for-optimize racket/base
(provide (struct-out c)) (require 'struct-a-for-optimize)
(struct c a (q))) (provide (struct-out c))
(struct c a (q))))
(test-comp '(module m racket/base (test-comp '(module m racket/base
(require 'struct-a-for-optimize) (require 'struct-a-for-optimize)
@ -3864,7 +3896,8 @@
(list (c? (c-q (c 1 2 3)))) (list (c? (c-q (c 1 2 3))))
5))) 5)))
(test-comp '(module m racket/base (test-comp #:except 'chez-scheme ; compilation of known accessor is not the same as `unsafe-struct-ref`
'(module m racket/base
(require racket/unsafe/ops) (require racket/unsafe/ops)
(struct a (x y)) (struct a (x y))
(define (f v) (define (f v)
@ -3896,7 +3929,8 @@
(unsafe-struct*-ref v 1)) (unsafe-struct*-ref v 1))
(void))))) (void)))))
(test-comp '(module m racket/base (test-comp #:except 'chez-scheme ; compilation of known accessor is not the same as `unsafe-struct-ref`
'(module m racket/base
(require racket/unsafe/ops) (require racket/unsafe/ops)
(struct a (x y)) (struct a (x y))
(define (f v) (define (f v)
@ -3909,6 +3943,18 @@
(unsafe-struct-ref v 1))))) (unsafe-struct-ref v 1)))))
(test-comp '(module m racket/base (test-comp '(module m racket/base
(require racket/unsafe/ops)
(struct a (x y) #:authentic)
(define (f v)
(list (a-x v) (a? v))))
'(module m racket/base
(require racket/unsafe/ops)
(struct a (x y) #:authentic)
(define (f v)
(list (a-x v) #t))))
(test-comp #:except 'chez-scheme
'(module m racket/base
(require racket/unsafe/ops) (require racket/unsafe/ops)
(struct a (x y)) (struct a (x y))
(define (f v) (define (f v)

View File

@ -30297,9 +30297,16 @@
'if 'if
app_0 app_0
app_1 app_1
(list (let ((a_0
s-rator_0 (list
tmp_0))))))) s-rator_0
tmp_0)))
(if (known-field-accessor-authentic?
k_0)
(cons
'|#%app/no-return|
a_0)
a_0))))))))
(wrap-tmp_0 (wrap-tmp_0
tmp_0 tmp_0
(car (car
@ -30372,10 +30379,17 @@
'if 'if
app_0 app_0
app_1 app_1
(list (let ((a_0
s-rator_0 (list
tmp_0 s-rator_0
tmp-rhs_0))))))) tmp_0
tmp-rhs_0)))
(if (known-field-mutator-authentic?
k_0)
(cons
'|#%app/no-return|
a_0)
a_0))))))))
(let ((app_0 (let ((app_0
(car (car
args_0))) args_0)))

View File

@ -909,7 +909,10 @@
`(unsafe-struct*-ref ,tmp ,(known-field-accessor-pos k)) `(unsafe-struct*-ref ,tmp ,(known-field-accessor-pos k))
`(if (unsafe-struct? ,tmp ,(schemify type-id 'fresh)) `(if (unsafe-struct? ,tmp ,(schemify type-id 'fresh))
(unsafe-struct*-ref ,tmp ,(known-field-accessor-pos k)) (unsafe-struct*-ref ,tmp ,(known-field-accessor-pos k))
(,s-rator ,tmp)))) ,(let ([a `(,s-rator ,tmp)])
(if (known-field-accessor-authentic? k)
(cons '#%app/no-return a)
a)))))
(wrap-tmp tmp (car args) (wrap-tmp tmp (car args)
sel)] sel)]
[else #f])) [else #f]))
@ -927,7 +930,10 @@
`(unsafe-struct*-set! ,tmp ,(known-field-mutator-pos k) ,tmp-rhs) `(unsafe-struct*-set! ,tmp ,(known-field-mutator-pos k) ,tmp-rhs)
`(if (unsafe-struct? ,tmp ,(schemify type-id 'fresh)) `(if (unsafe-struct? ,tmp ,(schemify type-id 'fresh))
(unsafe-struct*-set! ,tmp ,(known-field-mutator-pos k) ,tmp-rhs) (unsafe-struct*-set! ,tmp ,(known-field-mutator-pos k) ,tmp-rhs)
(,s-rator ,tmp ,tmp-rhs)))) ,(let ([a `(,s-rator ,tmp ,tmp-rhs)])
(if (known-field-mutator-authentic? k)
(cons '#%app/no-return a)
a)))))
(wrap-tmp tmp (car args) (wrap-tmp tmp (car args)
(wrap-tmp tmp-rhs (cadr args) (wrap-tmp tmp-rhs (cadr args)
mut))] mut))]