Value types support for legacy java

Project Valhalla, an experimental OpenJDK project to develop new features for java platform, has l-world value types as one of its subprojects. These value types are in beta as of now and will only be available for newer java versions once they’re ready. In this article, I’ll talk about a fully backward compatible approach to introducing value types in java language.

Let’s look at this example:

This is how we’ll use this class:

This class introduces a type Point which is basically a pair of read-only values, so it behaves as a value type. But because of the way JVM handles objects, new instances of Point class will always be allocated on the heap, even though it’s better to pass these objects by value (it’s just a pair of primitives). We could, in theory, manually handle the point objects as a pair of doubles, but that’s just not a feasible option, it would require a lot of boilerplate:

The reason this version is worse is that it pushes the implementation details of Point out of the Point class.

Is there anything we can do about that?

It turns out that yes, we can. JVM executes a tamed version of assembly called Java bytecode. And it turns out that there are tools we can use to manipulate that bytecode, namely ASM and BCEL. I’m working on a tool which will take a directory containing javac output as input, and transform those classfiles from the first version (shown above) to the second version. This article will lay out the specifications of the transformations that tool will perform:

Identifying value types:

We’ll introduce an annotation @ValueType. Users will mark classes to be processed as value type with it. These classes must be public final, should have java.lang.Object as their super type and should only contain public final fields.

Methods of value types:

Every method of a value type will be transformed into similar static methods which take the fields of value type as input. References to fields will have to be mapped to references to arguments (which are basically local variables).

Methods which take value types as argument:

Same as previous transformation.

Local Variables:

Every local variable which will store a value type will be transformed to a collection of local variables denoting fields of that object. We’ll have to transform GETFIELD operations on those variables to the corresponding GETLOCAL operation.

[Multidimentional] Arrays:

Same as local variables, they’ll be transformed to a collection of [multidimentional] arrays denoting fields of that object.

Methods Returning Value Types:

This one is a bit tricky. The method I intend to use is this:

(Note: I’m using Point class as an example)

  1. Introduce an inner class Point.Buffer which contains the fields of original Point class as it’s fields.
  2. Method’s supposed to return a  Point will be changed to return void, and they will store the return value in a  Point.Buffer instance passed to them as an argument.
  3. The caller will read the return value from Point.Buffer instance.

I know there’s a lot of copy going on in there. We’ll have to see how does this cost fares against the cost of millions of Point objects being created and garbage collected every second (as is possible for game engines). Let me know if there’s a better way.

Nested Value Types:

We can support nested value types, as long as a graph describing A contains B relationship between value types A and B is acyclic.

Does it work?

I made a test which does heavy computation on both versions of Point class (the value type version generated manually) and compares the time they took. The value-type version was over 6 times faster, even though it used methods returning Point a lot, which are the most inefficient part of our model.

I had to revise the test a couple of times because the JVM is very good at optimizing the code. Method inlining done by the JIT compiler renders the value types useless if the objects of that type are short lived. But JIT compiler can’t do much if that’s not the case, as shown by the results of test.

The value type post processor is being developed here

 See you later.

Leave a Reply

Your email address will not be published. Required fields are marked *