points by kuhsaft 2 days ago

> Now, one can argue that this is just smoke and mirrors with type erasure and it is but you can already put a Date into a List<Point> if you're so inclined because the JVM doesn't know the difference, hence type erasure.

And that's a massive problem that they're planing to solve with specialized generics.

> If I read the correctly, it means that if you have a Point value class then on the JVM level you'll be able to stuff any value class into there if you're so incline, just like with List<Point>.

I'm not sure what you mean. An L-type is an object reference. E.g. Ljava/lang/String, Lcom/org/CustomObject. The issue you're conflating is the erasure of List<T> to List<Object> and it's L-type Ljava/util/List.

> I prefer the Hack version

Hack/HHVM didn't have to worry about backwards compatibility.

---

The blog post does a pretty high level overview of the implementation, but my understanding of it is the following:

1. They are adding a new bytecode class flag for value classes. Bytecode descriptor for value classes are exactly the same (L-type).

2. Primitive wrapper classes will become value classes.

The difference from the CLR is that the JVM implementation is backward compatible with linked legacy bytecode. As they can accept a value class instance into their methods due to the same L-type. It's just additional metadata added to allow the JVM to stack allocate the class.

---

Separately, to handle generics:

1. Parameterized container classes will be flagged with a new bytecode to enable parametric attributes on initialization with the additional data of the parameters in the Constant Pool. Bytecode descriptor for classes are exactly the same with type-erasure, e.g. List<SomeType> erased to Ljava/util/List.

2. Initialization of parameterized classes are done with the additional metadata of the type argument stored in the Constant Pool.

3. The runtime does monomorphization of the parameterized class.

It doesn't seem too different to what the CLR does, i.e. runtime monomorphization. The difference is the JVM implementation is backward compatible with older type-erased code, i.e. the restrictions in Java due to type-erasure are exactly the same as before and the L-types don't change. It's just additional metadata added to allow the JVM to monomorphize the classes for performance.

---

In summary, value objects and specialized generics are backwards compatible with legacy bytecode. The JVM handles the compatibility. Of course, the newer bytecode is not forward compatible with older JVMs.