summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRich Hickey <richhickey@gmail.com>2009-01-28 22:24:15 +0000
committerRich Hickey <richhickey@gmail.com>2009-01-28 22:24:15 +0000
commite8a3530e6f07275cb1a176a6bba2eca42d258e40 (patch)
tree3f79844358261b45612ef20e03e5cd2cce551f37
parent3ff5b944cd03878ea0ddfc3a345ea090bda37f1c (diff)
[lazy] added closed-over local tail clearing, for once-only fns, used in delay
-rw-r--r--src/jvm/clojure/lang/Compiler.java21
1 files changed, 21 insertions, 0 deletions
diff --git a/src/jvm/clojure/lang/Compiler.java b/src/jvm/clojure/lang/Compiler.java
index 0b57c389..50921f7f 100644
--- a/src/jvm/clojure/lang/Compiler.java
+++ b/src/jvm/clojure/lang/Compiler.java
@@ -2817,6 +2817,7 @@ static public class FnExpr implements Expr{
int line;
PersistentVector constants;
int constantsID;
+ boolean onceOnly = false;
public final IPersistentCollection methods(){
return methods;
@@ -2898,6 +2899,7 @@ static public class FnExpr implements Expr{
static Expr parse(C context, ISeq form, String name) throws Exception{
FnExpr fn = new FnExpr(tagOf(form));
FnMethod enclosingMethod = (FnMethod) METHOD.get();
+ fn.onceOnly = RT.booleanCast(RT.get(RT.meta(form.first()), Keyword.intern(null, "once")));
//fn.thisName = name;
String basename = enclosingMethod != null ?
(enclosingMethod.fn.name + "$")
@@ -3211,6 +3213,21 @@ static public class FnExpr implements Expr{
}
}
+ void emitClearCloses(GeneratorAdapter gen){
+ int a = 1;
+ for(ISeq s = RT.keys(closes); s != null; s = s.rest(), ++a)
+ {
+ LocalBinding lb = (LocalBinding) s.first();
+ Class primc = lb.getPrimitiveType();
+ if(primc == null)
+ {
+ gen.loadThis();
+ gen.visitInsn(Opcodes.ACONST_NULL);
+ gen.putField(fntype, lb.name, OBJECT_TYPE);
+ }
+ }
+ }
+
synchronized Class getCompiledClass(){
if(compiledClass == null)
try
@@ -3537,6 +3554,10 @@ public static class FnMethod{
}
}
}
+ if(fn.onceOnly)
+ {
+ fn.emitClearCloses(gen);
+ }
}
}