Constant_Dynamic first experiences

Ghadi Shayban gshayban at
Mon Jul 2 20:31:44 UTC 2018

First of all, condy and indy are awesome and I really appreciate how
forward-looking the JVM goals are. Thank you so much for such
thoughtfully-designed tech.

In the Clojure compiler, I have been playing around with dynamic constants.
This is pretty cool stuff and I wanted to share the experience and ask a
couple questions.

(defn replace [x y coll]
  (map {:a x
        :b y} coll))

Currently our compiler creates and stores necessary constants into static
final fields during the static class initializer. In the stupid example
above, there are three such constants in the body (keywords :a, :b, the var

ConstantDynamic allows us to delay the constants' construction until they
are demanded (bsm linked).  This should save us clinit time and field
slots.  I've tested this out, and it works nicely -- I don't know how much
clinit time it saves, but there wasn't a startup regression, so kudos!

The other interesting thing in that function body is a map constructor.
This one is interesting because it's not a constant map, but the keys are
constants. The current emission strategy is to construct an array of kvs,
populate it, then call PersistentHashMap.create().  With condy the constant
keywords (the map's keys) be come `ldc`, but I would like to find a better
way to construct varargs things (like maps, sets, vectors, lists) without
all the array manipulating bytecode.  I've used MH.asCollector() and
asVarargsCollectors() with an indy callsite, but there was a slight
regression in startup time. In the example above the map construction
happens during normal execution of the method, but there are a lot of
_totally constant aggregates_ that get executed once only during clojure
runtime initialization (nearly everything is reified in the clojure
runtime: docstrings, file:line numbers.)

Is there anything that you would suggest for speeding up the (one-time)
creation of constant aggregates? Or am I best off with aastores then
calling a varargs constructor as we do currently?

How do constant dynamic and invokedynamic interact with jaotc? Can we teach
the AOT compiler about those things? (I'm assuming IndifiedStringConcat and
Lambdas already are understood by graal/jaotc)

What other techniques do you suggest for improving startup time?  I've
tried a lot of things, but delaying / not doing work is the safest bet.  I
don't really have a cost model for "early jvm bootup", but certainly we
load 2800 classes before you get a REPL.

Thanks again for all the cool technology.

More information about the amber-dev mailing list