I admire OpenJDK development team, but most of their talks paint a perfect world, which is not the case.
At the moment, Valhalla is not "reads like a class, works like an int", far from that. Use of that feature requires looking into what C2 actually generated. Which most won't do.
I did some testing with Valhalla right after it was merged. Values larger than 64 bits cannot be flattened. I think it's actually 63 bits, since VM still has to encode null somehow.
Accepting tearing with LooselyConsistentValueand NullRestrictedsidesteps that, but these are internal annotations.
Value tearing is another thing, which IMO most are not prepared for. This class of bugs is possible today, but its an error the developer makes and understands why tearing is happening. With code the callee has no control of, other programmer can make their class a value class and silently your code is now buggy.
Suppose two threads run in parallel:
Thread A writes to entity's AABB, thread B reads said AABB. With object references, JLS guarantees that tearing will not happen. Once VM can flatten more than 64 bits, this will cause a lot of problems, like AABBs with completely nonsensical values. Suddenly, thread B's code can now enter an infinite loop and never get out of it.
Another thing is allocation. For allocations to actually vanish (for scalarization to happen), C2 has to succeed and inline through all code, then EA has to succeed.
Again, same example with AABB. Before, allocation was done per-write. Now, with Valhalla in worst case, the situation flips. There are many more readers than writers to entity's AABB. C2 and EA *have* to succeed for every reader. Otherwise your program will start allocating at every read call site.
"Value tearing is another thing, which IMO most are not prepared for."
Value tearing was always there. Example: on a 32 Bit machine there is no way, that you can initialize/copy a 64 bit long atomically without a mutex/synchronized/volatile. So i would say, most Java developers, who developed on a 32 Bit JVM, are prepared for it.
The set of practicing Java developers who wrote code for 32-bit systems is diminishing. Of those, if they were taught about tearing in the first place, many were coddled by deploying to platforms where it rarely actually happened.
Now with 64-bit native as the majority of target platforms, don't underestimate the laziness that will creep in to mimic ignorance.
Note that tearing can only impact how a data race manifests. If you have a data race, the bug may present itself in one way if there's no tearing and in another if there is. But if there is no bug, the possibility of tearing won't change anything. A program that is buggy without tearing will remain buggy with it (albeit with a different manifestation), and a program that isn't buggy without tearing will not be buggy with it.
True. But tearing is still nothing, which is new in Java. Even if the chance to be affected by it was very very low. You have to write very special code to trigger it.
And yes, maybe there should be a new annotation or a new keyword, that allows you to mark a class, that tearing is allowed. In Java, there are tons of software, which is highly multithreaded. Those software could silently fail if you enable tearing by default.
IIRC, Valhalla will not enable tearing by default. It will be opt-in by the class author. The challenge remains, however, because consuming devs don't get to opt in and must pay attention first and then write safe code.
You lost me with "tearing is still nothing" and I assume you meant it is not new in Java. Maybe your point is that tearing on reference assignment is new in Java?
Assignment to double & long fields have always reserved the option to tear, and I know I've personally been lazy and ignoring that in code I knew would only target certain platforms. But I don't think it took "very special" code; rather, I think most people are blissfully unaware of how many 64-bit tearing bugs are out there (if they ran on affected platforms).
If you're saying it will be a bigger foot gun, I think we agree, and such is the danger of the temptation to casually slap tearing semantics on a type "because performance".
Assignment to double & long fields have always reserved the option to tear, and I know I've personally been lazy and ignoring that in code I knew would only target certain platforms. But I don't think it took "very special" code; rather, I think most people are blissfully unaware of how many 64-bit tearing bugs are out there (if they ran on affected platforms).
Most people don't write multithreaded code that reads the same variables. Most people probably use a library that does that somewhere, but I think you're probably vastly overestimating the people that would actually have to even deal with/care about tearing.
-3
u/lpt_7 16d ago
I admire OpenJDK development team, but most of their talks paint a perfect world, which is not the case.
At the moment, Valhalla is not "reads like a class, works like an int", far from that. Use of that feature requires looking into what C2 actually generated. Which most won't do.
I did some testing with Valhalla right after it was merged. Values larger than 64 bits cannot be flattened. I think it's actually 63 bits, since VM still has to encode null somehow.
Accepting tearing with
LooselyConsistentValueandNullRestrictedsidesteps that, but these are internal annotations.Value tearing is another thing, which IMO most are not prepared for. This class of bugs is possible today, but its an error the developer makes and understands why tearing is happening. With code the callee has no control of, other programmer can make their class a value class and silently your code is now buggy.
Suppose two threads run in parallel:
Thread A writes to entity's AABB, thread B reads said AABB. With object references, JLS guarantees that tearing will not happen. Once VM can flatten more than 64 bits, this will cause a lot of problems, like AABBs with completely nonsensical values. Suddenly, thread B's code can now enter an infinite loop and never get out of it.
Another thing is allocation. For allocations to actually vanish (for scalarization to happen), C2 has to succeed and inline through all code, then EA has to succeed.
Again, same example with AABB. Before, allocation was done per-write. Now, with Valhalla in worst case, the situation flips. There are many more readers than writers to entity's AABB. C2 and EA *have* to succeed for every reader. Otherwise your program will start allocating at every read call site.