[lworld] RFR: 8352647: [lworld] Remove larval InlineTypeNode in Unsafe intrinsics
Jatin Bhateja
jbhateja at openjdk.org
Sat Mar 29 08:22:45 UTC 2025
On Fri, 28 Mar 2025 19:18:26 GMT, Jatin Bhateja <jbhateja at openjdk.org> wrote:
>> Hi @merykitty ,
>> For attached test case I am seeing crash at state merge point b/w larval and non-larval value
>>
>> [unsafe_access.txt](https://github.com/user-attachments/files/19501609/unsafe_access.txt)
>>
>>
>> CPROMPT>javac --enable-preview -source 25 --add-exports=java.base/jdk.internal.misc=ALL-UNNAMED unsafe_access.java
>> Note: unsafe_access.java uses preview features of Java SE 25.
>> Note: Recompile with -Xlint:preview for details.
>> CPROMPT>
>> CPROMPT>java -XX:-PauseAtStartup --enable-preview --add-exports=java.base/jdk.internal.misc=ALL-UNNAMED -cp . unsafe_access
>> #
>> # A fatal error has been detected by the Java Runtime Environment:
>> #
>> # Internal Error (/home/jatinbha/sandboxes/lworld/src/hotspot/share/opto/parse1.cpp:1790), pid=2453805, tid=2453825
>> # assert(gvn().type(n)->is_zero_type()) failed: Should have been scalarized
>> #
>> # JRE version: OpenJDK Runtime Environment (25.0) (slowdebug build 25-internal-adhoc.root.lworld)
>> # Java VM: OpenJDK 64-Bit Server VM (slowdebug 25-internal-adhoc.root.lworld, mixed mode, sharing, tiered, compressed oops, compressed class ptrs, g1 gc, linux-amd64)
>> # Problematic frame:
>> # V [libjvm.so+0x178efa5] Parse::merge_common(Parse::Block*, int)+0x49f
>> #
>> # Core dump will be written. Default location: Core dumps may be processed with "/usr/share/apport/apport -p%p -s%s -c%c -d%d -P%P -u%u -g%g -- %E" (or dumping to /home/jatinbha/code/java/valhalla/core.2453805)
>> #
>> # An error report file with more information is saved as:
>> # /home/jatinbha/code/java/valhalla/hs_err_pid2453805.log
>> 10001399990
>> #
>> # Compiler replay data is saved as:
>> # /home/jatinbha/code/java/valhalla/replay_pid2453805.log
>> #
>> # If you would like to submit a bug report, please visit:
>> # https://bugreport.java.com/bugreport/crash.jsp
>> #
>> Aborted (core dumped)
>
>> @jatin-bhateja Merging a larval object and a non-larval object is undefined behaviour, and crashing should be an acceptable outcome then. There are issues with merges of larval objects, though, for example:
>>
>> ```
>> MyValue v = UNSAFE.makePrivateBuffer(v0);
>> for (int i = 0; i < 100; i++) {}
>> return UNSAFE.finishPrivateBuffer(v);
>> ```
>>
>> But generally, the situation of merging larval objects are messy not just with larval objects created by `Unsafe` and I want to defer the fix to after #1405.
>
> Thanks, @merykitty. I think MEET over larval and non-larval should result in a larval value, so InlineTypeNode, which is the other input of the Phi node, should be buffered and treated as a larval object too, until we hit upon a finishPrivate buffer call that brings this merged oop value out of the larval state and re-materialize an InlineTypeNode.
>
> Kindly include this test with this patch. for now, we can add it to ProblemList.txt, which can be enabled after #1405 .
> @jatin-bhateja A larval object created by `Unsafe` should adhere to all the rules that are put on a larval object created by the `new` bytecode. In the type verification system, each larval object has a distinct type being either `uninitializedThis` or `uninitialized(Offset)`. Meeting of a larval object with another larval object or with a non-larval object, thus, will result in a non-typed `reference`. As a result, the program is ill-formed if the merge is used. Please refer to [the JVMS, section 4.10.1](https://docs.oracle.com/javase/specs/jvms/se21/html/jvms-4.html#jvms-4.10.1).
Hi @merykitty ,
Larval transitions are either implicit, i.e. when a new value type instance is created, it begins in larval state and then post initilization transition out of larval state. The second kind of larval transition is explicit when we use UNSAFE APIs.
While an object is in the larval state, it should not exist in scalarized form, thus, a larval object should be buffered; it still is a legitimate value instance, but because it is assigned a buffer location, we can say for now it has a pseudo-identity. The compiler cannot directly forward the field initialization of larvals to its user; a read of a field value of a larval object is similar to getfield, i.e., the compiler needs to explicitly load the field value at the corresponding field offset from the base.
Given these semantics, a MEET b/w a larval and non-larval value should result in a laval value when mering the states of two basic blocks. I don't fully follow your comment on non-typed reference, as larval and non-larval instances are of value type.
Your approach to buffer the value type instance within the makePrivate buffer looks correct to me. Please include the test case that I shared with the patch and add it to ProblemList.txt for now.
-------------
PR Comment: https://git.openjdk.org/valhalla/pull/1406#issuecomment-2763228402
More information about the valhalla-dev
mailing list