<div dir="ltr"><div style="color:rgb(7,55,99)" class="gmail_default"><span style="font-family:monospace"><font size="4">Hello,</font></span></div><div style="color:rgb(7,55,99)" class="gmail_default"><span style="font-family:monospace"><font size="4"><br></font></span></div><div style="color:rgb(7,55,99)" class="gmail_default"><span style="font-family:monospace"><font size="4"><br></font></span></div><div class="gmail_default" style="color:rgb(7,55,99)"><span style="font-family:monospace"><font size="4">Would it be possible to decomplect nullability from a variable's encoding-mode (reference or inline)?<br></font></span></div><div class="gmail_default" style="color:rgb(7,55,99)"><span style="font-family:monospace"><font size="4"><br></font></span></div><div class="gmail_default" style="color:rgb(7,55,99)"><span style="font-family:monospace"><font size="4">I have been looking at the C# spec on "nullable-value-types" and I wonder if the Java runtime could do something similar under the hood to allow nullable-inlined-values, even on the heap.<br></font></span></div><div class="gmail_default" style="color:rgb(7,55,99)"><span style="font-family:monospace"><font size="4">I think that, compared to C#'s "value-types", Java can take advantage of the fact that its value-class instances are immutable, which means that pass-by-value or pass-by-reference is indistinguishable, which, with nullable-inlined-values,<font size="4"> could mean that</font> Java can have the variable encoding-mode completely encapsulated/hidden from the user-model as a runtime implementation detail.<br></font></span></div><div class="gmail_default" style="color:rgb(7,55,99)"><span style="font-family:monospace"><font size="4"><br></font></span></div><div class="gmail_default" style="color:rgb(7,55,99)"><span style="font-family:monospace"><font size="4">If this is possible, maybe Valhalla's Java could have a user-model like this:<br></font></span></div><div class="gmail_default" style="color:rgb(7,55,99)"><span style="font-family:monospace"><font size="4"><br></font></span></div><div class="gmail_default" style="color:rgb(7,55,99)"><span style="font-family:monospace"><font size="4"><br></font></span></div><div class="gmail_default" style="color:rgb(7,55,99)"><span style="font-family:monospace"><font size="4">*** A decomplected user-model ***<br></font></span></div><div class="gmail_default" style="color:rgb(7,55,99)"><span style="font-family:monospace"><font size="4"><br></font></span></div><div class="gmail_default" style="color:rgb(7,55,99)"><span style="font-family:monospace"><font size="4">For class-authors:<br><br> - *value-knob* to reject identity - 
Applicable on class declarations, indicates
that the class instances don't require identity (a value-class).<br> - 
*zero-knob* to indicate that the value-class has a zero-value - if a 
value-class does not have a zero-value, its instances won't be inlined 
in any shared-variables (§17.4.1.) since this is the only way for the language to 
ensure the non-existence of the zero-value. If the value-class is 
declared with a zero-value, then care must be taken when reading/writing
 constructors since *no constructor invariant can exclude the 
zero-value*.<br> - *tearable-knob* to allow tearing - Applicable on zero value-class 
declarations with bitSize > 32 bits, may be used by the class-author to hand the class-user the
 responsibility of how to avoid tearing, freeing the runtime to always 
inline instances in shared-mutables (non-final shared-variables). Conversely, if this knob is not 
used, instances will be kept atomic, which allows the class-author to 
guarantee constructor invariants *provided they're not broken by the zero-value*, which may be useful for the class 
implementation and class-users to rely upon.<br><br>For class-users:<br><br> -
 *not-nullable-knob (!)* to exclude null from a variable's value-set - 
Applicable on any variable declarations. On nullable variables, 
the default value is null and, in either encoding-mode (reference or inline), the runtime is 
free to choose the encoding for the extra bit of information required to
 represent the null state.<br> - *atomic-knob* to avoid tearing - Applicable on shared-mutable 
declarations, may be used to reverse the effect of the
 tearable-knob, thereby restoring atomicity.</font></span></div><div class="gmail_default" style="color:rgb(7,55,99)"><span style="font-family:monospace"><font size="4"><br></font></span></div><div class="gmail_default" style="color:rgb(7,55,99)"><span style="font-family:monospace"><font size="4"><br></font></span></div><div class="gmail_default" style="color:rgb(7,55,99)"><span style="font-family:monospace"><font size="4">The encoding-mode of a variable is decided at runtime according to this ternary expression:<br></font></span></div><div class="gmail_default"><span style="font-family:monospace"><font size="4"><span style="color:rgb(7,55,99)"><br></span></font></span></div><span style="font-family:monospace"><font size="4"><span style="color:rgb(7,55,99)"><span class="gmail_default" style="color:rgb(7,55,99)"></span>var encodingMode = <br>        !valueClass(variable.type)         ? REFERENCE    // value-knob<br>    :   tooBig(variable.type.bitSize)      ? REFERENCE<br>    :   !shared(variable)                  ? INLINE       // <span class="gmail_default" style="font-family:verdana,sans-serif;color:rgb(7,55,99)"></span>(§17.4.1.)<br>    :   !zeroValueClass(variable.type)     ? REFERENCE    // zero-knob<br>    :   final(variable)                    ? INLINE<br>    :   atomicWrite(variable.type.bitSize) ? INLINE<br>    :   atomic(variable)                   ? REFERENCE    // atomic-knob<br>    :   tearableValueClass(variable.type)  ? INLINE       // tearable-knob<br></span></font></span><div><span style="font-family:monospace"><font size="4"><span style="color:rgb(7,55,99)">    :                                        REFERENCE;<br></span></font></span></div><div><span style="font-family:monospace"><font size="4"><br><span style="color:rgb(7,55,99)"></span></font></span></div><div><span style="font-family:monospace"><font size="4"><span style="color:rgb(7,55,99)"></span></font></span></div><span style="font-family:monospace"><font size="4"><span style="color:rgb(7,55,99)">The variable.type.bitSize depends on nullability as nullable types may require more space.<br>The predicates tooBig and atomicWrite depend on the hardware. <span class="gmail_default" style="color:rgb(7,55,99)">As an</span> example, they could be:<br><br>    boolean tooBig(int bitSize)      {return bitSize > 256;}<br>    boolean atomicWrite(int bitSize) {return bitSize <= 64;}<br></span><span style="color:rgb(7,55,99)"></span></font></span><div><span style="font-family:monospace"><font size="4"><br></font></span></div><div><span style="font-family:monospace"><font size="4"><br></font></span></div><span style="font-family:monospace"><font size="4"><span style="color:rgb(7,55,99)">Table-view of the user-model knobs:<br><br>identity            ‖  (identity) |                          value                           |<br>zeroness            ‖  (no-zero)  |     (no-zero)    |                 zero                  |   <br>atomicity           ‖  (atomic)   |     (atomic)     |      (atomic)      |     tearable     |<br>nullability         ‖ <span class="gmail_default" style="color:rgb(7,55,99)"></span><span class="gmail_default" style="color:rgb(7,55,99)"> </span>(?)<span class="gmail_default" style="color:rgb(7,55,99)"></span> |  !   |  <span class="gmail_default" style="color:rgb(7,55,99)"> </span>(?)  |    !    | <span class="gmail_default" style="color:rgb(7,55,99)"> </span>(?) |      !      | <span class="gmail_default" style="color:rgb(7,55,99)"> </span>(?)<span class="gmail_default" style="color:rgb(7,55,99)"></span> |    !      |<br>==============================================================================================<br>encoding-mode       ‖  reference  |                    inline/reference                      |<br>needs reference     ‖  everywhere | shared-variables | no/shared-mutables |        no        |<br>definite-assignment ‖  no  | yes  |   no   |   yes   |  no  |     yes     | yes  |    yes    |<br>default             ‖ null | n.a. |  <span class="gmail_default" style="color:rgb(7,55,99)"></span>null  |   n.a.  | null |     n.a.    | n.a. |    n.a.   |<br>init-default        ‖    null     |       null       | null |  zero/null  | null | zero/null |</span></font></span><div class="gmail_default"><span style="font-family:monospace"><font size="4"><span style="color:rgb(7,55,99)"><br></span></font></span></div><div class="gmail_default" style="color:rgb(7,55,99)"><span style="font-family:monospace"><font size="4">Notes:<br></font></span></div><div class="gmail_default" style="color:rgb(7,55,99)"><div class="gmail_default" style="color:rgb(7,55,99)"><span style="font-family:monospace"><font size="4"> - tokens in parenthesis are the default when no knob is used<br></font></span></div><div class="gmail_default" style="color:rgb(7,55,99)"><span style="font-family:monospace"><font size="4"> - definite-assignment (§16.) means that the compiler enforces <span style="font-family:monospace"><font size="4">(to the best of its ability) </font></span>variable initialization before usage</font></span></div><div class="gmail_default" style="color:rgb(7,55,99)"><span style="font-family:monospace"><font size="4"> - default is the default-value of a variable when not definitely-assigned<br></font></span></div></div><div class="gmail_default" style="color:rgb(7,55,99)"><span style="font-family:monospace"><font size="4"> - init-default is the default-value of a variable before any initialization code runs</font></span></div><div class="gmail_default" style="color:rgb(7,55,99)"><span style="font-family:monospace"><font size="4"> - on non-nullable zero value-classes, the init-default (zero or null) <span style="font-family:monospace"><font size="4">depends on the </font></span>encoding-mode chosen by the runtime<br></font></span></div><div class="gmail_default" style="color:rgb(7,55,99)"><span style="font-family:monospace"><font size="4"> - on atomic zero value-classes, reference-encoding is needed on shared-mutables if instance bitSize cannot be written atomically<br></font></span></div><div class="gmail_default" style="color:rgb(7,55,99)"><span style="font-family:monospace"><font size="4"><br></font></span></div><div class="gmail_default" style="color:rgb(7,55,99)"><div class="gmail_default" style="color:rgb(7,55,99)"><div class="gmail_default" style="color:rgb(7,55,99)"><span style="font-family:monospace"><font size="4"><br></font></span></div><div class="gmail_default" style="color:rgb(7,55,99)"><span style="font-family:monospace"><font size="4">*** Migration of value-based classes ***<br></font></span></div><div class="gmail_default" style="color:rgb(7,55,99)"><span style="font-family:monospace"><font size="4"><span style="font-family:monospace"><font size="4"><br></font></span></font></span></div><div class="gmail_default" style="color:rgb(7,55,99)"><span style="font-family:monospace"><font size="4"><span style="font-family:monospace"><font size="4">Requiring
 definite-assignment on all non-nullable shared-mutables is 
useful to get rid of missed-initialization-bugs, so I think it's a good idea to require it wherever source-compatibility allows.</font></span></font></span><div class="gmail_default" style="color:rgb(7,55,99)"><div class="gmail_default" style="color:rgb(7,55,99)"><div class="gmail_default" style="color:rgb(7,55,99)"><span style="font-family:monospace"><font size="4">In
 this model, all value-based classes can be migrated to (atomic) zero value-classes. Due to definite-assignment, even if LocalDate is migrated to a zero 
value-class, it will be hard to get an accidental "Jan 1, 1970". 
Rational can also be a zero value-class but users will have to keep in 
mind that it's possible to get a zero-denominator Rational, even if the constructor throws when we try to build one.</font></span></div></div></div><div class="gmail_default" style="color:rgb(7,55,99)"><span style="font-family:monospace"><font size="4">To maintain source-compatibility, no migrated value-based class can be tearable, not even Double or Long, since wherever in existing code we have a field declaration such as:<br></font></span></div><span style="font-family:monospace"><font size="4"><br>    ValueBasedClass v;<br><br>v is always reference encoded and, therefore, atomic. For Double and Long, this is a bit of an anomaly, because it means that for these two primitives, and for them alone, each of these pair of field declarations will not be semantically equivalent:<br><br>long v;    // tearable <br>Long! v;   // atomic</font></span></div><div class="gmail_default" style="color:rgb(7,55,99)"><span style="font-family:monospace"><font size="4"><br></font></span></div><div class="gmail_default" style="color:rgb(7,55,99)"><span style="font-family:monospace"><font size="4">double d;  // tearable<br>Double! d; // atomic<br></font></span></div><div class="gmail_default" style="color:rgb(7,55,99)"><span style="font-family:monospace"><font size="4"><br></font></span></div><div class="gmail_default" style="color:rgb(7,55,99)"><span style="font-family:monospace"><font size="4"><br></font></span></div><div class="gmail_default" style="color:rgb(7,55,99)"><span style="font-family:monospace"><font size="4">João Mendonça<br></font></span></div></div></div></div>