New draft JEP: intrinsics for String::format and Objects::hash (among others)

Brian Goetz brian.goetz at oracle.com
Mon Oct 22 21:30:24 UTC 2018


> I've recently discovered that the latest version of Eclipse is using Objects.hash() by default when you ask to auto-generate the hashCode,
> obviously this is plainly wrong because the current implementation does a lot object allocations, but at the same time, the code is more readable.
> So +200 on this JEP !

Well, it's right, but it may have a surprising(ly bad) cost model. The 
goal here is to let people write the right code, with the right 
(awesomely good!) cost model.  (And same for toString using 
String.format()).  These two methods were picked as first targets 
because (a) there is a significant win to be had for both, and (b) every 
class should use them.

> Now, the issues i see.
> if you translate the bytecode, you are loosing the call to String.format() so if there is a NPE because one of the parameter is null, String.format() will disappear from the stacktrace of this NPE.

Yes, correct.  The stack trace will point back at the line calling 
`format()`.

> Also, from the point of view of the bytecode analyzers that do an abstract execution of the bytecode (Jacoco, Findbugs, Proguard, any IDEs, etc) each of them will have to have a mechanism to go from the invokedynamic call to the original call so it an be interpreted. It's seem to be a waste of resources to not a standard way to get the original call at bytecode level.
This is a general issue with any sort of indy code generation from 
javac; bytecode interpreters may want to learn the meanings of standard 
bootstraps, considering them to be "new bytecodes".  The same will be 
true when we start generating indy for switch translation, or switching 
to condy for lambda translation, or starting doing more aggressive 
constant folding.

Note that while we're waiting for full constant folding, intrinsics can 
do limited constant folding too, such as

     `multiLineString`.align()

> Limiting these intrinsics to the JDK methods has a big drawbacks, it makes the performance model less easier to understand.
> By example, String.valueOf() will be fast but the method debug(String format, Object...) of a LOG4J Logger will be slower (even if it changes its implementation to use String.format internally because the format parameter will not be constant inside the implementation).

This is really two separate issues.  The real concern you're raising 
here is that by intrinsifying some methods, sometimes, but not others, 
and not at other times, the cost model becomes less transparent.  This 
is true, but this is also a fact of life with dynamic compilation, JVM 
intrinsics, etc.  Glass p% empty / q% full.

> I understand that you do not want to open the pandora box of offering a macro system to everybody, but i hope there is a knd of middle ground, here, perhaps by enabling any methods to use the instrinsics annotation but to limit the bootstrap methods that can be used to the ones defined in the JDK.

Yes, we may eventually consider loosening up along some axes, once we 
have a better understanding of the risks, costs, and benefits. For now, 
restricting it to the JDK is a no-brainer, while we gather data on 
efficacy and use cases.  There are many other potential targets in the 
JDK too.

Intrinsification might not result in an indy; it might result in an LDC 
(condy or not), or it might result in a shuffling of the parameters and 
a redirection to another method (yes, both can be simulated by indy, but 
at a cost.)  So "restricting bootstraps" is not an effective axis of 
restriction, but we can continue to look for axes along which this might 
be reasonably expanded.




More information about the amber-spec-experts mailing list