Revisiting default values
Dan Smith
daniel.smith at oracle.com
Mon Jul 13 21:39:06 UTC 2020
> On Jul 13, 2020, at 12:19 PM, Dan Smith <daniel.smith at oracle.com> wrote:
>
>> On Jul 10, 2020, at 12:23 PM, Dan Smith <daniel.smith at oracle.com> wrote:
>>
>> Option G: JVM support for default instance guards
>>
>> Inline class files can indicate that their default instance is invalid. All attempts to operate on that instance (via field/method accesses, other than 'withfield') result in an exception.
>>
>> This tightens up Option F, making it just as impossible to access members of the default instance as it is to access members of 'null'.
>>
>> Same issues as Option E regarding adding a "new NPE" to the platform.
>
> There's a variant of this that deserves spelling out:
>
> ---
>
> Option J: JVM treats default instance as 'null'
>
> Like Option G, an inline class file can indicate that its default instance is invalid—in this case, 'null'. All attempts to operate on that instance result in an NPE. Conceptually, the null instance and the null reference are the same, and should generally be indistinguishable.
>
> (We explored this awhile back as a tool for migration, before going in a different direction.)
>
> Some implications:
>
> - The VM probably wants to normalize its encodings (null reference vs. null instance), meaning there's a translation layer on field/array reads, just like Option I, and also for field/array writes, just like Option D.
>
> - Casts to Q types for certain classes should also translate from null reference to null instance, rather than NPE.
>
> - For these classes, the 'withfield' instruction is uniquely able to operate on and produce 'null'.
>
> - In the language, the 'null' literal can be assigned to some inline types. (In the VM, the verifier could require using 'defaultvalue' instead, if it wants to avoid some class loading.)
>
> - We could revisit the question of whether it's possible to migrate an identity class to be an inline-default inline class as long as the default instance is 'null'. (There are additional issues, like binary compatibility. But we could we-open that exploration...)
>
> ---
>
> My sense is that Option I dominates Option J by most measures—it achieves the same result (default value is invalid), with less work at flattened storage barriers, fewer tweaks to the rest of the system, and a more useful programming model (no nulls being passed around).
And here's another option that has been previously discarded, but might be worth picking back up. This one to address Bucket #2:
---
Option K: JVM initializes fields/arrays to a designated default
The VM allows inline classes to designate a logical default instance, and during class preparation or array allocation, any fields/components of the inline type are initialized to the logical default.
Compare to Option D. Rather than adding barriers to reads/writes that interact with the storage, we simply initialize the storage "properly" in the first place.
The possibly-fatal downside is that it means every array allocation for that inline type has to stamp out a bunch of copies of a particular bit pattern, rather than the simpler all-zeros pattern. But that extra cost may be worth it in exchange for faster reads/writes to the array. (Same comments for class instances, although I don't think it's as much of a concern, given the relatively small sizes of class instances.)
Note that some arrays *already* have to stamp out a nonzero bit pattern, if the encoding of an inline type uses pointers rather than flattened fields (e.g., for an inline class with too many fields).
---
If we're enthusiastic about addressing Bucket #2, this seems like a viable approach—quite simple, and with comparable performance to most of the other approaches.
More information about the valhalla-spec-observers
mailing list