> On Jul 13, 2023, at 3:05 PM, [email protected] 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.

Reply via email to