From 7be9d4760b5e4d2fcbf72b60c0eeb6b861d4f841 Mon Sep 17 00:00:00 2001 From: Ben Smith-Mannschott Date: Tue, 18 Oct 2011 21:51:13 +0200 Subject: [PATCH] CLJ-850: Be sure invokePrim returning subclass of of Object properly implements Fn$XX Given: - P is some primitive type - O is type Object - R some subclass of Object: When Clojure generates a `R invokePrim(P x)`, it also generates a `O invoke(O x)` , which delegates to `R invokePrim(P x)`. `R invokePrim(P x)` overloads, but does not override the method of the corresponding Fn$PO interface. (Java, the virtual machine, supports overloading on return type, though Java the language does not.) Clojure needs to generate an additional `O invokePrim(P x)` method to satisfy the interface. This also delegates to `R invokePrim(P x)`. --- src/jvm/clojure/lang/Compiler.java | 22 +++++++++++++++++++--- 1 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/jvm/clojure/lang/Compiler.java b/src/jvm/clojure/lang/Compiler.java index 55e1268..6ed5280 100644 --- a/src/jvm/clojure/lang/Compiler.java +++ b/src/jvm/clojure/lang/Compiler.java @@ -5113,8 +5113,22 @@ public static class FnMethod extends ObjMethod{ } + private boolean isSubclassOfObject(Type t){ + final String d = t.getDescriptor(); + return d.startsWith("L") && !d.equals("Ljava/lang/Object;"); + } + public void doEmitPrim(ObjExpr fn, ClassVisitor cv){ - Method ms = new Method("invokePrim", getReturnType(), argtypes); + Type returnType = getReturnType(); + if (isSubclassOfObject(returnType)) + doEmitPrim(fn, cv, OBJECT_TYPE); + doEmitPrim(fn, cv, returnType); + doEmitDelegatingToPrim(fn, cv, returnType); + } + + private void doEmitPrim(ObjExpr fn, ClassVisitor cv, Type returnType){ + + Method ms = new Method("invokePrim", returnType, argtypes); GeneratorAdapter gen = new GeneratorAdapter(ACC_PUBLIC + ACC_FINAL, ms, @@ -5151,10 +5165,12 @@ public static class FnMethod extends ObjMethod{ gen.returnValue(); //gen.visitMaxs(1, 1); gen.endMethod(); + } - //generate the regular invoke, calling the prim method + private void doEmitDelegatingToPrim(ObjExpr fn, ClassVisitor cv, Type returnType) { Method m = new Method(getMethodName(), OBJECT_TYPE, getArgTypes()); - + Method ms = new Method("invokePrim", returnType, argtypes); + GeneratorAdapter gen; gen = new GeneratorAdapter(ACC_PUBLIC, m, null, -- 1.7.4.4