diff options
author | Rich Hickey <richhickey@gmail.com> | 2008-09-12 14:09:48 +0000 |
---|---|---|
committer | Rich Hickey <richhickey@gmail.com> | 2008-09-12 14:09:48 +0000 |
commit | dcd325e36cffdb53fee52dac186bcf02b7220452 (patch) | |
tree | 223407f447d566c60e5c5608ad460eb101eeb7ab /src | |
parent | 6d32a71c424d44bbec801d62db6cd90ff0312539 (diff) |
interim checkin - delayed class loading infrastructure
Diffstat (limited to 'src')
-rw-r--r-- | src/jvm/clojure/lang/Compiler.java | 51 | ||||
-rw-r--r-- | src/jvm/clojure/lang/Var.java | 5 |
2 files changed, 51 insertions, 5 deletions
diff --git a/src/jvm/clojure/lang/Compiler.java b/src/jvm/clojure/lang/Compiler.java index afb25dec..e087d088 100644 --- a/src/jvm/clojure/lang/Compiler.java +++ b/src/jvm/clojure/lang/Compiler.java @@ -275,7 +275,12 @@ static class DefExpr implements Expr{ public Object eval() throws Exception{ if(initProvided) - var.bindRoot(init.eval()); + { +// if(init instanceof FnExpr && ((FnExpr) init).closes.count()==0) +// var.bindRoot(new FnLoaderThunk((FnExpr) init,var)); +// else + var.bindRoot(init.eval()); + } if(meta != null) { var.setMeta((IPersistentMap) meta.eval()); @@ -2651,6 +2656,33 @@ static class SourceDebugExtensionAttribute extends Attribute{ } } +static class FnLoaderThunk extends RestFn{ + FnExpr fx; + Var v; + IFn f; + + FnLoaderThunk(FnExpr fx, Var v){ + super(0); + this.fx = fx; + this.v = v; + } + + protected Object doInvoke(Object args) throws Exception{ + IFn f = loadFn(); + return f.applyTo((ISeq) args); + } + + synchronized private IFn loadFn() throws Exception{ + if(f == null) + { + Class fc = fx.getCompiledClass(); + f = (IFn)fc.newInstance(); + v.swapRoot(f); + } + return f; + } +} + static public class FnExpr implements Expr{ static final String CONST_PREFIX = "const__"; IPersistentCollection methods; @@ -2685,6 +2717,8 @@ static public class FnExpr implements Expr{ final static Method getClassMethod = Method.getMethod("Class getClass()"); final static Method getClassLoaderMethod = Method.getMethod("ClassLoader getClassLoader()"); final static Method getConstantsMethod = Method.getMethod("Object[] getConstants(int)"); + private DynamicClassLoader loader; + private byte[] bytecode; public FnExpr(Object tag){ this.tag = tag; @@ -2981,16 +3015,22 @@ static public class FnExpr implements Expr{ //end of class cv.visitEnd(); - //define class and store - DynamicClassLoader loader = (DynamicClassLoader) LOADER.get(); - compiledClass = loader.defineClass(name, cw.toByteArray()); + loader = (DynamicClassLoader) LOADER.get(); + bytecode = cw.toByteArray(); + } + + synchronized Class getCompiledClass(){ + if(compiledClass == null) + compiledClass = loader.defineClass(name, bytecode); + return compiledClass; } public Object eval() throws Exception{ - return compiledClass.newInstance(); + return getCompiledClass().newInstance(); } public void emit(C context, FnExpr fn, GeneratorAdapter gen){ + getCompiledClass(); //emitting a Fn means constructing an instance, feeding closed-overs from enclosing scope, if any //fn arg is enclosing fn, not this gen.newInstance(fntype); @@ -3091,6 +3131,7 @@ static public class FnExpr implements Expr{ } return OBJECT_TYPE; } + } enum PSTATE{ diff --git a/src/jvm/clojure/lang/Var.java b/src/jvm/clojure/lang/Var.java index fe6b8b9d..fcbd746f 100644 --- a/src/jvm/clojure/lang/Var.java +++ b/src/jvm/clojure/lang/Var.java @@ -222,6 +222,11 @@ synchronized public void bindRoot(Object root){ _meta = _meta.assoc(macroKey, RT.F); } +synchronized void swapRoot(Object root){ + validate(getValidator(), root); + this.root = root; +} + synchronized public void unbindRoot(){ this.root = dvals; } |