> 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.
