P.S. If the original designers of Java bytecode had allowed <init> to allocate 
its own object, and return it, we’d be having a different discussion.  I wish 
it had been like that.  I think it is a false economy to have “new X(…)” and 
“super(…)” call the same method symbol; that is the root of many evils.

On 13 Jul 2023, at 13:52, John Rose wrote:

> On 13 Jul 2023, at 7:24, Brian Goetz wrote:
>
>> This is a good thought; we split the initialization protocol and its a fair 
>> question to ask whether we can go back to a lump.
>>
>> In this case, I suspect John is about to say “Please let’s not give the 
>> verifier any more jobs to do.”
>
> It is that, and even worse.  If you work the details, you’ll quickly run into 
> the fact that the <init> protocol (for Java constructors) builds an object 
> but does not return the new object, it takes the new object from the caller 
> in a tabula rasa (blank) state, and pokes values into it.  Worse, the new 
> object is supplied (by a new opcode) from an untrusted (even hostile) client. 
>  That means that the verifier needs complex rules (>10% of the total 
> complexity) to track these untrusted-but-trusted blank objects and make sure 
> they are handed to <init> before being used.  That’s bad.  We have a steady 
> bug stream from this very delicate machinery.  Maybe it’s done after a 
> quarter century but I wouldn’t bet the farm on that.
>
> Worse still, for values, there is no architecturally defined state, for 
> values, which corresponds to the “tabula rasa” state of the receiver of an 
> <init> call.  We know something of that state; it is called a “larval 
> object”, but the Valhalla JVMS does not define or rely on it.  The proposed 
> “unification” would require us to somehow simulate larval objects in terms of 
> today’s blank identity objects, and define how the larval-to-adult state 
> transition works, or it would have to build new verifier rules for larval 
> objects (mutable while <init> runs, then pure values after that).  Either 
> option seems much worse than what we have chosen to do so far.
>
> What we have chosen to do so far is have a functionally clean model for value 
> objects that does not require mutability, either temporary (larval-only) or 
> permanent (I shudder at that thought). This functionally clean model uses 
> withfield instead of getfield, and aconst_init instead of the “new” opcode.  
> I think that is a great trade, because it lets us off the hook from defining 
> mutability into values, at any stage of their lifetimes.
>
> Yes, serialization smuggles larval mutability back in, but that’s a private 
> matter of optimization, between the VM and JDK.  I really don’t want to see 
> that in the JVMS, because it would be just as hairy and complex and bug-prone 
> as today’s new/<init> dance.  Yes, we should use the old mechanisms when we 
> can, and we do!  But the new/<init> dance is, IMO, hopelessly entangled with 
> a presupposition of object identity, and also hopelessly buggy; so I don’t 
> think it can help us, and I wouldn’t touch to extend it even if I thought it 
> might help.
>
> How’s that?  :-)

Reply via email to