dynamic-require: fast path for re-exported variables
When `dynamic-require` is used to access an export that isn't a variable defined in the same module, `dynamic-require` falls back to `eval` in a fresh namespace, which can be expensive. The new fast path handles the case that a variable is re-exported. The new fast path is relevant to deserialization, which now uses a submodule that re-exports from an enclosing module.
This commit is contained in:
parent
abc174e16c
commit
01eece18a7
|
@ -1005,6 +1005,51 @@
|
||||||
(begin-for-syntax
|
(begin-for-syntax
|
||||||
(define y 2))))
|
(define y 2))))
|
||||||
|
|
||||||
|
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; Check `dynamic-require` re-export fast path
|
||||||
|
|
||||||
|
(for ([specs (list (list '(provide)
|
||||||
|
'x)
|
||||||
|
(list '(provide x)
|
||||||
|
'x)
|
||||||
|
(list '(provide (rename-out [x xx]))
|
||||||
|
'x)
|
||||||
|
(list '(provide (rename-out [y x]))
|
||||||
|
'x)
|
||||||
|
(list '(provide)
|
||||||
|
'(rename-out [y x])
|
||||||
|
"y")
|
||||||
|
(list '(provide)
|
||||||
|
'(rename-out [z x])
|
||||||
|
"x"
|
||||||
|
;; slow:
|
||||||
|
"exp\nexp\nrun\nexp\nexp\n"))])
|
||||||
|
(define ns (make-base-namespace))
|
||||||
|
(define o (open-output-string))
|
||||||
|
(parameterize ([current-output-port o])
|
||||||
|
(eval `(module m racket/base
|
||||||
|
(require (for-syntax racket/base))
|
||||||
|
(begin-for-syntax (displayln "exp"))
|
||||||
|
(define x "x")
|
||||||
|
(define y "y")
|
||||||
|
(define-syntax (z stx) #'x)
|
||||||
|
,(car specs)
|
||||||
|
(module* sub #f
|
||||||
|
(displayln "run")
|
||||||
|
(provide ,(cadr specs))))
|
||||||
|
ns))
|
||||||
|
(define expected (if (null? (cddr specs)) "x" (caddr specs)))
|
||||||
|
(define expected-out (if ((length specs) . < . 4)
|
||||||
|
"exp\nexp\nrun\n"
|
||||||
|
(list-ref specs 3)))
|
||||||
|
(define (dynamic-require/o m x)
|
||||||
|
(parameterize ([current-output-port o])
|
||||||
|
(dynamic-require m x)))
|
||||||
|
(parameterize ([current-namespace ns])
|
||||||
|
(test expected dynamic-require/o '(submod 'm sub) 'x)
|
||||||
|
(test expected dynamic-require/o '(submod 'm sub) 'x))
|
||||||
|
(test expected-out get-output-string o))
|
||||||
|
|
||||||
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
(report-errs)
|
(report-errs)
|
||||||
|
|
|
@ -1205,8 +1205,57 @@ static Scheme_Object *_dynamic_require(int argc, Scheme_Object *argv[],
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
if (fail_with_error) {
|
if (fail_with_error) {
|
||||||
if (!phase) {
|
if (!phase
|
||||||
/* Evaluate id in a fresh namespace */
|
&& srcm->me->rt->provide_srcs
|
||||||
|
&& SCHEME_TRUEP(srcm->me->rt->provide_srcs[i])) {
|
||||||
|
/* Handle simple re-exporting */
|
||||||
|
int j;
|
||||||
|
Scheme_Module *srcm2;
|
||||||
|
|
||||||
|
srcmname = srcm->me->rt->provide_srcs[i];
|
||||||
|
srcmname = scheme_modidx_shift(srcmname, srcm->me->src_modidx, srcm->self_modidx);
|
||||||
|
srcmname = scheme_module_resolve(srcmname, 1);
|
||||||
|
srcname = srcm->me->rt->provide_src_names[i];
|
||||||
|
|
||||||
|
srcm2 = module_load(srcmname, env, errname);
|
||||||
|
|
||||||
|
for (j = srcm2->me->rt->num_var_provides; j--; ) {
|
||||||
|
if (SCHEME_FALSEP(srcm2->me->rt->provide_srcs[j])
|
||||||
|
&& SAME_OBJ(srcname, srcm2->me->rt->provide_src_names[j])) {
|
||||||
|
/* simple re-export applies: */
|
||||||
|
srcm = srcm2;
|
||||||
|
count = srcm->me->rt->num_provides;
|
||||||
|
name = srcm2->me->rt->provides[j];
|
||||||
|
i = j;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (j < 0) {
|
||||||
|
/* Try indirect: */
|
||||||
|
Scheme_Module_Export_Info *exp_info = srcm2->exp_infos[0];
|
||||||
|
for (j = exp_info->num_indirect_provides; j--; ) {
|
||||||
|
if (SAME_OBJ(srcname, exp_info->indirect_provides[j])) {
|
||||||
|
srcm = srcm2;
|
||||||
|
name = srcname;
|
||||||
|
count = srcm->me->rt->num_provides;
|
||||||
|
i = count;
|
||||||
|
position = j;
|
||||||
|
indirect_ok = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (j < 0) {
|
||||||
|
/* simple re-exporting doesn't work */
|
||||||
|
srcmname = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (srcmname) {
|
||||||
|
/* Simple re-exporting shortcut worked */
|
||||||
|
break;
|
||||||
|
} else if (!phase) {
|
||||||
|
/* The long way: evaluate id in a fresh namespace */
|
||||||
Scheme_Object *a[3], *ns;
|
Scheme_Object *a[3], *ns;
|
||||||
Scheme_Config *config;
|
Scheme_Config *config;
|
||||||
Scheme_Cont_Frame_Data cframe;
|
Scheme_Cont_Frame_Data cframe;
|
||||||
|
@ -1265,8 +1314,7 @@ static Scheme_Object *_dynamic_require(int argc, Scheme_Object *argv[],
|
||||||
if (i == count) {
|
if (i == count) {
|
||||||
if (indirect_ok) {
|
if (indirect_ok) {
|
||||||
/* Try indirect provides: */
|
/* Try indirect provides: */
|
||||||
Scheme_Module_Export_Info *exp_info = m->exp_infos[0];
|
Scheme_Module_Export_Info *exp_info = srcm->exp_infos[0];
|
||||||
srcm = m;
|
|
||||||
count = exp_info->num_indirect_provides;
|
count = exp_info->num_indirect_provides;
|
||||||
if (position >= 0) {
|
if (position >= 0) {
|
||||||
i = position;
|
i = position;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user