While trying to run clojure on JNode I noticed that some dead code in
the ASM generated bytecode of clojure makes it fail because it
confuses the JIT.
One example of the problem can be seen with javap:
javap -c clojure.core\$last__2780
Result (relevant part) :
public java.lang.Object invoke(java.lang.Object) throws
java.lang.Exception;
Code:
0: getstatic #22; //Field const__0:Lclojure/lang/Var;
3: invokevirtual #37; //Method clojure/lang/Var.get:()Ljava/
lang/Object;
6: checkcast #39; //class clojure/lang/IFn
9: aload_1
10: invokeinterface #41, 2; //InterfaceMethod clojure/lang/
IFn.invoke:(Ljava/lang/Object;)Ljava/lang/Object;
15: dup
16: ifnull 47
19: getstatic #47; //Field java/lang/Boolean.FALSE:Ljava/
lang/Boolean;
22: if_acmpeq 48
25: getstatic #22; //Field const__0:Lclojure/lang/Var;
28: invokevirtual #37; //Method clojure/lang/Var.get:()Ljava/
lang/Object;
31: checkcast #39; //class clojure/lang/IFn
34: aload_1
35: invokeinterface #41, 2; //InterfaceMethod clojure/lang/
IFn.invoke:(Ljava/lang/Object;)Ljava/lang/Object;
40: astore_1
41: goto 0
44: goto 65
47: pop
48: getstatic #26; //Field const__1:Lclojure/lang/Var;
51: invokevirtual #37; //Method clojure/lang/Var.get:()Ljava/
lang/Object;
54: checkcast #39; //class clojure/lang/IFn
57: aload_1
58: aconst_null
59: astore_1
60: invokeinterface #41, 2; //InterfaceMethod clojure/lang/
IFn.invoke:(Ljava/lang/Object;)Ljava/lang/Object;
65: areturn
By investigating the bytecode one can notice that line: "44: goto
65" in unreachable. This creates the problem.
After some investigation of the clojure source code I came to the
conclusion that for this particular case changing the
clojure.lang.Compiler, r1193 at line 2367 to:
if(!(thenExpr instanceof RecurExpr))
gen.goTo(endLabel);
That is: if the thenExpr of the if node is such that it wouldn't fall
through to the elseExpr then there is no need to emit a goto bytecode
for jumping to the end of the if statement, bacause it will be
unreachable. With this change I rebuilt clojure and apparently it's
working fine, the bytecode of the method above is correct, but
unfortunately there are similar situations in other parts of the code
where usesless bytecode is emited.
For instance clojure.core$partition__3754.invoke(Object,Object,Object)
also contains deadcode similar to the above and it's related to the if
node.
If clojure will be used on other experimental, limited or non-
mainstream Java platforms such problems in the generated bytecode will
surface and create problems. The bugs in such paltforms (their
intolerance to various non-fatal byecode problems) can stay hidden
because the bytecode generated by javac doesn't have such problems.
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"Clojure" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
-~----------~----~----~----~------~----~------~--~---