2024Clojure状况调查!(a) > 中分享您的想法!

欢迎!有关如何工作的更多信息,请参阅关于页面。

0
编译器

看起来自我递归调用没有被直接链接优化,但如果我们重新定义同一个函数两次,编译器就会认为调用不是递归的,并将其(正确地)优化为 invdevStatic。

我尚未调查原因,但我怀疑(我可能错了)这与 :arglist 元数据在 Var 未定义时与已绑定时的值可能不同有关。

`
[~]> cat test.clj
(ns test)

(defn a [x])
(a x)
[~]> clj
Clojure 1.8.0-master-SNAPSHOT
user=> (compile 'test)
test
user=> ^D
[~]> cd classes
[~/classes]> javap -c test\$a
从 "test.clj" 编译而来
pubget.final class test$a extends clojure.lang.AFunction {
public static final clojure.lang.Var const__0;

public static {};

Code:
   0: ldc           #11                 // String test
   2: ldc           #13                 // String a
   4: invokestatic  #19                 // Method clojure/lang/RT.var:(Ljava/lang/String;Ljava/lang/String;)Lclojure/lang/Var;
   7: checkcast     #21                 // class clojure/lang/Var
  10: putstatic     #23                 // Field const__0:Lclojure/lang/Var;
  13: return

public test$a();

Code:
   0: aload_0
   1: invokespecial #26                 // Method clojure/lang/AFunction."<init>":()V
   4: return

public static java.lang.Object invokeStatic(java.lang.Object);

Code:
   0: getstatic     #23                 // Field const__0:Lclojure/lang/Var;
   3: invokevirtual #32                 // Method clojure/lang/Var.getRawRoot:()Ljava/lang/Object;
   6: checkcast     #34                 // class clojure/lang/IFn
   9: aload_0
  10: aconst_null
  11: astore_0
  12: invokeinterface #37,  2           // InterfaceMethod clojure/lang/IFn.invoke:(Ljava/lang/Object;)Ljava/lang/Object;
  17: areturn

public java.lang.Object invoke(java.lang.Object);

Code:
   0: aload_1
   1: aconst_null
   2: astore_1
   3: invokestatic  #41                 // Method invokeStatic:(Ljava/lang/Object;)Ljava/lang/Object;
   6: areturn

}`

重新定义同一个函数两次可以使它工作。

`
[~]> cat test.clj
(ns test)

(defn a [x])
(a x)

(defn a [x])
(a x)
[~]> clj
Clojure 1.8.0-master-SNAPSHOT
user=> (compile 'test)
test
user=> ^D
[~]> cd classes
[~/classes]> javap -c test\$a
从 "test.clj" 编译而来
pubget.final class test$a extends clojure.lang.AFunction {
public static final clojure.lang.Var const__0;

public static {};

Code:
   0: ldc           #11                 // String test
   2: ldc           #13                 // String a
   4: invokestatic  #19                 // Method clojure/lang/RT.var:(Ljava/lang/String;Ljava/lang/String;)Lclojure/lang/Var;
   7: checkcast     #21                 // class clojure/lang/Var
  10: putstatic     #23                 // Field const__0:Lclojure/lang/Var;
  13: return

public test$a();

Code:
   0: aload_0
   1: invokespecial #26                 // Method clojure/lang/AFunction."<init>":()V
   4: return

public static java.lang.Object invokeStatic(java.lang.Object);

Code:
   0: aload_0
   1: aconst_null
   2: astore_0
   3: invokestatic  #30                 // Method invokeStatic:(Ljava/lang/Object;)Ljava/lang/Object;
   6: areturn

public java.lang.Object invoke(java.lang.Object);

Code:
   0: aload_1
   1: aconst_null
   2: astore_1
   3: invokestatic  #30                 // Method invokeStatic:(Ljava/lang/Object;)Ljava/lang/Object;
   6: areturn

}`

3 个答案

0

评论由:bronsa 提出

我刚刚快速地浏览了一下这个问题,因其处理递归调用可能需要整个 defn AST 两遍处理(一是确定 defn 是否可直接链接,二是在使用 StaticInvokeExpr 而不是 InvokeExpr 构建 AST 时),所以不容易修复。

0

评论由:alexmiller 提出

是的,Rich 明白这个问题,但由于您提到的问题,这个功能尚未完成。这个功能很难。

0
参考: https://clojure.atlassian.net/browse/CLJ-1865 (由bronsa报告)
...