schemify: improve use-before-definition analysis

This improvement removes only a few places where a variable use is
considered possibly too early in the RacketCS implementation, but
the improvement is significant for uses of `input-port?` in "io".
This commit is contained in:
Matthew Flatt 2018-08-21 06:36:18 -06:00
parent 473ec2762e
commit eed18fac93
3 changed files with 44 additions and 5 deletions

View File

@ -8,6 +8,9 @@
;; * 'too-early - the identifier may be referenced before it is
;; defined
;;
;; * 'too-early/ready - a variant of 'too-early where the variable
;; is now definitely ready
;;
;; * 'not-ready - the identifier's value is not yet ready, so a
;; reference transitions to 'too-early
;;
@ -28,6 +31,7 @@
(provide delayed-mutated-state?
simple-mutated-state?
not-ready-mutated-state?
too-early-mutated-state?
via-variable-mutated-state?
set!ed-mutated-state?)
@ -35,11 +39,15 @@
(define (simple-mutated-state? v)
(or (not v)
(delayed-mutated-state? v)))
(delayed-mutated-state? v)
(eq? v 'too-early/ready)))
(define (not-ready-mutated-state? v)
(eq? v 'not-ready))
(define (too-early-mutated-state? v)
(eq? v 'too-early))
;; When referecing an exported identifier, we need to consistently go
;; through a `variable` record when it can be `set!`ed. We don't need
;; to go through a `variable` record if the identifier might simply be

View File

@ -8,9 +8,11 @@
"struct-type-info.rkt"
"mutated-state.rkt"
"find-known.rkt"
"infer-known.rkt"
"letrec.rkt")
(provide mutated-in-body)
(provide mutated-in-body
update-mutated-state!)
;; See "mutated-state.rkt" for information on the content of the
;; `mutated` table.
@ -190,3 +192,31 @@
[else
(hash-remove! mutated v)
(state)])])))])))
(define (update-mutated-state! l mut-l mutated)
(cond
[(wrap-null? mut-l) '()]
[(eq? l mut-l)
;; Check for function definitions at the start of `l`, because we
;; can mark all 'too-early variable uses as being ready from now
;; on
(define new-mut-l
(let loop ([mut-l mut-l])
(cond
[(wrap-null? mut-l) '()]
[else
(match (wrap-car mut-l)
[`(define-values (,ids ...) ,rhs)
(cond
[(lambda? rhs #:simple? #t)
(for ([id (in-list ids)])
(define u-id (unwrap id))
(when (too-early-mutated-state? (hash-ref mutated u-id #f))
(hash-set! mutated u-id 'too-early/ready)))
(loop (wrap-cdr mut-l))]
[else mut-l])]
[`,_ mut-l])])))
(if (eq? mut-l l)
(wrap-cdr mut-l)
l)]
[else mut-l]))

View File

@ -186,7 +186,8 @@
;; corresponding exported `variable` records, but delay those
;; installs to the end, if possible
(define schemified
(let loop ([l l] [accum-exprs null] [accum-ids null])
(let loop ([l l] [in-mut-l l] [accum-exprs null] [accum-ids null])
(define mut-l (update-mutated-state! l in-mut-l mutated))
(cond
[(null? l)
(define set-vars
@ -218,7 +219,7 @@
schemified
(let id-loop ([ids ids] [accum-exprs null] [accum-ids accum-ids])
(cond
[(wrap-null? ids) (loop (wrap-cdr l) accum-exprs accum-ids)]
[(wrap-null? ids) (loop (wrap-cdr l) mut-l accum-exprs accum-ids)]
[(or (or for-jitify? for-cify?)
(via-variable-mutated-state? (hash-ref mutated (unwrap (wrap-car ids)) #f)))
(define id (unwrap (wrap-car ids)))
@ -233,7 +234,7 @@
[else
(id-loop (wrap-cdr ids) accum-exprs (cons (unwrap (wrap-car ids)) accum-ids))]))))]
[`,_
(loop (wrap-cdr l) (cons schemified accum-exprs) accum-ids)])])))
(loop (wrap-cdr l) mut-l (cons schemified accum-exprs) accum-ids)])])))
;; Return both schemified and known-binding information, where
;; the later is used for cross-linklet optimization
(values schemified knowns mutated))