Welcome! Please see the About page for a little more info on how this works.

+7 votes
in Compiler by
retagged by
;; 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)])

This fails to compile with a 'Method size too large!' error.

It looks like what's happening is that we're getting really unlucky with the hashes of the two keywords. AFAICT the case macro looks at the differences between the hashes - it emits a tableswitch (O(1)) of all of the intermediate values if the difference is less than 8192 and a lookupswitch (O(log n)) if it's greater.

e.g. in this case the hashes are 1020273352 and 1020279615, so it generates an entry in the tableswitch for every number between the two (to allow for constant time lookup)

In this case, the difference is about 6200, so it becomes a (large) tableswitch, and three of these in the same function causes it to go over the 64kB bytecode limit.

Work-around that worked for me (thanks @hiredman on Clojurians) is to enclose the case statements in an immediately invoked function - ((fn [] (case ...)))

Cheers,

James

1 Answer

0 votes
by
selected by
by
Cheers Alex!
...