----- Mail original ----- > De: "John Rose" <john.r.r...@oracle.com> > À: "daniel smith" <daniel.sm...@oracle.com> > Cc: "valhalla-spec-experts" <valhalla-spec-experts@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.sm...@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