评论者:hiredman
使用hoistedmethod-pass-1.diff,示例代码生成的字节码如下
`
user=> (println (no.disassemble/disassemble (fn [] (loop [b 0] (recur (loop [a 1] a))))))
// 从form-init1272682692522767658.clj编译(版本1.5 : 49.0,超级位)
public final class user$eval1675$fn__1676 extends clojure.lang.AFunction {
// 字段描述符 #7 Ljava/lang/Object;
public static final java.lang.Object const__0;
// 字段描述符 #7 Ljava/lang/Object;
public static final java.lang.Object const__1;
// 方法描述符 #10 ()V
// 栈:2,局部变量:0
public static {};
0 lconst_0
1 invokestatic java.lang.Long.valueOf(long) : java.lang.Long [16]
4 putstatic user$eval1675$fn__1676.const__0 : java.lang.Object [18]
7 lconst_1
8 invokestatic java.lang.Long.valueOf(long) : java.lang.Long [16]
11 putstatic user$eval1675$fn__1676.const__1 : java.lang.Object [20]
14 return
Line numbers:
[pc: 0, line: 1]
// 方法描述符 #10 ()V
// 栈:1,局部变量:1
public user$eval1675$fn__1676();
0 aload_0 [this]
1 invokespecial clojure.lang.AFunction() [23]
4 return
Line numbers:
[pc: 0, line: 1]
// 方法描述符 #25 ()Ljava/lang/Object;
// 栈:3,局部变量:3
public java.lang.Object invoke();
0 lconst_0
1 lstore_1 [b]
2 aload_0 [this]
3 lload_1 [b]
4 invokevirtual user$eval1675$fn__1676.__hoisted1677(long) : long [29]
7 lstore_1 [b]
8 goto 2
11 areturn
Line numbers:
[pc: 0, line: 1]
Local variable table:
[pc: 2, pc: 11] local: b index: 1 type: long
[pc: 0, pc: 11] local: this index: 0 type: java.lang.Object
// 方法描述符 #27 (J)J
// 栈:2,局部变量:5
public long __hoisted1677(long b);
0 lconst_1
1 lstore_3 [a]
2 lload_3
3 lreturn
Line numbers:
[pc: 0, line: 1]
Local variable table:
[pc: 2, pc: 3] local: a index: 3 type: long
[pc: 0, pc: 3] local: this index: 0 type: java.lang.Object
[pc: 0, pc: 3] local: b index: 1 type: java.lang.Object
}
nil
user=>
`
方法__hoisted1677的主体是内部循环
为参考,此处粘贴了同样函数编译于1.6.0版本的字节码部分 https://gist.github.com/hiredman/f178a690718bde773ba0 内部循环的主体缺失,因为它实现为一个自己的IFn类,该类被实例化后立即执行。它捕获数字的装箱版,并返回装箱版