summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2021-03-04 06:19:12 -0800
committerKaz Kylheku <kaz@kylheku.com>2021-03-04 06:19:12 -0800
commite4b8ced9469facaddae849f982eab90c290ba820 (patch)
tree382f0c5347ca11c1a8482054c1e67fa28e8f996a
parent12bd13a955936fe1ee30bb4f2a202ecadd2cce9e (diff)
downloadtxr-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.tl27
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)))