Fork me on GitHub
#clojure-dev
<
2017-04-24
>
ghadi14:04:03

hare-brained idea to enhance emitted code for map / vector construction: pre-construct an array with all the literal parameters -- then fill in only the dynamic parameters at runtime

ghadi14:04:12

should be simple with invokedynamic

tbaldridge14:04:49

Would only really work for larger maps though, < 8 items it's probably faster to create a PersistentArrayMap from an array instead of create a map and add some things to it.

ghadi14:04:54

there's probably a heuristic/threshold involved for sure, but even for < 8 items / PAM, half your slots are probably literal keywords

ghadi14:04:49

you would System.arraycopy the half-filled array, finish filling it in, and pass it to PAM/create()

tbaldridge14:04:09

right, but how is that faster than creating an array and filling in the pointers?

tbaldridge14:04:31

It's "copy an array, write 8 pointers" vs "create an array, write 16 pointers"

ghadi15:04:49

i saw a recent john rose talk last night, and he said the bytecode for creating an array is boilerplatey and hard to do escape analysis on

ghadi15:04:22

it would be 1 opcode for the invoke instead of a crap ton for pushing ints and arraystores

tbaldridge15:04:59

well it seems like it'd be easy enough to hack in and benchmark.

ghadi15:04:11

yeah i'll try to cook up a prototype later this week

tbaldridge15:04:13

I've thought of doing this in the past, but threw the idea out for the reasons I mentioned.

tbaldridge15:04:21

Never did benchmark it though

ghadi15:04:51

One of the challenges for this is representing the literals in bytecode

ghadi15:04:42

because the invokedynamic bootstrap method can only take constants/ldc as partial arguments

ghadi15:04:28

A crappy way to do it would be to print the "template" like "[:foo _ :bar _ :baz _]" and c.c/read it in the bootstrap method

ghadi15:04:06

ConstantDynamic "condy" is coming though! ... we'll have ldc instructions that can take a bootstrap method

ghadi15:04:53

One clever thing to encode the constant parameters of the bootstrap method: write a bitmap in an int of the filled out slots, then write the representations of a subset of literal expressions, like string/keyword/long. Longs would be unambiguous, and keywords could be strings w/ a magic prefix. So e.g. a boostrap method with these params: 10101010 (int) "kwfoo" "kwbar" "kwbaz" 42 BootstrapMethod (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Lclojure/lang/IPersistentMap ^ would result in a call site that took 4 arguments, and generated a map looking like:

{:foo arg1
 :bar arg2 
 :baz arg3 
 42 arg4}

ghadi16:04:29

the bootstrap method would look something like:

bootstrap (Lookup caller, String name, MethodType mt, int bitmap, Object... args) {
   Object[] template = new Object[Integer.bitCount(bitmap)];
   .... insert the args into the array template
   return ConstantCallSite(partial(fill_out_remaining(template, bitmap)));
}

ghadi16:04:08

integer keys in maps are probably not worth accounting for

ghadi16:04:18

just keywords and strings...