[records] Ancillary fields

Remi Forax forax at univ-mlv.fr
Wed Apr 18 21:45:12 UTC 2018



On April 18, 2018 8:39:12 PM UTC, Brian Goetz <brian.goetz at oracle.com> wrote:
>
>
>> Ahh, you missed the `lazy` keyword on there :-) Which is good because
>
>> it raises an issue: when you forget it, bad performance may result 
>> without other observable consequence. Although, it's already the case
>
>> that reading code like the above ought to raise all kinds of alarm 
>> bells (e.g., now I want to go check which fields computeHashCode() 
>> might be referring to, and where /they're/ initialized), so I 
>> /should/ be looking for that `lazy` keyword to put my mind at ease.
>So 
>> maybe this is okay.
>
>Well, "bad" is relative; it won't be any worse than what you do today 
>with eager static fields.  But yes, I did drop the lazy there.
>
>> I assume that, unlike other field initializers, I'm safe to refer 
>> to/any/ other field regardless of how and where that field is 
>> initialized. Right?
>
>I think you mostly are asking about instance fields.  It would be safe 
>to refer to any other field, however, if you _read_ a lazy field in the
>
>constructor, it might trigger computation of the field based on a 
>partially initialized object.  The compiler could warn on the obvious 
>cases where this happens, but of course it can be buried in a chain of 
>method calls.
>
>> The intersection with primitives is interesting. I assume it gets 
>> secretly created as an Integer? So there's a little extra hidden 
>> memory consumption.
>
>For static fields, there's an obvious and good answer that is optimally
>
>time and space efficient with no anomalies: condy.  We desugar
>
>     lazy static T t = e
>     ...
>     moo(t)
>
>into
>
>     // no field needed
>     static t$init() { return ; }
>     ...
>     moo( ldc condy[ ... ] )
>
>and let the constant pool do the lazy initialization and caching. JITs 
>love this.
>
>For instance fields, we have a choice; use extra space in the object to
>
>store the "already initialized" bit, or satisfy ourselves with the
>trick 
>that String does with hashCode() -- allow redundant recomputation in
>the 
>case where the initializer serves up the default value.
>
>So I think the divide is not ref-vs-primitive but whether we are
>willing 
>to take the recomputation hit when it serves up a default value.

I fully agree.
The lazy static with condy also has the same semantics, if the bsm do a side effect you may see that the bsm can be called multiple times.

For the record, I've just presented the lazy static this afternoon at devoxx fr (in order to explain the semantics of condy) and several people reach me afterward saying  it was in interesting idea.

Remi




-- 
Sent from my Android device with K-9 Mail. Please excuse my brevity.


More information about the amber-spec-experts mailing list