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