expander: repair for cross-module inlining during recompilation

When recompiling from machine-independent form to an VM- and
platform-specific form, cross-module inlining could fail due to an
module path index being resolved in the wrong mode (loading versus
non-loading).

As a concrete example, "racket/draw/private/bitmap.rkt" tended to be
recompiled in a way that did not inline `_ubyte` as `_uint8`, which in
turn made `ptr-set!` and `ptr-ref` operations much slower, which would
make certain bitmap operations drastically slower.

Related to racket/drracket#350
This commit is contained in:
Matthew Flatt 2021-01-12 20:00:43 -07:00
parent 7a52e81c33
commit c64bf5d961
4 changed files with 54 additions and 3 deletions

View File

@ -3488,6 +3488,55 @@ case of module-leve bindings; it doesn't cover local bindings.
(dynamic-require ''regression-test-to-make-sure-property-procedure-mutation-is-seen #f)
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Check an interaction of recompilation and cross-module-inlining
;; Make sure that a constant is inlined across a module boundary by
;; recompilation
(parameterize ([current-module-name-resolver
(let ([orig (current-module-name-resolver)])
(case-lambda
[(mp ns) (orig mp ns)]
[(mp wrt stx load?)
(cond
[(equal? mp "module-out-of-thin-air.rkt")
(when load?
(unless (module-declared? ''module-out-of-thin-air)
(eval `(module module-out-of-thin-air racket/base
(define five 5)
(provide five)))))
(make-resolved-module-path 'module-out-of-thin-air)]
[else
(orig mp wrt stx load?)])]))])
(define mi-compiled
(parameterize ([current-namespace (make-base-namespace)]
[current-compile-target-machine #f])
(compile '(module uses-module-out-of-thin-air racket/base
(require "module-out-of-thin-air.rkt")
(define also-five five)
(provide also-five)))))
;; We expect that `mi-compiled` does not have 5 inlined.
;; If it does, that's not actually a problem, but it means that
;; the rest of the test doesn't check what it means to check, so
;; count it as a problem
(parameterize ([current-namespace (make-base-namespace)])
(eval '(module module-out-of-thin-air racket/base
(define five 6)
(provide five)))
(eval mi-compiled)
(test 6 dynamic-require ''uses-module-out-of-thin-air 'also-five))
(define recompiled
(parameterize ([current-namespace (make-base-namespace)])
(compiled-expression-recompile mi-compiled)))
(parameterize ([current-namespace (make-base-namespace)])
(eval '(module module-out-of-thin-air racket/base
(define five 6)
(provide five)))
(eval recompiled)
;; Ir recompilation did not inline the 5, then the result
;; will be 6 instead of 5:
(test 5 dynamic-require ''uses-module-out-of-thin-air 'also-five)))
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(report-errs)

View File

@ -34392,7 +34392,8 @@ static const char *startup_source =
"(lambda(mu*_0)"
"(begin"
" 'intern-module-use*"
"(let-values(((mod-name_0)(1/module-path-index-resolve(module-use-module mu*_0))))"
"(let-values(((mod-name_0)"
"(1/module-path-index-resolve(module-use-module mu*_0) load-modules?_0)))"
"(let-values(((existing-mu*_0)"
"(hash-ref mu*-intern-table_0(cons mod-name_0(module-use-phase mu*_0)) #f)))"
"(if existing-mu*_0"

View File

@ -39344,7 +39344,8 @@
(begin
(let ((mod-name_0
(1/module-path-index-resolve
(module-use-module mu*_0))))
(module-use-module mu*_0)
load-modules?_0)))
(let ((existing-mu*_0
(hash-ref
mu*-intern-table_0

View File

@ -449,7 +449,7 @@
;; collapse them to a single import
(define mu*-intern-table (make-hash))
(define (intern-module-use* mu*)
(define mod-name (module-path-index-resolve (module-use-module mu*)))
(define mod-name (module-path-index-resolve (module-use-module mu*) load-modules?))
(define existing-mu* (hash-ref mu*-intern-table (cons mod-name (module-use-phase mu*)) #f))
(cond
[existing-mu*