Yes, it will allow a few key things:
Passing composite values around on the stack, so method params and returns don’t have to box our friendly little Point
class anymore.
Composite types can be inlined inside arrays, so we can avoid boxing there too. And nested valhalla types can be fully inlined in the object, and arrays too, e.g the equivalent of
data class Complex(r: Float, c: Float)
data class ComplexLineSegment(start: Complex, end: Complex)
ComplexLineSegment would be representable as four consecutive Float values on the stack, or in an array.
I’m not sure the array format is even forced to be ‘row-major’ (yet?). Its plausable that the JVM could columnarize – (e.g. every 8 Complex items could plausibly be written in memory as r,r,r,r,r,r,r,r,c,c,c,c,c,c,c,c
instead of r,c,r,c,r,c,r,c,r,c,r,c,r,c,r,c
).
A quick summary for today would be the top of this page: https://wiki.openjdk.java.net/display/valhalla/L-World+Value+Types
Value Types are small, immutable, identity-less types
User model: "codes like a class, works like an int"
Use cases: Numerics, algebraic data types, tuples, cursors, ...
Removing identity commitment enables optimizations such as
flattening of value types in containers such as fields or arrays
reducing cost of indirection and locality of reference with attendant cache miss penalties
reducing memory footprint and load on garbage collectors
Combining Immutability and no identity commitment allows value types to be stored in registers or stack or passed by value
The “L-world” change from the first prototype is summarized there in more detail. An even briefer summary:
“Q-world”, the old prototype, introduced a bunch of new bytecode instructions to distinguish value types from object/reference types, and a new class descriptor format for them. This led to lots of issues.
“L-world” makes everythig an object again – at least as far as bytecode for method signatures is concerned. The object descriptors are re-purposed to additionally cover the new value classes, by adding extra info to the object class descriptor. Then it is up to the JVM to optimize the call sites and optimize away boxing. Now only two new bytecode instructions are added: one to create a default instance (every value type has to have a default, last I checked this is just all zeroes in memory so that empty arrays are as if filled with default values), and one to copy a value but change one field for copy-on-write semantics.
EDIT:
Another thing to note is that because these are meant to be substitutable when the values are the same, equals() on a value type when the value type contains a reference, implies reference equality on the inner reference (following through to a reference’s equals() method can break the contract otherwise). There has been some debate about this, however.
This is one place where scala case classes as they are today would be a mismatch.