----- Mail original ----- > De: "daniel smith" <daniel.sm...@oracle.com> > À: "Remi Forax" <fo...@univ-mlv.fr>, "John Rose" <john.r.r...@oracle.com> > Cc: "valhalla-spec-experts" <valhalla-spec-experts@openjdk.java.net> > Envoyé: Mercredi 28 Octobre 2020 16:49:49 > Objet: Re: Source code analysis: calls to wrapper class constructors
>> On Oct 27, 2020, at 10:56 PM, John Rose <john.r.r...@oracle.com> wrote: >> >> 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. > > >> On Oct 28, 2020, at 3:25 AM, Remi Forax <fo...@univ-mlv.fr> wrote: >> >> 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. > > Don't forget the 'dup'. We're assuming a 'new' immediately followed by 'dup' > (4 > nops), and code that will eventually consume the second one and leave the > first > one fully-initialized. yes, i forget the DUP :) > > You're right that this disrupts verification; I think we can address this > pre-verification by rewriting the StackMapTable, eliminating all references to > 'uninitialized(Offset)' and shrinking the stack by two. Another solution, replace NEW [ref] DUP by NOP INVOKESTATIC java/lang/Integer giveMeAFakeInteger ()Ljava/lang/Integer; and replace the INVOKESPECIAL by an INVOKE_STATIC java/lang/Integer trampoline (Ljava/lang/Integer;I) with the method giveMeAFakeInteger returning a special Integer (can be null, maybe?) the method trampoline calling Integer.valueOf(). > > The bigger limitation, which I don't think you run into in any javac-generated > code, is that you can put a copy of the uninitialized object reference > anywhere > you want—in locals, duplicated 15 times on the stack, etc. That's the point > where I'm guessing we give up. > > So, there's a tractable rewrite for any code with the shape: > > new java/lang/Integer; > dup; > ... [ad hoc computation, as long as it doesn't touch the two uninitialized > Integer refs] > invokespecial java/lang/Integer.<init>(...)V; Yep, some codes not generated by javac or ecj will fail. Rémi