The last miles
Dan Smith
daniel.smith at oracle.com
Fri Jul 14 16:17:03 UTC 2023
> On Jul 13, 2023, at 3:05 PM, forax at univ-mlv.fr wrote:
>
> - outside the value class, the semantics of the opcode "new" is changed to be the semantics of "aconst_init" if the class is a value class.
> invokespecial Complex <init>()V semantics is changed if Complex is a value class, so on stack takes two instances + the parameters and calls <init>(LComplex;)LComplex;
>
> It's not beautiful, it's a hack, as Brian said it's a lump move. But it's not as bad as you seem to think :)
We sort of tried this when we looked at migrating existing 'new Integer(0)' calls in bytecode. There, we looked for a simple bytecode translation, turning this:
new java/lang/Integer;
dup;
iconst_0;
invokespecial java/lang/Integer.<init>:(I)V;
into this:
aconst_init java/lang/Integer;
dup;
iconst_0;
invokemagic java/lang/Integer.<vnew>:(I)Ljava/lang/Integer;;
For full generality, the 'invokemagic' operation should:
- On entry, consume an Integer along with method args, as if it were invoking an instance method
- On return, replace every Integer on the stack/in locals that was produced by the same 'aconst_init' call as the "receiver" with the <vnew> result
This seemed like a pretty significant new JVM behavior, so instead we tentatively proposed shifting the responsibility to an external compatibility tool, which could perform a bytecode rewrite and wasn't obligated to support all shapes. (We should get data on this, but for presumably almost all constructor invocations, the "every Integer on the stack/in locals" reduces to "the variable currently on the top of the stack". Obviously a simpler problem, but not a constraint the JVM imposes.)
---
Another idea we've thought about is a magic '<new>' method. It would look something like:
iconst_0;
invokestatic java/lang/Integer.<new>:(I)Ljava/lang/Integer;
At the declaration site, it's *impossible to declare* a <new> method. Instead, the behavior is implicit:
- If Integer is an identity class, the effect of '<new>' is to do new/dup/<init>
- If Integer is a value class, the effect of '<new>' is to call <vnew>
(A sub-diversion we went on was to allow user-declared '<new>' methods—factories, basically. But there are guarantees you get from direct 'new' calls that you lose if you let people write their own factories. We weren't comfortable with that.)
The magic '<new>' method seems reasonable, and provides a path going forward to get rid of new/dup/<init> code. But it doesn't do anything for legacy bytecode. So the problem of needing a bytecode rewriting tool remains.
More information about the valhalla-spec-observers
mailing list