2024 年 Clojure 状态调查! 中分享您的想法。

欢迎!请参阅 关于 页面,了解更多关于此功能的信息。

+7
编译器
重标记
;; contrived one but the min repro that I could find
(defn foo [a]
  [(case a
     :f64 0
     :f32 1)
   (case a
     :f64 2
     :f32 3)
   (case a
     :f64 4
     :f32 5)])

这会导致编译错误:'方法大小过大!'

看起来我们遇到了两个关键字散列非常不幸运的情况。据我所知,`case` 宏查看散列之间的差异 ── 如果差异小于 8192,它会为一个中间值发射一个 tableswitch(O(1)),如果它更大,它会生成一个 lookupswitch(O(log n))。

例如,在这个案例中,散列是 1020273352 和 1020279615,因此它为两个之间的每个数字生成 tableswitch 条目(以允许常数时间查找)

在这个案例中,差异大约是 6200,因此它变成了一个(大的)tableswitch,在同一函数中三个这样的会导致超过 64kB 字节码限制。

解决方法(感谢 Clojurians 中的 @hiredman):在立即调用的函数中包围 `case` 语句 ── ((fn [] (case ...)))

谢谢,

James

1 个答案

0
by
selected by
by
加油,Alex!
...