diff options
Diffstat (limited to 'src/jvm')
-rw-r--r-- | src/jvm/clojure/lang/Compiler.java | 119 |
1 files changed, 98 insertions, 21 deletions
diff --git a/src/jvm/clojure/lang/Compiler.java b/src/jvm/clojure/lang/Compiler.java index b1096704..060ce4d6 100644 --- a/src/jvm/clojure/lang/Compiler.java +++ b/src/jvm/clojure/lang/Compiler.java @@ -187,6 +187,9 @@ static final public Var KEYWORD_CALLSITES = Var.create(); //vector<var> static final public Var PROTOCOL_CALLSITES = Var.create(); +//vector<var> +static final public Var VAR_CALLSITES = Var.create(); + //keyword->constid static final public Var KEYWORDS = Var.create(); @@ -2734,11 +2737,13 @@ static class InvokeExpr implements Expr{ public final int line; public final String source; public boolean isProtocol = false; - public int siteIndex = 0; + public boolean isDirect = false; + public int siteIndex = -1; public Class protocolOn; public java.lang.reflect.Method onMethod; static Keyword onKey = Keyword.intern("on"); static Keyword methodMapKey = Keyword.intern("method-map"); + static Keyword dynamicKey = Keyword.intern("dynamic"); public InvokeExpr(String source, int line, Symbol tag, Expr fexpr, IPersistentVector args) throws Exception{ this.source = source; @@ -2767,6 +2772,17 @@ static class InvokeExpr implements Expr{ this.onMethod = (java.lang.reflect.Method) methods.get(0); } } + else if(pvar == null && VAR_CALLSITES.isBound() + && fvar.ns.name.name.startsWith("clojure") + && !RT.booleanCast(RT.get(RT.meta(fvar),dynamicKey)) +// && !fvar.sym.name.equals("report") +// && fvar.isBound() && fvar.get() instanceof IFn + ) + { + //todo - more specific criteria for binding these + this.isDirect = true; + this.siteIndex = registerVarCallsite(((VarExpr) fexpr).var); + } } this.tag = tag != null ? tag : (fexpr instanceof VarExpr ? ((VarExpr) fexpr).tag : null); } @@ -2795,6 +2811,23 @@ static class InvokeExpr implements Expr{ { emitProto(context,objx,gen); } + else if(isDirect) + { + Label callLabel = gen.newLabel(); + + gen.getStatic(objx.objtype, objx.varCallsiteName(siteIndex), IFN_TYPE); + gen.dup(); + gen.ifNonNull(callLabel); + + gen.pop(); + fexpr.emit(C.EXPRESSION, objx, gen); + gen.checkCast(IFN_TYPE); +// gen.dup(); +// gen.putStatic(objx.objtype, objx.varCallsiteName(siteIndex), IFN_TYPE); + + gen.mark(callLabel); + emitArgsAndCall(0, context,objx,gen); + } else { fexpr.emit(C.EXPRESSION, objx, gen); @@ -3044,7 +3077,9 @@ static public class FnExpr extends ObjExpr{ KEYWORDS, PersistentHashMap.EMPTY, VARS, PersistentHashMap.EMPTY, KEYWORD_CALLSITES, PersistentVector.EMPTY, - PROTOCOL_CALLSITES, PersistentVector.EMPTY)); + PROTOCOL_CALLSITES, PersistentVector.EMPTY, + VAR_CALLSITES, PersistentVector.EMPTY + )); //arglist might be preceded by symbol naming this fn if(RT.second(form) instanceof Symbol) @@ -3097,6 +3132,7 @@ static public class FnExpr extends ObjExpr{ fn.constants = (PersistentVector) CONSTANTS.deref(); fn.keywordCallsites = (IPersistentVector) KEYWORD_CALLSITES.deref(); fn.protocolCallsites = (IPersistentVector) PROTOCOL_CALLSITES.deref(); + fn.varCallsites = (IPersistentVector) VAR_CALLSITES.deref(); fn.constantsID = RT.nextID(); // DynamicClassLoader loader = (DynamicClassLoader) LOADER.get(); @@ -3153,6 +3189,7 @@ static public class ObjExpr implements Expr{ IPersistentVector keywordCallsites; IPersistentVector protocolCallsites; + IPersistentVector varCallsites; final static Method voidctor = Method.getMethod("void <init>()"); @@ -3318,6 +3355,12 @@ static public class ObjExpr implements Expr{ null, null); } + for(int i=0;i<varCallsites.count();i++) + { + cv.visitField(ACC_PRIVATE + ACC_STATIC + ACC_FINAL + , varCallsiteName(i), IFN_TYPE.getDescriptor(), null, null); + } + //static init for constants, keywords and vars GeneratorAdapter clinitgen = new GeneratorAdapter(ACC_PUBLIC + ACC_STATIC, Method.getMethod("void <clinit> ()"), @@ -3335,6 +3378,29 @@ static public class ObjExpr implements Expr{ if(keywordCallsites.count() > 0) emitKeywordCallsites(clinitgen); + for(int i=0;i<varCallsites.count();i++) + { + Label skipLabel = clinitgen.newLabel(); + Label endLabel = clinitgen.newLabel(); + Var var = (Var) varCallsites.nth(i); + clinitgen.push(var.ns.name.toString()); + clinitgen.push(var.sym.toString()); + clinitgen.invokeStatic(RT_TYPE, Method.getMethod("clojure.lang.Var var(String,String)")); + clinitgen.dup(); + clinitgen.invokeVirtual(VAR_TYPE,Method.getMethod("boolean hasRoot()")); + clinitgen.ifZCmp(GeneratorAdapter.EQ,skipLabel); + + clinitgen.invokeVirtual(VAR_TYPE,Method.getMethod("Object getRoot()")); + clinitgen.checkCast(IFN_TYPE); + clinitgen.putStatic(objtype, varCallsiteName(i), IFN_TYPE); + clinitgen.goTo(endLabel); + + clinitgen.mark(skipLabel); + clinitgen.pop(); + + clinitgen.mark(endLabel); + } + clinitgen.returnValue(); clinitgen.endMethod(); @@ -3374,11 +3440,6 @@ static public class ObjExpr implements Expr{ cv.visitField(ACC_PRIVATE, cachedProtoFnName(i), AFUNCTION_TYPE.getDescriptor(), null, null); cv.visitField(ACC_PRIVATE, cachedProtoImplName(i), IFN_TYPE.getDescriptor(), null, null); } - for(int i=0;i<keywordCallsites.count();i++) - { -// cv.visitField(ACC_FINAL, siteName(i), ILOOKUP_SITE_TYPE.getDescriptor(), null, null); -// cv.visitField(ACC_PUBLIC, thunkName(i), ILOOKUP_THUNK_TYPE.getDescriptor(), null, null); - } //ctor that takes closed-overs and inits base + fields Method m = new Method("<init>", Type.VOID_TYPE, ctorTypes()); @@ -3422,17 +3483,7 @@ static public class ObjExpr implements Expr{ } } - //copy static sites into instance site and thunk - for(int i=0;i<keywordCallsites.count();i++) - { -// ctorgen.loadThis(); -// ctorgen.getStatic(objtype,siteNameStatic(i),KEYWORD_LOOKUPSITE_TYPE); -// ctorgen.putField(objtype, siteName(i),ILOOKUP_SITE_TYPE); -// ctorgen.loadThis(); -// ctorgen.getStatic(objtype,siteNameStatic(i),KEYWORD_LOOKUPSITE_TYPE); -// ctorgen.putField(objtype, thunkName(i),ILOOKUP_THUNK_TYPE); - } - + ctorgen.visitLabel(end); ctorgen.returnValue(); @@ -3924,6 +3975,10 @@ static public class ObjExpr implements Expr{ return "__cached_proto_impl__" + n; } + String varCallsiteName(int n){ + return "__var__callsite__" + n; + } + String thunkNameStatic(int n){ return thunkName(n) + "__"; } @@ -5087,7 +5142,7 @@ private static KeywordExpr registerKeyword(Keyword keyword){ private static int registerKeywordCallsite(Keyword keyword){ if(!KEYWORD_CALLSITES.isBound()) - throw new IllegalAccessError(); + throw new IllegalAccessError("KEYWORD_CALLSITES is not bound"); IPersistentVector keywordCallsites = (IPersistentVector) KEYWORD_CALLSITES.deref(); @@ -5098,7 +5153,7 @@ private static int registerKeywordCallsite(Keyword keyword){ private static int registerProtocolCallsite(Var v){ if(!PROTOCOL_CALLSITES.isBound()) - throw new IllegalAccessError(); + throw new IllegalAccessError("PROTOCOL_CALLSITES is not bound"); IPersistentVector protocolCallsites = (IPersistentVector) PROTOCOL_CALLSITES.deref(); @@ -5107,6 +5162,18 @@ private static int registerProtocolCallsite(Var v){ return protocolCallsites.count()-1; } +private static int registerVarCallsite(Var v){ + if(!VAR_CALLSITES.isBound()) + throw new IllegalAccessError("VAR_CALLSITES is not bound"); + + IPersistentVector varCallsites = (IPersistentVector) VAR_CALLSITES.deref(); + + varCallsites = varCallsites.cons(v); + VAR_CALLSITES.set(varCallsites); + return varCallsites.count()-1; +} + + private static Expr analyzeSymbol(Symbol sym) throws Exception{ Symbol tag = tagOf(sym); if(sym.ns == null) //ns-qualified syms are always Vars @@ -5390,6 +5457,10 @@ public static Object load(Reader rdr, String sourcePath, String sourceName) thro RT.map(LOADER, RT.makeClassLoader(), SOURCE_PATH, sourcePath, SOURCE, sourceName, + METHOD, null, + LOCAL_ENV, null, + LOOP_LOCALS, null, + NEXT_LOCAL_NUM, 0, RT.CURRENT_NS, RT.CURRENT_NS.deref(), LINE_BEFORE, pushbackReader.getLineNumber(), LINE_AFTER, pushbackReader.getLineNumber() @@ -5496,6 +5567,10 @@ public static Object compile(Reader rdr, String sourcePath, String sourceName) t Var.pushThreadBindings( RT.map(SOURCE_PATH, sourcePath, SOURCE, sourceName, + METHOD, null, + LOCAL_ENV, null, + LOOP_LOCALS, null, + NEXT_LOCAL_NUM, 0, RT.CURRENT_NS, RT.CURRENT_NS.deref(), LINE_BEFORE, pushbackReader.getLineNumber(), LINE_AFTER, pushbackReader.getLineNumber(), @@ -5724,7 +5799,8 @@ static public class NewInstanceExpr extends ObjExpr{ KEYWORDS, PersistentHashMap.EMPTY, VARS, PersistentHashMap.EMPTY, KEYWORD_CALLSITES, PersistentVector.EMPTY, - PROTOCOL_CALLSITES, PersistentVector.EMPTY + PROTOCOL_CALLSITES, PersistentVector.EMPTY, + VAR_CALLSITES, PersistentVector.EMPTY )); if(ret.isDeftype()) { @@ -5751,6 +5827,7 @@ static public class NewInstanceExpr extends ObjExpr{ ret.constantsID = RT.nextID(); ret.keywordCallsites = (IPersistentVector) KEYWORD_CALLSITES.deref(); ret.protocolCallsites = (IPersistentVector) PROTOCOL_CALLSITES.deref(); + ret.varCallsites = (IPersistentVector) VAR_CALLSITES.deref(); } finally { |