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 clojure@googlegroups.com
To unsubscribe from this group, send email to 
clojure+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to