Browsing the Clojure source code I came across an Intrinsics.java file. It looks like it is a mapping of some clojure runtime functions to JVM opcodes.
However, I am not sure where they get applied. The following code
(def ^:const pi 3.141592)
(defn circumference [^double r] (* r 2.0 pi))
compiles to
public static java.lang.Object invokeStatic(double r);
0 dload_0 [r]
1 ldc2_w <Double 2.0> [14]
4 dmul
5 ldc2_w <Double 3.141592> [16]
8 invokestatic clojure.lang.Numbers.multiply(double, double) : double [23]
11 invokestatic java.lang.Double.valueOf(double) : java.lang.Double [29]
14 areturn
and I see that clojure.lang.Numbers.multiply(double, double) : double did not get replaced to DMUL.
How exactly are intrinsics used? Thank you.
Currently intrinsics are only used where the expression being compiled is meant to remain unboxed. Thus the (* r 2.0) multiplication in your example does receive the intrinsic treatment (resulting in the one dmul in your example invokeStatic), but the (* #<result of (* r 2.0)> 3.141592) multiplication does not.
You can get the clojure.lang.Numbers.multiply(double, double) : double intrinsic to be applied to the multiplication by r as well by ensuring that the return type is double as well.
For example this:
(def ^:const pi 3.141592)
(defn circumference ^double [^double r] (* r 2.0 pi))
compiles to the following:
public static double invokeStatic(double r);
0 dload_0 [r]
1 ldc2_w <Double 2.0> [14]
4 dmul
5 ldc2_w <Double 3.141592> [16]
8 dmul
9 dreturn
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With