Search code examples
clojurecompiler-constructionclojure-java-interop

What are Clojure Intrinsics


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.


Solution

  • 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