Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8235370

[valhalla] storage class wrapper types


    • Type: Enhancement
    • Status: Open
    • Priority: P4
    • Resolution: Unresolved
    • Affects Version/s: repo-valhalla
    • Fix Version/s: repo-valhalla
    • Component/s: hotspot
    • Labels:


      Storage class wrapper types in the VM

      Variables in the JVM heap come in a variety of _storage classes_, starting with the basic set of field modifiers: regular mutable (the default), `final`, and `volatile`. Array elements are also variables in the JVM heap, but can only be regular mutable.

      In addition, there are a number of de facto specialized storage classes defined by various portions of the JVM and core libraries, using either hardwired inheritable "magic" fields, or else "magic" annotations.

      A list of these storage classes might go as follows:

      1. _regular mutable_ (default): Modifiable and efficient. Subject to tearing and races.

      2. _final_ (modifier): Non-modifiable. Safe publication from constructors.

      3. _volatile_ (modifier): Modifiable. Serializing access across threads. Atomic.

      4. _atomic_ (proposed inline class feature): Modifiable. Not subject to tearing, like _volatile_. But not necessarily serialized.

      5. _stable_ (`@Stable` annotation): Modifiable once, constant foldable after overwrite of default.

      6. _hyper-aligned_ (see JDK-8234886): Layout padded to align to a boundary of 128, 256, or 512 bits.

      7. _contended_ (`@Contended` annotation): Layout padded to reduce false sharing in memory caches.

      8. _weak_ (magic field): A weak reference; can be reset to `null` in certain circumstances. (Also, _soft_ and _phantom_ references.)

      9. _not-inline_ (internal JVM behavior): The JVM allocates a hidden indirection for this variable of an inline type, rather than spreading its fields directly.

      10. _force-inline_ (internal JVM behavior): The JVM spreads the fields of this variable of an inline type, rather than allocating a hidden indirection.

      > Comments

      > An object field marked `@Contended` is endowed with internal layout adjustments intended to reduce false sharing in memory caches. Roughly speaking, it is given enough padding before and after to place it alone on a cache line. (There is also a way to group several such variables.)

      > If and when JDK-8234886 is implemented, it will also be possible to speak of variables which are _hyper-aligned_ at particular offsets within their cache lines (or multiple or sub-multiples of cache lines). Such variables can be used with hardware features that impose alignment constraints that are stronger than the 64-bit alignment typically required of long and double variables.

      > The particular field `java.lang.ref.Reference.value` is specially processed by the garbage collector as a soft, weak, or phantom reference.

      These storage classes are properties of variables, not values. They apply more or less uniformly regardless of the _type_ of the variable. There are probably more concents in this vein. Clearly some are in appropriate for the general user; some have only special and narrow use cases.

      This note proposes a convention for expressing such storage classes by means of a package of "magic" inline types, each of which embodies some particular storage class, and stores a value using the rules of that class.

      These inline types would be specially recognized by the JVM, analogously to today's special recognition of the `ACC_FINAL` and `ACC_VOLATILE` modifier bits, the `Reference.value` field, and the `@Contended` annotation.

      Here are examples of inline classes which might confer the effects of the
      `volatile` keyword, the `@Contended` annotation, and the `@Stable` annotation:

      public inline class VolatileReference {
        public final Object value; // JVM magic: always accessed as volatile
        VolatileReference(Object value) { this.value = value; }
      public inline class ContendedReference {
        public final Object value; // JVM magic: always laid out as @Contended
        ContendedReference(Object value) { this.value = value; }
      public inline class StableReference {
        public final Object value; // JVM magic: always treated as @Stable
        StableReference(Object value) { this.value = value; }
      public inline class WeakReference {
        public final Object value; // JVM magic: scanned as a weak reference, nullable by GC
        WeakReference(Object value) { this.value = value; }

      It seems likely that similar inline definitions can be made for the other storage classes. Each one would be linked as a "magic type" to the JVM, just as today's types in `java.lang.ref` are magic, and the annotation `@Contended` is magic.

      As JVM primitives they can be defined in an internal module and package such as `jdk.internal.variable`, and can be selectively surfaced in a `java.base` package such as `java.lang.variable`.

      The sketch above shows only storage class wrappers of type `Object`. Other types can be generated by copy-editing, or else a generic type could be defined using specialized templates:

      public inline template class Volatile<any T> {
        public final T value; // JVM magic: always accessed as volatile
        Volatile(T value) { this.value = value; }

      Although inline type fields are always `final`, these wrapper types can easily embody non-final variables of the various storage classes. The essential principle to note is that the value _as a whole_ is mutable (if the enclosing variable is non-`final`), and so while the `value` field of the wrapper is not directly settable, the wrapper can be replaced at any time with a new wrapper value of the same type, and a different `value` field.

      For weak references, this means that the JVM would replace the wrapper as a whole with a null-carrying instance of the wrapper, when the GC chooses to clear the variable. The special queueing behavior for weak references might not seem to apply here, unless a two-component value type is defined.

      The storage class _final_ probably does not warrant reification as a storage class wrapper, since mutability is controlled by the presence or absence of the `final` modifier of the declaration which would use the wrapper type. This objection appears to be unique to the _final_ storage class, while the other storage classes would appear to be expressible using this wrapper pattern.

      Note that arrays of wrapper storage classes would endow their elements with the indicated storage class. This can give us volatile arrays, stable arrays, and so forth, in a regular manner. Again, this pattern fails to apply to a long-standing need for non-modifiable arrays with `final` elements. Such arrays must be the subject of a different RFE.

      The _regular mutable_ storage class might not seem to need reification in a storage class wrapper, but there might be some use for such a wrapper in context, such as inline classes, where the default is _not_ regular mutable variables, but instead of _final_ variables.

      public inline template class Mutable<any T> {
        public final T value; // JVM magic: piecemeal write access allowed via VHs
        Mutable(T value) { this.value = value; }

      In a case like this, an inline class `X` using the `NonFinal` wrapper on one or all of its fields `X.f` would advertise that frameworks (like Panama) which provide access paths to mutate components of flat structures are allowed to make independent modifications to the field. In essence, such a modification is equivalent to (but more efficient and race-free than) loading the whole `X` value, constructing a copy with a new `X.f` value, and storing it back.




            • Assignee:
              jrose John Rose
            • Votes:
              0 Vote for this issue
              2 Start watching this issue


              • Created: