summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRich Hickey <richhickey@gmail.com>2008-09-12 14:09:48 +0000
committerRich Hickey <richhickey@gmail.com>2008-09-12 14:09:48 +0000
commitdcd325e36cffdb53fee52dac186bcf02b7220452 (patch)
tree223407f447d566c60e5c5608ad460eb101eeb7ab /src
parent6d32a71c424d44bbec801d62db6cd90ff0312539 (diff)
interim checkin - delayed class loading infrastructure
Diffstat (limited to 'src')
-rw-r--r--src/jvm/clojure/lang/Compiler.java51
-rw-r--r--src/jvm/clojure/lang/Var.java5
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;
}