diff options
author | Rich Hickey <richhickey@gmail.com> | 2009-11-15 12:37:32 -0500 |
---|---|---|
committer | Rich Hickey <richhickey@gmail.com> | 2009-11-15 12:37:32 -0500 |
commit | ecd7161bf4397f04385fdaf9e5c6168580676ffa (patch) | |
tree | f10c8901e09939e522445d06bd36d797683d3521 | |
parent | a64704a9f163ed7271e527587c4d27073c25fc48 (diff) |
perf tweaks
-rw-r--r-- | src/clj/clojure/core_deftype.clj | 14 | ||||
-rw-r--r-- | src/jvm/clojure/lang/Compiler.java | 8 | ||||
-rw-r--r-- | src/jvm/clojure/lang/MethodImplCache.java | 13 | ||||
-rw-r--r-- | src/jvm/clojure/lang/Util.java | 10 | ||||
-rw-r--r-- | src/jvm/clojure/lang/Var.java | 2 |
5 files changed, 35 insertions, 12 deletions
diff --git a/src/clj/clojure/core_deftype.clj b/src/clj/clojure/core_deftype.clj index 58827784..3d77ad47 100644 --- a/src/clj/clojure/core_deftype.clj +++ b/src/clj/clojure/core_deftype.clj @@ -260,11 +260,13 @@ `(if (instance? ~on-interface ~target) (. ~(with-meta target {:tag on-interface}) ~(or on-method method) ~@(rest gargs))) `(do)) - (let [cache# (.__methodImplCache ~gthis) - c# (class ~target) - f# (or (.fnFor cache# c#) - (-cache-protocol-fn ~gthis ~target))] - (f# ~@gargs)))))) + (let [cache# (.__methodImplCache ~gthis)] + (if (clojure.lang.Util/identical (clojure.lang.Util/classOf ~target) + (.lastClass cache#)) + ((.lastImpl cache#) ~@gargs) + (let [f# (or (.fnFor cache# (clojure.lang.Util/classOf ~target)) + (-cache-protocol-fn ~gthis ~target))] + (f# ~@gargs)))))))) arglists))] (set! (.__methodImplCache f#) cache#) f#)))) @@ -287,7 +289,7 @@ (defn- emit-protocol [name opts+sigs] (let [[opts sigs] - (loop [opts {} sigs opts+sigs] + (loop [opts {:on nil} sigs opts+sigs] (condp #(%1 %2) (first sigs) string? (recur (assoc opts :doc (first sigs)) (next sigs)) keyword? (recur (assoc opts (first sigs) (second sigs)) (nnext sigs)) diff --git a/src/jvm/clojure/lang/Compiler.java b/src/jvm/clojure/lang/Compiler.java index 3f61aba0..24ccd87b 100644 --- a/src/jvm/clojure/lang/Compiler.java +++ b/src/jvm/clojure/lang/Compiler.java @@ -2755,7 +2755,8 @@ static class InvokeExpr implements Expr{ Expr e = (Expr) args.nth(0); e.emit(C.EXPRESSION, objx, gen); gen.dup(); //target, target - gen.invokeVirtual(OBJECT_TYPE,Method.getMethod("Class getClass()")); //target,class + gen.invokeStatic(UTIL_TYPE,Method.getMethod("Class classOf(Object)")); //target,class +// gen.invokeVirtual(OBJECT_TYPE,Method.getMethod("Class getClass()")); //target,class gen.dup(); //target,class,class gen.loadThis(); gen.getField(objx.objtype, objx.cachedClassName(siteIndex),CLASS_TYPE); //target,class,class,cached-class @@ -2778,19 +2779,17 @@ static class InvokeExpr implements Expr{ gen.dup(); //target,class,class gen.loadThis(); gen.swap(); - //gen.checkCast(CLASS_TYPE); gen.putField(objx.objtype, objx.cachedClassName(siteIndex),CLASS_TYPE); //target,class 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.checkCast(AFUNCTION_TYPE); gen.putField(objx.objtype, objx.cachedProtoFnName(siteIndex),AFUNCTION_TYPE); //target, class, proto-fn gen.dupX1(); //target, proto-fn, class, proto-fn - gen.checkCast(AFUNCTION_TYPE); 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 @@ -2801,7 +2800,6 @@ static class InvokeExpr implements Expr{ gen.dup(); //target,impl, impl gen.loadThis(); gen.swap(); - gen.checkCast(IFN_TYPE); gen.putField(objx.objtype, objx.cachedProtoImplName(siteIndex),IFN_TYPE); //target,impl gen.swap(); //impl,target gen.goTo(callLabel); diff --git a/src/jvm/clojure/lang/MethodImplCache.java b/src/jvm/clojure/lang/MethodImplCache.java index 8aac1c69..a8670a57 100644 --- a/src/jvm/clojure/lang/MethodImplCache.java +++ b/src/jvm/clojure/lang/MethodImplCache.java @@ -19,6 +19,10 @@ public final int shift; public final int mask; public final Object[] table; //[class, fn. class, fn ...] +//these are not volatile by design +public Object lastClass; +public IFn lastImpl; + public MethodImplCache(IPersistentMap protocol, Keyword methodk){ this(protocol, methodk, 0, 0, RT.EMPTY_ARRAY); } @@ -29,12 +33,19 @@ public MethodImplCache(IPersistentMap protocol, Keyword methodk, int shift, int this.shift = shift; this.mask = mask; this.table = table; + this.lastClass = this; } public IFn fnFor(Class c){ + if(c == lastClass) + return lastImpl; int idx = ((Util.hash(c) >> shift) & mask) << 1; if(idx < table.length && table[idx] == c) - return (IFn) table[idx + 1]; + { + lastClass = c; + return lastImpl = + (IFn) table[idx + 1]; + } return null; } diff --git a/src/jvm/clojure/lang/Util.java b/src/jvm/clojure/lang/Util.java index 0fd54475..6dcdade0 100644 --- a/src/jvm/clojure/lang/Util.java +++ b/src/jvm/clojure/lang/Util.java @@ -35,6 +35,16 @@ static public boolean equals(Object k1, Object k2){ return k1 != null && k1.equals(k2); } +static public boolean identical(Object k1, Object k2){ + return k1 == k2; +} + +static public Class classOf(Object x){ + if(x != null) + return x.getClass(); + return null; +} + static public int compare(Object k1, Object k2){ if(k1 == k2) return 0; diff --git a/src/jvm/clojure/lang/Var.java b/src/jvm/clojure/lang/Var.java index f2681f0c..2a603b03 100644 --- a/src/jvm/clojure/lang/Var.java +++ b/src/jvm/clojure/lang/Var.java @@ -128,6 +128,8 @@ public boolean isBound(){ } final public Object get(){ + if(count.get() == 0 && root != dvals) + return root; return deref(); } |