JEP 303 vs JEP 348

forax at forax at
Thu Feb 14 11:50:41 UTC 2019

----- Mail original -----
> De: "Brian Goetz" <brian.goetz at>
> À: "Remi Forax" <forax at>
> Cc: "amber-spec-experts" <amber-spec-experts at>
> Envoyé: Mercredi 13 Février 2019 17:56:20
> Objet: Re: JEP 303 vs JEP 348

> I understand why you might think this, but there’s a method to our madness.
> Yes, both share the commonality of replacing a method call with something else.
> But, that’s where the similarity ends. 


> For JEP 348, this is an opportunistic
> optimization; for 303, it is essential functionality (the call can’t proceed
> un-intrinsified.)  And, for the indy() intrinsic, it simply cannot live without
> the constant folding and propagation.  So separating those aspects is not
> practical.

yes, on paper, but for JEP 348 you also need to know if the arguments of an intrinsics are constant or not.
For String.valueOf(), knowing if the format is constant or not allows further optimizations, for Objects.hash() if all arguments are constant then it's a ldc.
It's not hypothetical, the implementation of JEP 348 already works like this.

The only difference is that with JEP 348, you can fallback to an unoptimized version, while for JEP 303 you may think that having a non constant parameters for Intrinsics.ldc/invokedynamic make little sense but i beg to disagree (see below).

> The two differ dramatically in their spec impact, as well.  348 requires little
> more than permission to redirect the translation for specific methods; 303 is
> much more deeply intrusive.

We can pull the VarHandle trick !
Instead of specifying the semantics of Intrinsics.ldc/invokedynamic in the JLS which is as you said intrusive, you can move the spec part in the javadoc by transforming the compile time error to a runtime one.
If the arguments of Intrinsics.ldc/invokedynamic are not constant, the compiler can still generate an indy call that will verify at runtime that the arguments are constants (technically by verifying that methods are always called with the same instances doing pointer checks). So we have moved compile errors to runtime errors which is objectively bad but we have at the same time avoided big change of the JLS by transforming Intrinsics.ldc/invokedynamic to API point only.

We may still need enhanced constant folding but that's another concern.


* you can still generate an special indy for a call to Intrinsics.ldc or Intrisic.invokedynamic thats will verify at runtime that the arguments never changed, moving the compile error into a runtime error. You may think it's a stupid idea but it greatly simplify the spec.

>> On Feb 12, 2019, at 7:15 PM, Remi Forax <forax at> wrote:
>> JEP 348 provides a way to replace a method call with a ldc/indy,
>> so it's another way to implement JEP 303 (the intrinsification part) given that
>> an Intrinsics. (resp a ldc.invokedynamic) is just a method annotated with both
>> PolymorphicSignature and CompilerIntrinsicCandidate.
>> class Intrinsics {
>>    @CompilerIntrinsicCandidate
>>    @PolymorphicSignature
>>    public static Object invokedynamic(BootstrapSpecifier indy, Object... args) {
>>    return null; }
>> }
>> So in my opinion, we should withdraw JEP 303, adds a new JEP only about the
>> constant propagation + mirroring of ConstantDesc and add Intrinsics.ldc and
>> Intrinsic.invokedynamic as part of JEP 348.
> > Rémi

More information about the amber-spec-observers mailing list