> De: "John Rose" <john.r.r...@oracle.com> > À: "Remi Forax" <fo...@univ-mlv.fr> > Cc: "Valhalla Expert Group Observers" > <valhalla-spec-observ...@openjdk.java.net>, "daniel smith" > <daniel.sm...@oracle.com>, "valhalla-spec-experts" > <valhalla-spec-experts@openjdk.java.net> > Envoyé: Mercredi 28 Octobre 2020 20:08:30 > Objet: Re: Source code analysis: calls to wrapper class constructors
> Please accept the Tiger Woods Code Golf award for that one! Did i win something, a free t-shirt :) > It only works if the “dup” output (after “new”) is still contiguous > on the stack. That won’t be true if javac for some reason spilled > the result of “new” to a local instead of holding it on stack. > IIRC one reason to spill from stack to locals during expression > evaluation is if there is some kind of complicated control flow > inside the expression. Different javac’s historically have > different policies about stuff like that. I've never seen such bytecode shapes but I don't think i've ever seen a classfile compiled with a version which was less that Java 1.2. Rémi >> On Oct 28, 2020, at 4:25 AM, Remi Forax < [ mailto:fo...@univ-mlv.fr | >> fo...@univ-mlv.fr ] > wrote: >> ----- Mail original ----- >>> De: "John Rose" < [ mailto:john.r.r...@oracle.com | john.r.r...@oracle.com >>> ] > >>> À: "daniel smith" < [ mailto:daniel.sm...@oracle.com | >>> daniel.sm...@oracle.com ] >>> > >>> Cc: "valhalla-spec-experts" < [ >>> mailto:valhalla-spec-experts@openjdk.java.net | >>> 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 < [ mailto:daniel.sm...@oracle.com | >>> 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