Source code analysis: calls to wrapper class constructors
forax at univ-mlv.fr
forax at univ-mlv.fr
Wed Oct 28 16:28:29 UTC 2020
----- Mail original -----
> De: "daniel smith" <daniel.smith at oracle.com>
> À: "Remi Forax" <forax at univ-mlv.fr>, "John Rose" <john.r.rose at oracle.com>
> Cc: "valhalla-spec-experts" <valhalla-spec-experts at 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.rose at 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 <forax at 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
>> 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
> 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)
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;
> ... [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.
More information about the valhalla-spec-observers