I think this analysis is largely right. On the stack (parameters, returns, locals), the difference between B2/B3.ref and B3.val will be minimal; some extra register allocation pressure for the null channel, and that’s it. So I think its reasonable to say “doesn’t matter” for these.
Where B3.val pays for itself in performance (but has a cost in other complexity) is on the heap, and doubly so when dealing with larger volumes of data (e.g., arrays.) > With this kind of guidance, a focus on the density of storage, and a > good way to spell ".val", I can see the benefit of Kevin's approach. This is mostly where I am (though, there’s more to stack, and the ref/val thing is only part of it, so we have to look at the whole picture.) > On Apr 26, 2022, at 2:37 PM, Dan Heidinga <heidi...@redhat.com> wrote: > > Where is a B3 (.val) instance preferable to a B2 (B3 .ref) instance? > What are the criteria that would make an API designer expose a B3 > (.val) instance in their method descriptors? > > The primary benefit of a B3 (.val) instance over a B2 instance is > memory density. This relates to the containers holding the value. > The benefits are most evident when dealing with larger numbers of > flattened instances or arrays that live in the heap. The B3 (.val) is > primarily a benefit for backing storage. Agreed? > > For API points, the .val instance ensures that nulls are impossible > and the methods can avoid null checks but may need special handling > for the all-zero value. There are potentially performance benefits > from the calling conventions knowing a priori that null isn't in the > value set. The impact of this is TBD. Alternatively, the default > .ref has the benefits Kevin pointed out in his original email (not > repeating them here). > > Tearing only comes into play when writing to storage. It's a > non-issue for API points. Anything controversial here? > > The question again is what's the primary reason(s) for exposing a B3 > (.val) vs B2 instance in APIs? What guidance would we give API > designers around the use of B3 .val instances? > > My initial attempt at this: > * Use B3 .val instances for backing storage - so instance variables, > arrays, and static fields (Flattening of statics tbd). > * Use B3 .val instances for internal private API points - so private > methods or package private methods where the instance has already come > through some front door > * Use B2 (B3 .ref) in most public APIs for migration, avoiding bad > default values, etc as per Kevin's initial email - at the risk of > slightly worse performance? > * Use B3 .val instances for the small set of public APIs where every > inch of performance matters (and only after proving it matters) > > With this kind of guidance, a focus on the density of storage, and a > good way to spell ".val", I can see the benefit of Kevin's approach. > Still not 100% on board but persuadable. > > In the B3 defaults to .ref model, what does the constructor return? > An L or Q? Can the user control that? > > Remi's "new Complex(r, i)" example left me wondering do users say: > Complex.val c = new Complex(1, 2); > or > Complex.val c = new Complex.val(1, 2); > > Does the Complex class author decide by providing one or the other > form of constructor: > Complex.val(int r, int i) { /* Return QComplex */ .... } > and > Complex(int r, int i) { /* Return LComplex */ .... } > > The instance itself doesn't change but there may be conversions > (checkcast) needed one way or the other. > > --Dan > > On Tue, Apr 26, 2022 at 1:56 PM Dan Smith <daniel.sm...@oracle.com> wrote: >> >> On Apr 26, 2022, at 8:45 AM, Kevin Bourrillion <kev...@google.com> wrote: >> >> I think I would insist that `.val` be spelled with only one additional >> character... or even that the value type be generated as the snake_case form >> of the name! >> >> >> Okay, this is a meaningful refinement that I find less objectionable. >> >> If it's '#Integer128' or 'Integer128!' instead of 'Integer128.val', we've >> trimmed away a chunk of the typing/reading overhead (though it's still >> there, and I think some of the overhead is directly in service of what you >> find attractive—the idea that the value type is something unnatural/a >> departure from the norm). >> >> If it's 'integer128' and 'Integer128', well now there is no "default" type, >> and I think we're talking about something categorically different. There are >> some new (surmountable?) problems, but my earlier objections don't apply. >> >