Source code analysis: calls to wrapper class constructors
Remi Forax
forax at univ-mlv.fr
Wed Oct 28 09:25:59 UTC 2020
----- Mail original -----
> De: "John Rose" <john.r.rose at oracle.com>
> À: "daniel smith" <daniel.smith at oracle.com>
> Cc: "valhalla-spec-experts" <valhalla-spec-experts at openjdk.java.net>
> Envoyé: Mercredi 28 Octobre 2020 05:56:29
> Objet: Re: Source code analysis: calls to wrapper class constructors
> On Oct 27, 2020, at 12:27 PM, Dan Smith <daniel.smith at oracle.com> wrote:
>>
>> This tooling will support common bytecode patterns like 'new Foo; dup; ...;
>> invokespecial Foo.<init>;', but will not be a comprehensive solution.
>> (Mimicking the behavior of instance initialization method invocation in full
>> generality would be a very difficult task.)
>
> One of the reasons it’s not going to be comprehensive
> is code like new Integer(complicatedExpr()), in which
> the `new` and `invokespecial <init>` are separated
> by (almost) arbitrarily complex bytecode. The two
> instructions don’t even have to be in the same basic
> block (at the bytecode level):
>
> new Integer(foo() ? bar() : baz())
> // compiles to 4 BB’s in a diamond
>
> If we add switch expressions with large sub-blocks,
> I think we get peak separation of the start and
> end parts of the new/init dance:
>
> new Integer(switch (x) {
> case 1 -> { complicatedBlock: try { … } catch ... ; return 0;
> default -> { for (;;) … }} )
>
> All of this gives me yet one more reason we would have
> been better off with factory methods instead of
> open-coding the new/init dance. It was, in hindsight,
> a false economy to open code the object creation “guts”
> instead of putting them in factory API points.
>
> And with an eye toward future evolutions of legacy code
> (legacy code not yet in existence!), and uniformity with
> the factory methods of inline classes, let’s try harder
> to get rid of the new/init dance for identity objects.
I believe there is a quick and dirty trick,
replace new java/lang/Integer by 3 NOPs and replace INVOKESPECIAL java/lang/Integer <init> (I)V by INVOKESTATIC java/lang/Integer valueOf (I)Ljava/lang/Integer;
It has to be done after the code is verified because the new execution doesn't push java/lang/Integer on the stack anymore before calling the arbitrary init expression thus any StackMapTables in between the NOPs and INVOKESTATIC are invalid.
>
> — John
Rémi
More information about the valhalla-spec-observers
mailing list