diff options
Diffstat (limited to 'src/jvm')
-rw-r--r-- | src/jvm/clojure/lang/Compiler.java | 72 | ||||
-rw-r--r-- | src/jvm/clojure/lang/MethodImplCache.java | 27 |
2 files changed, 37 insertions, 62 deletions
diff --git a/src/jvm/clojure/lang/Compiler.java b/src/jvm/clojure/lang/Compiler.java index 36594ce1..3febaee6 100644 --- a/src/jvm/clojure/lang/Compiler.java +++ b/src/jvm/clojure/lang/Compiler.java @@ -2885,11 +2885,8 @@ static class InvokeExpr implements Expr{ } public void emitProto(C context, ObjExpr objx, GeneratorAdapter gen){ - Label elseLabel = gen.newLabel(); - Label notSameClassLabel = gen.newLabel(); - Label faultLabel = gen.newLabel(); - Label callLabel = gen.newLabel(); Label onLabel = gen.newLabel(); + Label callLabel = gen.newLabel(); Label endLabel = gen.newLabel(); Var v = ((VarExpr)fexpr).var; @@ -2897,70 +2894,26 @@ static class InvokeExpr implements Expr{ Expr e = (Expr) args.nth(0); e.emit(C.EXPRESSION, objx, gen); gen.dup(); //target, target + gen.invokeStatic(UTIL_TYPE,Method.getMethod("Class classOf(Object)")); //target,class + gen.loadThis(); + gen.getField(objx.objtype, objx.cachedClassName(siteIndex),CLASS_TYPE); //target,class,cached-class + gen.visitJumpInsn(IF_ACMPEQ, callLabel); //target if(protocolOn != null) { + gen.dup(); //target, target gen.instanceOf(Type.getType(protocolOn)); gen.ifZCmp(GeneratorAdapter.NE, onLabel); - gen.dup(); } - gen.invokeStatic(UTIL_TYPE,Method.getMethod("Class classOf(Object)")); //target,class - gen.dup(); //target,class,class - gen.loadThis(); - gen.getField(objx.objtype, objx.cachedClassName(siteIndex),CLASS_TYPE); //target,class,class,cached-class - gen.visitJumpInsn(IF_ACMPNE, notSameClassLabel); //target,class - objx.emitVar(gen, v); - gen.invokeVirtual(VAR_TYPE, Method.getMethod("Object getRawRoot()")); //target, class, proto-fn - gen.dup(); //target, class, proto-fn, proto-fn - gen.loadThis(); - gen.getField(objx.objtype, objx.cachedProtoFnName(siteIndex),AFUNCTION_TYPE); //target,class, proto-fn,proto-fn,cached-proto-fn - gen.visitJumpInsn(IF_ACMPNE, elseLabel); //target,class, proto-fn - gen.pop(); //target,class - gen.pop(); //target - gen.loadThis(); - gen.getField(objx.objtype, objx.cachedProtoImplName(siteIndex),IFN_TYPE); //target,proto-impl - gen.swap(); //proto-impl, target - gen.goTo(callLabel); - - gen.mark(notSameClassLabel); //target,class - gen.dup(); //target,class,class + gen.mark(callLabel); //target + gen.dup(); //target, target + gen.invokeStatic(UTIL_TYPE,Method.getMethod("Class classOf(Object)")); //target,class gen.loadThis(); gen.swap(); - gen.putField(objx.objtype, objx.cachedClassName(siteIndex),CLASS_TYPE); //target,class + gen.putField(objx.objtype, objx.cachedClassName(siteIndex),CLASS_TYPE); //target objx.emitVar(gen, v); - gen.invokeVirtual(VAR_TYPE, Method.getMethod("Object getRawRoot()")); //target, class, proto-fn - - gen.mark(elseLabel); //target, class, proto-fn - gen.checkCast(AFUNCTION_TYPE); - gen.dup(); //target,class,proto-fn,proto-fn - gen.loadThis(); - gen.swap(); - gen.putField(objx.objtype, objx.cachedProtoFnName(siteIndex),AFUNCTION_TYPE); //target, class, proto-fn - gen.dupX1(); //target, proto-fn, class, proto-fn - gen.getField(AFUNCTION_TYPE,"__methodImplCache", Type.getType(MethodImplCache.class)); //target,protofn,class,cache - gen.swap(); //target,protofn,cache,class - gen.invokeVirtual(Type.getType(MethodImplCache.class),Method.getMethod("clojure.lang.IFn fnFor(Class)")); //target,protofn,impl - gen.dup(); //target,protofn,impl, impl - gen.ifNull(faultLabel); //target,protofn,impl - gen.swap(); //target,impl, protofn - gen.pop(); //target, impl - gen.dup(); //target,impl, impl - gen.loadThis(); + gen.invokeVirtual(VAR_TYPE, Method.getMethod("Object getRawRoot()")); //target, proto-fn gen.swap(); - gen.putField(objx.objtype, objx.cachedProtoImplName(siteIndex),IFN_TYPE); //target,impl - gen.swap(); //impl,target - gen.goTo(callLabel); - - //not in fn table, null out cached fn and use proto-fn itself (which should seed table for next time) - gen.mark(faultLabel); //target,protofn,null - gen.pop(); //target, protofn - gen.swap(); //protofn, target - gen.loadThis(); - gen.visitInsn(Opcodes.ACONST_NULL); - gen.putField(objx.objtype, objx.cachedProtoFnName(siteIndex), AFUNCTION_TYPE); //target, class, proto-fn - gen.goTo(callLabel); - - gen.mark(callLabel); //impl, target emitArgsAndCall(1, context,objx,gen); gen.goTo(endLabel); @@ -2976,9 +2929,8 @@ static class InvokeExpr implements Expr{ Method m = new Method(onMethod.getName(), Type.getReturnType(onMethod), Type.getArgumentTypes(onMethod)); gen.invokeInterface(Type.getType(protocolOn), m); HostExpr.emitBoxReturn(objx, gen, onMethod.getReturnType()); - } + } gen.mark(endLabel); - } void emitArgsAndCall(int firstArgToEmit, C context, ObjExpr objx, GeneratorAdapter gen){ diff --git a/src/jvm/clojure/lang/MethodImplCache.java b/src/jvm/clojure/lang/MethodImplCache.java index 8d18a3b6..e4ed06d0 100644 --- a/src/jvm/clojure/lang/MethodImplCache.java +++ b/src/jvm/clojure/lang/MethodImplCache.java @@ -13,11 +13,24 @@ package clojure.lang; public final class MethodImplCache{ + +static public class Entry{ + final public Class c; + final public IFn fn; + + public Entry(Class c, IFn fn){ + this.c = c; + this.fn = fn; + } +} + public final IPersistentMap protocol; public final Keyword methodk; public final int shift; public final int mask; -public final Object[] table; //[class, fn. class, fn ...] +public final Object[] table; //[class, entry. class, entry ...] + +volatile Entry mre = null; public MethodImplCache(IPersistentMap protocol, Keyword methodk){ this(protocol, methodk, 0, 0, RT.EMPTY_ARRAY); @@ -32,12 +45,22 @@ public MethodImplCache(IPersistentMap protocol, Keyword methodk, int shift, int } public IFn fnFor(Class c){ + Entry last = mre; + if(last != null && last.c == c) + return last.fn; + return findFnFor(c); +} + +IFn findFnFor(Class c){ int idx = ((Util.hash(c) >> shift) & mask) << 1; if(idx < table.length && table[idx] == c) { - return (IFn) table[idx + 1]; + Entry e = ((Entry) table[idx + 1]); + mre = e; + return e != null ? e.fn : null; } return null; } + } |