diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2021-03-04 06:19:12 -0800 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2021-03-04 06:19:12 -0800 |
commit | e4b8ced9469facaddae849f982eab90c290ba820 (patch) | |
tree | 382f0c5347ca11c1a8482054c1e67fa28e8f996a | |
parent | 12bd13a955936fe1ee30bb4f2a202ecadd2cce9e (diff) | |
download | txr-e4b8ced9469facaddae849f982eab90c290ba820.tar.gz txr-e4b8ced9469facaddae849f982eab90c290ba820.tar.bz2 txr-e4b8ced9469facaddae849f982eab90c290ba820.zip |
compiler: bug: duplicate code in load-time lifting.
This issue affects the original code which lifts lambdas to
load-time, as well as the new, recently added code for
similarly lifting functional combinator expressions.
The problem is that the trick works by compiling an expression
twice. The result of the first compile is thrown away in the
case when we compile it again in the load-time context.
But compiling has a side effect: the expression itself
may have an embedded load-time-liftable expression, which gets
deposited into the load-time fragment list. Thus garbage ends
up in the list of load-time fragments.
We likely want to save and restore other things, like
allocated D regisers.
* share/txr/stdlib/compiler.tl (compiler shapshot, compiler
restore): New methods.
(comp-lambda-impl, comp-fun): Save a snapshot of the compiler state
before doing the speculative compilation. If we don't use that
compilation, we restore the state from the snapshot.
-rw-r--r-- | share/txr/stdlib/compiler.tl | 27 |
1 files changed, 22 insertions, 5 deletions
diff --git a/share/txr/stdlib/compiler.tl b/share/txr/stdlib/compiler.tl index de5788c2..c74a7fb2 100644 --- a/share/txr/stdlib/compiler.tl +++ b/share/txr/stdlib/compiler.tl @@ -185,7 +185,19 @@ (stab (hash :eql-based)) lt-frags last-form - var-spies)) + var-spies + + (:method snapshot (me) + (let ((snap (copy me))) + (set snap.dreg (copy me.dreg) + snap.data (copy me.data) + snap.sidx (copy me.sidx) + snap.stab (copy me.stab)) + snap)) + + (:method restore (me snap) + (replace-struct me snap)))) + (eval-only (defmacro compile-in-toplevel (me . body) @@ -1100,16 +1112,19 @@ (defmeth compiler comp-lambda (me oreg env form) (if *load-time* me.(comp-lambda-impl oreg env form) - (let* ((lambda-frag me.(comp-lambda-impl oreg env form)) + (let* ((snap me.(snapshot)) + (lambda-frag me.(comp-lambda-impl oreg env form)) (ok-lift-var-pov (all lambda-frag.fvars (lambda (sym) (not env.(lookup-var sym))))) (ok-lift-fun-pov (all lambda-frag.ffuns (lambda (sym) (not env.(lookup-fun sym)))))) - (if (and ok-lift-var-pov ok-lift-fun-pov) - me.(compile oreg env ^(sys:load-time-lit nil ,form)) - lambda-frag)))) + (cond + ((and ok-lift-var-pov ok-lift-fun-pov) + me.(restore snap) + me.(compile oreg env ^(sys:load-time-lit nil ,form))) + (t lambda-frag))))) (defmeth compiler comp-fun (me oreg env form) (mac-param-bind form (op arg) form @@ -1252,6 +1267,7 @@ (tree-bind (sym . args) form (let* ((fbind env.(lookup-fun sym t)) + (snap me.(snapshot)) (cfrag me.(comp-call-impl oreg env (if fbind 'call 'gcall) (if fbind fbind.loc me.(get-sidx sym)) args))) @@ -1265,6 +1281,7 @@ (eq (symbol-package sym) user-package)))))) (when (and ok-lift-var-pov ok-lift-fun-pov) + me.(restore snap) (set cfrag me.(compile oreg env ^(sys:load-time-lit nil ,form)))))) (pushnew sym cfrag.ffuns) cfrag))) |