fix cm-accomplice and avoid redundant reader-module dependencies

svn: r11354
This commit is contained in:
Matthew Flatt 2008-08-20 13:29:42 +00:00
parent 15cf8e72e1
commit 6516518ae5
7 changed files with 158 additions and 45 deletions

View File

@ -4,13 +4,4 @@
(define (register-external-file f)
(unless (and (path? f) (complete-path? f))
(raise-type-error 'register-external-file "complete path" f))
(let ([param (lambda () void)])
;; Load the code in a separate thread, so that the dynamic
;; extent of this one (likely a phase-sensitive macro expansion)
;; doesn't pollute the load:
(thread-wait
(thread (lambda ()
(set! param
(dynamic-require 'compiler/private/cm-ctime
'current-external-file-registrar)))))
((param) f)))
(log-message (current-logger) 'info "compilation dependency" f))

View File

@ -110,31 +110,72 @@
", which appears to be in the future"
""))]))
(define-struct ext-reader-guard (proc prev)
#:property prop:procedure (struct-field-index proc))
(define (compile-zo* mode path read-src-syntax zo-name)
(define param
;; Avoid using cm while loading cm-ctime:
(parameterize ([use-compiled-file-paths null])
(dynamic-require 'compiler/private/cm-ctime
'current-external-file-registrar)))
;; External dependencies registered through reader guard and accomplice-logged events:
(define external-deps null)
(define deps-sema (make-semaphore 1))
(define done-key (gensym))
(define (external-dep! p)
(set! external-deps (cons (path->bytes p) external-deps)))
(call-with-semaphore
deps-sema
(lambda ()
(set! external-deps (cons (path->bytes p) external-deps)))))
;; Set up a logger to receive and filter accomplice events:
(define accomplice-logger (make-logger))
(define accomplice-log-receiver
(make-log-receiver accomplice-logger 'info))
(define log-th
(let ([orig-log (current-logger)])
(thread (lambda ()
(let loop ()
(let ([l (sync accomplice-log-receiver)])
(cond
[(eq? (vector-ref l 2) done-key) 'done]
[(and (eq? (vector-ref l 0) 'info)
(equal? "compilation dependency" (vector-ref l 1))
(path? (vector-ref l 2)))
(external-dep! (vector-ref l 2))
(loop)]
[else
(log-message orig-log (vector-ref l 0) (vector-ref l 1) (vector-ref l 2))
(loop)])))))))
;; Compile the code:
(define code
(parameterize ([param external-dep!]
[current-reader-guard
(parameterize ([current-reader-guard
(let ([rg (current-reader-guard)])
(lambda (d)
(let ([d (rg d)])
(when (module-path? d)
(let ([p (resolved-module-path-name
(module-path-index-resolve
(module-path-index-join d #f)))])
(when (path? p) (external-dep! p))))
d)))])
(make-ext-reader-guard
(lambda (d)
;; Start by calling the previously installed guard
;; to transform the module path, but also avoid
;; redundant dependencies by skipping over cm guards
;; for files being compiled.
(let ([d (let loop ([rg rg])
(if (ext-reader-guard? rg)
(loop (ext-reader-guard-prev rg))
(rg d)))])
(when (module-path? d)
(let ([p (resolved-module-path-name
(module-path-index-resolve
(module-path-index-join d #f)))])
(when (path? p) (external-dep! p))))
d))
rg))]
[current-logger accomplice-logger])
(get-module-code path mode compile
(lambda (a b) #f) ; extension handler
#:source-reader read-src-syntax)))
(define code-dir (get-compilation-dir mode path))
;; Wait for accomplice logging to finish:
(log-message accomplice-logger 'info "stop" done-key)
(sync log-th)
;; Write the code and dependencies:
(when code
(make-directory* code-dir)
(with-compile-output zo-name

View File

@ -1,13 +0,0 @@
(module cm-ctime '#%kernel
(#%provide current-external-file-registrar)
(define-values (current-external-file-registrar)
(make-parameter
void
(lambda (p)
(if (if (procedure? p)
(procedure-arity-includes? p 1)
#f)
'ok
(raise-type-error 'current-external-file-registrar "procedure (arity 2)" p))
p))))

View File

@ -249,10 +249,14 @@ A parameter for a procedure of one argument that is called to report
@defproc[(register-external-file [file (and path? complete-path?)]) void?]{
Registers the complete path @scheme[file] with a compilation manager
implemented by @schememodname[compiler/cm], if one is active. The
compilation manager then records (in a @filepath{.dep} file) the path
as contributing to the implementation of the module currently being
Logs a message (see @scheme[log-message]) at level @scheme['info]. The
message is @scheme["compilation dependency"], and the data associated
with the message is @scheme[file].
A compilation manager implemented by @schememodname[compiler/cm] looks
for such messages to register an external dependency. The compilation
manager records (in a @filepath{.dep} file) the path as contributing
to the implementation of the module currently being
compiled. Afterward, if the registered file is modified, the
compilation manager will know to recompile the module.

View File

@ -675,6 +675,7 @@
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(when (make-info-domain)
(setup-printf #f "--- updating info-domain tables ---")
;; Each ht maps a collection root dir to an info-domain table. Even when
;; `collections-to-compile' is a subset of all collections, we only care
;; about those collections that exist in the same root as the ones in

View File

@ -0,0 +1,91 @@
(load-relative "loadtest.ss")
(Section 'cm)
(require compiler/cm
scheme/file)
(define dir (build-path (find-system-path 'temp-dir)
"plt-cm-test"))
(make-directory* dir)
(define (try files #; (list (list path content-str compile?) ...)
recomps #; (list (list (list touch-path ...)
(list rebuild-path ...)
(list check-rebuilt-path ...)))
)
(delete-directory/files dir)
(make-directory* dir)
(printf "wrorking in ~s\n" dir)
(for-each (lambda (f)
(printf "writing ~a\n" (car f))
(with-output-to-file (build-path dir (car f))
(lambda ()
(display (cadr f)))))
files)
(for-each (lambda (f)
(when (caddr f)
(printf "making ~a\n" (car f))
(managed-compile-zo (build-path dir (car f)))))
files)
(let ([timestamps
(hash-copy
(for/hash ([f (in-list files)])
(values (car f)
(file-or-directory-modify-seconds
(build-path dir "compiled" (path-add-suffix (car f) #".zo"))
#f
(lambda () -inf.0)))))])
(for-each (lambda (recomp)
(printf "pausing...\n")
(sleep 1) ;; timestamps have a 1-second granularity on most filesystems
(for-each (lambda (f)
(printf "touching ~a\n" f)
(with-output-to-file (build-path dir f)
#:exists 'append
(lambda () (display " "))))
(car recomp))
(for-each (lambda (f)
(printf "re-making ~a\n" f)
(managed-compile-zo (build-path dir f)))
(cadr recomp))
(for-each (lambda (f)
(let ([ts (hash-ref timestamps f)]
[new-ts
(file-or-directory-modify-seconds
(build-path dir "compiled" (path-add-suffix f #".zo"))
#f
(lambda () -inf.0))]
[updated? (lambda (a b) a)])
(test (and (member f (caddr recomp)) #t)
updated?
(new-ts . > . ts)
f)
(hash-set! timestamps f new-ts)))
(map car files)))
recomps)))
(try '(("a.ss" "(module a scheme/base (require \"b.ss\" \"d.ss\" \"g.ss\"))" #t)
("b.ss" "(module b scheme/base (require scheme/include) (include \"c.sch\"))" #t)
("d.ss" "#reader \"e.ss\" 10" #t)
("c.sch" "5" #f)
("e.ss" "(module e syntax/module-reader \"f.ss\")" #t)
("f.ss" "(module f scheme/base (provide (all-from-out scheme/base)))" #t)
("g.ss" "(module g scheme/base (require (for-syntax scheme/base scheme/include \"i.ss\")) (define-syntax (f stx) (include \"h.sch\")))" #t)
("h.sch" "(quote-syntax 12)" #f)
("i.ss" "(module i scheme/base)" #t))
'([("a.ss") ("a.ss") ("a.ss")]
[("b.ss") ("a.ss") ("a.ss" "b.ss")]
[("b.ss") ("b.ss") ("b.ss")]
[() ("a.ss") ("a.ss")]
[("c.sch") ("a.ss") ("a.ss" "b.ss")]
[("f.ss") ("a.ss") ("a.ss" "d.ss" "f.ss")]
[("e.ss") ("e.ss") ("e.ss")]
[() ("a.ss") ("a.ss" "d.ss")]
[("i.ss") ("a.ss") ("a.ss" "g.ss" "i.ss")]
[("h.sch") ("a.ss") ("a.ss" "g.ss")]))
;; ----------------------------------------
(report-errs)

View File

@ -67,8 +67,6 @@
(go (build-path (current-load-relative-directory) "xform-mod.ss")
#f
"xform-collects/xform/xform-mod.ss")
;; Needed for cm:
(go 'compiler/private/cm-ctime #f #f)
;; Readers:
(go 'mzscheme/lang/reader #f #f)
(go 'scheme/base/lang/reader #f #f)