summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRich Hickey <richhickey@gmail.com>2010-04-05 17:52:55 -0400
committerRich Hickey <richhickey@gmail.com>2010-04-05 17:52:55 -0400
commit54ab7bd6b6b2894923cc0a9333a5ea39738ae4f6 (patch)
tree104648a9f77038a96b4622181e7694e7988aa3ac
parentc733148ba0fb3ff7bbab133f5375422972e62d08 (diff)
use reify for ILookupThunk impls in deftype
-rw-r--r--src/clj/clojure/core_deftype.clj16
-rw-r--r--src/jvm/clojure/lang/Compiler.java67
2 files changed, 9 insertions, 74 deletions
diff --git a/src/clj/clojure/core_deftype.clj b/src/clj/clojure/core_deftype.clj
index d8027302..8e13902a 100644
--- a/src/clj/clojure/core_deftype.clj
+++ b/src/clj/clojure/core_deftype.clj
@@ -149,13 +149,15 @@
(get ~'__extmap k# else#)))
`(getLookupThunk [~'this k#]
(case k#
- ~@(mapcat
- (fn [fld]
- (let [cstr (str (clojure.core/name classname) "$__lookup__" (clojure.core/name fld))]
- [(keyword fld)
- `(-> ~cstr (Class/forName) (.newInstance))]))
- base-fields)
- nil)))]
+ ~@(let [gtarget (gensym)
+ hinted-target (with-meta gtarget {:tag tagname})]
+ (mapcat
+ (fn [fld]
+ [(keyword fld)
+ `(reify clojure.lang.ILookupThunk
+ (get [_ ~gtarget] (. ~hinted-target ~fld)))])
+ base-fields))
+ nil)))]
[i m]))
(idynamictype [[i m]]
[(conj i 'clojure.lang.IDynamicType)
diff --git a/src/jvm/clojure/lang/Compiler.java b/src/jvm/clojure/lang/Compiler.java
index 080fc060..f4091281 100644
--- a/src/jvm/clojure/lang/Compiler.java
+++ b/src/jvm/clojure/lang/Compiler.java
@@ -6049,8 +6049,6 @@ static public class NewInstanceExpr extends ObjExpr{
fmap = fmap.assoc(sym, lb);
closesvec[i*2] = lb;
closesvec[i*2 + 1] = lb;
- if(!sym.name.startsWith("__"))
- compileLookupThunk(ret, sym);
}
//todo - inject __meta et al into closes - when?
@@ -6208,71 +6206,6 @@ static public class NewInstanceExpr extends ObjExpr{
return loader.defineClass(COMPILE_STUB_PREFIX + "." + ret.name, bytecode);
}
- static Class compileLookupThunk(NewInstanceExpr ret, Symbol fld) throws Exception{
- //String superName, NewInstanceExpr ret, String[] interfaceNames){
- ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
- ClassVisitor cv = cw;
- String iname = ret.internalName + "$__lookup__" + fld.name;
- String cname = ret.name + "$__lookup__" + fld.name;
- Class fclass = tagClass(tagOf(fld));
-
- //workaround until full support for type-hinted non-primitive fields
- if(!fclass.isPrimitive())
- fclass = Object.class;
-
- Type ftype = Type.getType(fclass);
- cv.visit(V1_5, ACC_PUBLIC + ACC_SUPER + ACC_FINAL, iname,
- null,"java/lang/Object",new String[]{"clojure/lang/ILookupThunk"});
-
- GeneratorAdapter ctorgen = new GeneratorAdapter(ACC_PUBLIC,
- voidctor,
- null,
- null,
- cv);
- ctorgen.visitCode();
- ctorgen.loadThis();
- ctorgen.invokeConstructor(OBJECT_TYPE, voidctor);
- ctorgen.returnValue();
- ctorgen.endMethod();
-
- Method meth = Method.getMethod("Object get(Object)");
-
- GeneratorAdapter gen = new GeneratorAdapter(ACC_PUBLIC,
- meth,
- null,
- null,
- cv);
- gen.visitCode();
- Label faultLabel = gen.newLabel();
- Label endLabel = gen.newLabel();
-
- gen.loadArg(0);
- gen.dup();
- gen.instanceOf(ret.objtype);
- gen.ifZCmp(GeneratorAdapter.EQ, faultLabel);
- gen.checkCast(ret.objtype);
- gen.getField(ret.objtype, munge(fld.name), ftype);
- HostExpr.emitBoxReturn(ret,gen,fclass);
- gen.goTo(endLabel);
-
- gen.mark(faultLabel);
- gen.pop();
- gen.loadThis();
-
- gen.mark(endLabel);
- gen.returnValue();
- gen.endMethod();
-
- //end of class
- cv.visitEnd();
-
- byte[] bytecode = cw.toByteArray();
- if(RT.booleanCast(COMPILE_FILES.deref()))
- writeClassFile(iname, bytecode);
- DynamicClassLoader loader = (DynamicClassLoader) LOADER.deref();
- return loader.defineClass(cname, bytecode);
- }
-
static String[] interfaceNames(IPersistentVector interfaces){
int icnt = interfaces.count();
String[] inames = icnt > 0 ? new String[icnt] : null;