1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-05-01 12:20:26 +02:00

Primcall inlining in eval.scm, lazy function body compilation

* module/ice-9/eval.scm (primitive-eval): Lazily compile lambda bodies.
  Special-case calls to top-level or module variables, and recognize
  some of those calls as primcalls.  In that case, emit closures with
  the primcalls.
This commit is contained in:
Andy Wingo 2015-03-12 14:06:15 +01:00
parent eb0376567d
commit d76d80d23c

View file

@ -111,26 +111,60 @@
(or (memoized-typecode (syntax->datum #'type)) (or (memoized-typecode (syntax->datum #'type))
(error "not a typecode" (syntax->datum #'type))))))) (error "not a typecode" (syntax->datum #'type)))))))
(define-syntax-rule (lazy (arg ...) exp)
(letrec ((proc (lambda (arg ...)
(set! proc exp)
(proc arg ...))))
(lambda (arg ...)
(proc arg ...))))
(define (compile-lexical-ref depth width) (define (compile-lexical-ref depth width)
(lambda (env) (lambda (env)
(env-ref env depth width))) (env-ref env depth width)))
(define (compile-call f args) (define (compile-top-call cenv loc args)
(let ((f (compile f))) (let* ((module (env-toplevel cenv))
(var (%resolve-variable loc module)))
(define (primitive=? name)
"Return true if VAR is the same as the primitive bound to NAME."
(match loc
((mode . loc)
(and (match loc
((mod name* . public?) (eq? name* name))
(_ (eq? loc name)))
;; `module' can be #f if the module system was not yet
;; booted when the environment was captured.
(or (not module)
(eq? var (module-local-variable the-root-module name)))))))
(define-syntax-rule (maybe-primcall (prim ...) arg ...)
(cond
((primitive=? 'prim) (lambda (env) (prim (arg env) ...)))
...
(else (lambda (env) ((variable-ref var) (arg env) ...)))))
(match args (match args
(() (lambda (env) ((f env)))) (()
(lambda (env) ((variable-ref var))))
((a) ((a)
(let ((a (compile a))) (let ((a (compile a)))
(lambda (env) ((f env) (a env))))) (maybe-primcall
(null? nil? pair? struct? string? vector? symbol?
keyword? variable? bitvector? char? zero?
1+ 1- car cdr lognot not vector-length
variable-ref string-length struct-vtable)
a)))
((a b) ((a b)
(let ((a (compile a)) (let ((a (compile a))
(b (compile b))) (b (compile b)))
(lambda (env) ((f env) (a env) (b env))))) (maybe-primcall
(+ - * / eq? eqv? equal? = < > <= >=
ash logand logior logxor logtest logbit?
cons vector-ref struct-ref allocate-struct variable-set!)
a b)))
((a b c) ((a b c)
(let ((a (compile a)) (let ((a (compile a))
(b (compile b)) (b (compile b))
(c (compile c))) (c (compile c)))
(lambda (env) ((f env) (a env) (b env) (c env))))) (maybe-primcall (vector-set! struct-set!) a b c)))
((a b c . args) ((a b c . args)
(let ((a (compile a)) (let ((a (compile a))
(b (compile b)) (b (compile b))
@ -140,22 +174,57 @@
'() '()
(cons (compile (car args)) (lp (cdr args))))))) (cons (compile (car args)) (lp (cdr args)))))))
(lambda (env) (lambda (env)
(apply (f env) (a env) (b env) (c env) (apply (variable-ref var) (a env) (b env) (c env)
(let lp ((args args)) (let lp ((args args))
(if (null? args) (if (null? args)
'() '()
(cons ((car args) env) (lp (cdr args)))))))))))) (cons ((car args) env) (lp (cdr args))))))))))))
(define (compile-box-ref box) (define (compile-call f args)
(match f
((,(typecode box-ref) . (,(typecode resolve) . loc))
(lazy (env) (compile-top-call env loc args)))
(_
(match args
(()
(let ((f (compile f)))
(lambda (env) ((f env)))))
((a)
(let ((f (compile f))
(a (compile a)))
(lambda (env) ((f env) (a env)))))
((a b)
(let ((f (compile f))
(a (compile a))
(b (compile b)))
(lambda (env) ((f env) (a env) (b env)))))
((a b c)
(let ((f (compile f))
(a (compile a))
(b (compile b))
(c (compile c)))
(lambda (env) ((f env) (a env) (b env) (c env)))))
((a b c . args)
(let ((f (compile f))
(a (compile a))
(b (compile b))
(c (compile c))
(args (let lp ((args args))
(if (null? args)
'()
(cons (compile (car args)) (lp (cdr args)))))))
(lambda (env)
(apply (f env) (a env) (b env) (c env)
(let lp ((args args))
(if (null? args)
'()
(cons ((car args) env) (lp (cdr args)))))))))))))
(define (compile-box-ref cenv box)
(match box (match box
((,(typecode resolve) . var-or-loc) ((,(typecode resolve) . loc)
(lambda (env) (let ((var (%resolve-variable loc (env-toplevel cenv))))
(cond (lambda (env) (variable-ref var))))
((variable? var-or-loc) (variable-ref var-or-loc))
(else
(set! var-or-loc
(%resolve-variable var-or-loc (env-toplevel env)))
(variable-ref var-or-loc)))))
((,(typecode lexical-ref) depth . width) ((,(typecode lexical-ref) depth . width)
(lambda (env) (lambda (env)
(variable-ref (env-ref env depth width)))) (variable-ref (env-ref env depth width))))
@ -164,13 +233,9 @@
(lambda (env) (lambda (env)
(variable-ref (box env))))))) (variable-ref (box env)))))))
(define (compile-resolve var-or-loc) (define (compile-resolve cenv loc)
(lambda (env) (let ((var (%resolve-variable loc (env-toplevel cenv))))
(cond (lambda (env) var)))
((variable? var-or-loc) var-or-loc)
(else
(set! var-or-loc (%resolve-variable var-or-loc (env-toplevel env)))
var-or-loc))))
(define (compile-if test consequent alternate) (define (compile-if test consequent alternate)
(let ((test (compile test)) (let ((test (compile test))
@ -477,7 +542,7 @@
(let ((proc (proc env))) (let ((proc (proc env)))
(set-procedure-property! proc prop val) (set-procedure-property! proc prop val)
proc)))))) proc))))))
(let ((body (compile body))) (let ((body (lazy (env) (compile body))))
(set-procedure-meta (set-procedure-meta
meta meta
(match tail (match tail
@ -560,10 +625,10 @@
(compile-call f args)) (compile-call f args))
((,(typecode box-ref) . box) ((,(typecode box-ref) . box)
(compile-box-ref box)) (lazy (env) (compile-box-ref env box)))
((,(typecode resolve) . var-or-loc) ((,(typecode resolve) . loc)
(compile-resolve var-or-loc)) (lazy (env) (compile-resolve env loc)))
((,(typecode if) test consequent . alternate) ((,(typecode if) test consequent . alternate)
(compile-if test consequent alternate)) (compile-if test consequent alternate))
@ -604,10 +669,10 @@
((,(typecode call/cc) . proc) ((,(typecode call/cc) . proc)
(compile-call/cc proc)))) (compile-call/cc proc))))
(let ((proc (compile (let ((eval (compile
(memoize-expression (memoize-expression
(if (macroexpanded? exp) (if (macroexpanded? exp)
exp exp
((module-transformer (current-module)) exp))))) ((module-transformer (current-module)) exp)))))
(env #f)) (env #f))
(proc env))) (eval env)))