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