Status fields:
creation_ts: | 2008-06-14 12:59 |
---|---|
component: | verifier |
version: | default branch |
rep_platform: | All |
op_sys: | All |
bug_status: | NEW |
reporter: | stefan@complang.tuwien.ac.at |
From clojure_20080612.zip: $ cacao -cp clojure.jar clojure.lang.Repl Exception in thread "main" java.lang.ExceptionInInitializerError at clojure.lang.Repl.<clinit>(Repl.java:22) Caused by: java.lang.RuntimeException: clojure.lang.Compiler$CompilerException: boot.clj:208: subtype constraint violated (java.lang.Object is not a subclass of clojure.lang.IObj) at clojure.lang.RT.<clinit>(RT.java:255) at clojure.lang.Repl.<clinit>(Repl.java:22) Caused by: clojure.lang.Compiler$CompilerException: boot.clj:208: subtype constraint violated (java.lang.Object is not a subclass of clojure.lang.IObj) at clojure.lang.Compiler.analyzeSeq(Compiler.java:3759) at clojure.lang.Compiler.analyze(Compiler.java:3614) at clojure.lang.Compiler.analyze(Compiler.java:3589) at clojure.lang.Compiler.eval(Compiler.java:3779) at clojure.lang.Compiler.load(Compiler.java:4032) at clojure.lang.RT.loadResourceScript(RT.java:278) at clojure.lang.RT.doInit(RT.java:288) at clojure.lang.RT.<clinit>(RT.java:251) ...1 more Caused by: java.lang.LinkageError: subtype constraint violated (java.lang.Object is not a subclass of clojure.lang.IObj) at clojure.fns.clojure.meta__42.invoke(boot.clj:147) at clojure.fns.clojure.defn__50.doInvoke(boot.clj:203) at clojure.lang.RestFn.invoke(RestFn.java:460) at clojure.lang.Var.invoke(Var.java:291) at clojure.lang.AFn.applyToHelper(AFn.java:195) at clojure.lang.Var.applyTo(Var.java:396) at clojure.lang.Compiler.macroexpand1(Compiler.java:3688) at clojure.lang.Compiler.analyzeSeq(Compiler.java:3740) ...8 more
gij doesn't like it too much as well: $ gij -cp clojure.jar clojure.lang.Repl Exception in thread "main" java.lang.NoClassDefFoundError: clojure.fns.clojure.meta__42 at java.lang.Class.initializeClass(libgcj.so.9) at java.lang.Class.newInstance(libgcj.so.9) at clojure.lang.Compiler$FnExpr.eval(Compiler.java:2949) at clojure.lang.Compiler$DefExpr.eval(Compiler.java:267) at clojure.lang.Compiler.eval(Compiler.java:3780) at clojure.lang.Compiler.load(Compiler.java:4032) at clojure.lang.RT.loadResourceScript(RT.java:278) at clojure.lang.RT.doInit(RT.java:288) at clojure.lang.RT.<clinit>(RT.java:251) at java.lang.Class.initializeClass(libgcj.so.9) at clojure.lang.Repl.<clinit>(Repl.java:22) at java.lang.Class.initializeClass(libgcj.so.9) Caused by: java.lang.VerifyError: verification failed at PC 31 in clojure.fns.clojure.meta__42:invoke((Ljava.lang.Object;)Ljava.lang.Object;): incompatible type on stack at java.lang.Class.initializeClass(libgcj.so.9) ...11 more $ gij --version java version "1.5.0" gij (GNU libgcj) version 4.3.0 20080428 (Red Hat 4.3.0-8) Copyright (C) 2007 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Edwin, could you have a look at this one?
OK, I'm assigning that one to me now, but we need to have Edwin to take a look at that one.
The problem is this method in the generated meta__42 class: Method name:"invoke" public Descriptor: (java.lang.Object)java.lang.Object Attribute "Code", length:106, max_stack:3, max_locals:2, code_length:42 0: getstatic <Field clojure.fns.clojure.meta__42.const__0 clojure.lang.Var> 3: invokevirtual <Method clojure.lang.Var.get ()java.lang.Object> 6: checkcast <Class clojure.lang.IFn> 9: getstatic <Field clojure.fns.clojure.meta__42.const__1 java.lang.Class> 12: aload_1 13: invokeinterface <InterfaceMethod clojure.lang.IFn.invoke (java.lang.Object,java.lang.Object)java.lang.Object> nargs:3 18: dup 19: ifnull 39 22: getstatic <Field java.lang.Boolean.FALSE java.lang.Boolean> 25: if_acmpeq 40 28: aload_1 29: aconst_null 30: astore_1 31: invokeinterface <InterfaceMethod clojure.lang.IObj.meta ()clojure.lang.IPersistentMap> nargs:1 36: goto 41 39: pop 40: aconst_null 41: areturn The invokeinterface at 31 calls a method of clojure.lang.IObj using a java.lang.Object instance (loaded via aload_1). I wonder why this works with HotSpot. Maybe there is information in the class file that jcf-dump does not show correctly? -Edwin
Hmm, I'm not sure what I should answer. Maybe we really should forward this issue to an OpenJDK mailing list, e.g. hotspot-dev.
FYI <http://groups.google.com/group/clojure/browse_thread/thread/a9466e10ff9569f1> – From Rich Hickey (clojure author): "invokevirtual does not require a verified target type AFAIK" He just added a CHECKCAST instruction to the generated code <http://clojure.svn.sourceforge.net/viewvc/clojure?view=rev&revision=975>. I will soon verify if this makes it possible to run clojure.
The CHECKCAST instruction from the clojure svn makes the verifier happy. Unfortunately, another error happens shortly thereafter. clojure.lang.Compiler$CompilerException: boot.clj:1422: More than one matching method found: append (the line number reference in boot.clj applies to svn r925)
(I could have found out easier by using -noverify). While I'm definitely surprised that an invokeinterface can be used on a not CHECKCAST'ed type, I cannot find anything in the vmspec that states otherwise. In fact, the description of invokeinterface turns out to be interesting reading. It says that invokeinterface should throw an IncompatibleClassChangeError if the object on the stack does not implement the resolved interface.
A lot of information about invokeinterface is in PR88.
It seems that someone will need to come up with a clever idea how to check this at (invokeinterface) runtime then. It's sounds quite easy actually; we would just need to check if there is a non-zero pointer at interfaceindex.
The "More than one matching method found: append" error happens only with the classpath runtime, not with OpenJDK. At least we're fine there...
*** Bug 90 has been marked as a duplicate of this bug. ***
We discussed various potential solutions during yesterday's meeting. - Probably the best way to handle this would be to make the verifier flag such "bad" INVOKEINTERFACE instructions and generate runtime checks only for the flagged ones. However, noone is proficient with the verifier. - Another idea was to add a pseudo-CHECKCAST before invokeinterface which would behave like CHECKCAST but throw the correct exception (IncompatibleClassChange). This was not met with much enthusiasm. - Extending the SIGSEGV handler for this case was briefly proposed but I don't think this is feasible. - For a quick solution, a runtime flag could be added which would govern the creation of runtime checks (boundary check and non-null check).
*** Bug 90 has been marked as a duplicate of this bug. ***