compiler: never retain namespace for constantness-test argument

Even when `(variable-reference-constant? (#%variable-reference ....))`
cannot be optimized to a boolean, the expression should not retain a
reference to the enclosing namespace. That space guarantee is
important for the compilation of calls to keyword-accepting functions.
This commit is contained in:
Matthew Flatt 2015-01-18 16:11:31 -07:00
parent ab5baca97c
commit 676109f638
2 changed files with 34 additions and 1 deletions

View File

@ -257,6 +257,38 @@
(for ([t thds]) (kill-thread t)))
;; ----------------------------------------
;; Check that an unoptimizable `(variable-reference-constant? (#%variable-reference r))`
;; expression does not retain a reference to the namespace --- since not retaining
;; a reference can be important to the expansion to a call to a keyword-accepting
;; function.
(when (eq? '3m (system-type 'gc))
(define (mk)
(parameterize ([current-namespace (make-base-namespace)])
(eval '(module module-with-unoptimized-varref-constant racket/base
(define (r)
(variable-reference-constant?
(#%variable-reference r)))
(define top (box 1))
(define top-boxed (make-weak-box top))
(set! r r)
(provide r top-boxed)))
(list (dynamic-require ''module-with-unoptimized-varref-constant 'r)
(dynamic-require ''module-with-unoptimized-varref-constant 'top-boxed))))
(let ([l (for/list ([i 10])
(mk))])
(collect-garbage)
(define fraction-retained
(/ (for/fold ([n 0]) ([p (in-list l)])
(if (weak-box-value (cadr p))
(add1 n)
n))
(for/fold ([n 0]) ([p (in-list l)])
(if (car p) (add1 n) n))))
(test #t < fraction-retained 1/2)))
;; ----------------------------------------
(report-errs)

View File

@ -1351,7 +1351,7 @@ ref_syntax (Scheme_Object *form, Scheme_Comp_Env *env, Scheme_Compile_Info *rec,
/* retaining `dummy' ensures that the environment stays
linked from the actual variable */
if (rec[drec].comp)
if (rec[drec].comp && ((l == 1) || !rec[drec].testing_constantness))
dummy = scheme_make_environment_dummy(env);
else
dummy = NULL;
@ -1433,6 +1433,7 @@ ref_syntax (Scheme_Object *form, Scheme_Comp_Env *env, Scheme_Compile_Info *rec,
o = scheme_alloc_object();
o->type = scheme_varref_form_type;
SCHEME_PTR1_VAL(o) = (Scheme_Object *)var;
if (!dummy) dummy = scheme_false;
SCHEME_PTR2_VAL(o) = (Scheme_Object *)dummy;
return o;
} else {