1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-06-17 17:20:29 +02:00

Rebuild nested scopes for js continuations

* module/language/cps/compile-js.scm (compile-cont, compile-clause):
  Rebuild nested scopes for $kargs, using dominator information.
  (compile-fun, compile-clauses): Pass down dominator information.
This commit is contained in:
Ian Price 2017-06-20 19:05:59 +01:00
parent 936050c657
commit c2589b5c48

View file

@ -5,6 +5,7 @@
#:use-module ((language js-il) #:use-module ((language js-il)
#:renamer (lambda (x) (if (eqv? x 'make-prompt) 'make-prompt* x))) #:renamer (lambda (x) (if (eqv? x 'make-prompt) 'make-prompt* x)))
#:use-module (ice-9 match) #:use-module (ice-9 match)
#:use-module ((srfi srfi-1) #:select (append-map))
#:export (compile-js)) #:export (compile-js))
(define intmap-select (@@ (language cps compile-bytecode) intmap-select)) (define intmap-select (@@ (language cps compile-bytecode) intmap-select))
@ -27,12 +28,13 @@
(define (compile-fun cps kfun) (define (compile-fun cps kfun)
(define doms (compute-dom-edges (compute-idoms cps kfun)))
(match (intmap-ref cps kfun) (match (intmap-ref cps kfun)
(($ $kfun src meta self tail clause) (($ $kfun src meta self tail clause)
(make-function (make-function
(make-id self) (make-id self)
(make-kid tail) (make-kid tail)
(compile-clauses cps clause self))))) (compile-clauses cps doms clause self)))))
(define (extract-and-compile-conts cps) (define (extract-and-compile-conts cps)
@ -57,22 +59,21 @@
(intmap-fold step cps '())) (intmap-fold step cps '()))
(define (compile-clauses cps clause self) (define (compile-clauses cps doms clause self)
;; FIXME: This duplicates all the conts in each clause, and requires ;; FIXME: This duplicates all the conts in each clause, and requires
;; the inliner to remove them. A better solution is to change the ;; the inliner to remove them. A better solution is to change the
;; function type to contain a separate map of conts, but this requires ;; function type to contain a separate map of conts, but this requires
;; more code changes, and is should constitute a separate commit. ;; more code changes, and is should constitute a separate commit.
(define function-conts (extract-and-compile-conts cps))
(let loop ((clause clause)) (let loop ((clause clause))
(match (intmap-ref cps clause) (match (intmap-ref cps clause)
(($ $kclause arity body #f) (($ $kclause arity body #f)
`((,(make-kid clause) `((,(make-kid clause)
,(arity->params arity self) ,(arity->params arity self)
,(compile-clause cps arity body self function-conts)))) ,(compile-clause cps doms arity body self))))
(($ $kclause arity body next) (($ $kclause arity body next)
`((,(make-kid clause) `((,(make-kid clause)
,(arity->params arity self) ,(arity->params arity self)
,(compile-clause cps arity body self function-conts)) ,(compile-clause cps doms arity body self))
. ,(loop next)))))) . ,(loop next))))))
@ -91,27 +92,48 @@
allow-other-keys?)))) allow-other-keys?))))
(define (compile-clause cps arity body self bindings) (define (compile-clause cps doms arity body self)
(match arity (match arity
(($ $arity req opt rest ((_ _ kw-syms) ...) _) (($ $arity req opt rest ((_ _ kw-syms) ...) _)
(let ((ids (map make-id (let ((ids (map make-id
(append req opt kw-syms (if rest (list rest) '()))))) (append req opt kw-syms (if rest (list rest) '())))))
(make-continuation (make-continuation
(cons (make-id self) ids) (cons (make-id self) ids)
(make-local bindings (make-continue (make-kid body) ids))))))) (make-local (list (cons (make-kid body) (compile-cont cps doms body)))
(make-continue (make-kid body) ids)))))))
(define (compile-cont cps doms cont)
(define (compile-cont cps cont) (define (redominate label exp)
(match (intmap-ref cps cont) ;; This ensures that functions which are dominated by a $kargs [e.g.
;; The term in a $kargs is always a $continue ;; because they need its arguments] are moved into its body, and so
(($ $kargs names syms ($ $continue k src exp)) ;; we get correct scoping.
(make-continuation (map make-id syms) (compile-exp exp k))) (define (find&compile-dominated label)
(($ $kreceive ($ $arity req _ (? symbol? rest) _ _) k2) (append-map (lambda (label)
(let ((ids (map make-id (append req (list rest))))) (match (intmap-ref cps label)
(make-continuation ids (make-continue (make-kid k2) ids)))) (($ $ktail) '()) ; ignore tails
(($ $kreceive ($ $arity req _ #f _ _) k2) (($ $kargs)
(let ((ids (map make-id req))) ;; kargs may bind more arguments
(make-continuation ids (make-continue (make-kid k2) ids)))))) (list (cons (make-kid label) (compile label))))
(else
;; otherwise, even if it dominates other conts,
;; it doesn't need to contain them
(cons (cons (make-kid label) (compile label))
(find&compile-dominated label)))))
(intmap-ref doms label)))
(make-local (find&compile-dominated label) exp))
(define (compile cont)
(match (intmap-ref cps cont)
;; The term in a $kargs is always a $continue
(($ $kargs names syms ($ $continue k src exp))
(make-continuation (map make-id syms)
(redominate cont (compile-exp exp k))))
(($ $kreceive ($ $arity req _ (? symbol? rest) _ _) k2)
(let ((ids (map make-id (append req (list rest)))))
(make-continuation ids (make-continue (make-kid k2) ids))))
(($ $kreceive ($ $arity req _ #f _ _) k2)
(let ((ids (map make-id req)))
(make-continuation ids (make-continue (make-kid k2) ids))))))
(compile cont))
(define (compile-exp exp k) (define (compile-exp exp k)
(match exp (match exp