Skip to content

8335256: [lworld] C2: Remove larval InlineTypeNode #1447

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: lworld
Choose a base branch
from

Conversation

merykitty
Copy link
Member

@merykitty merykitty commented Apr 27, 2025

Hi

The root issue is that a larval value object is fundamentally different from a non-larval one. The most important thing is that it has a unique identity and it expects any modification on 1 reference observable by all other equivalent references. As a result, we need a mechanism to track the identity of a larval object, which InlineTypeNode does not provide. My current proposal to fix this issue is to abandon larval InlineTypeNodes and use the oop like other objects.

It is probably beneficial to have another mechanism to make it easier optimizing larval inline type nodes, but I think it can be a follow-up RFE.

An example regarding the issue with tracking the identity of a larval InlineTypeNode:

Consider this pseudobytecode sequence:

new MyValue;
dup;
loop;
invokespecial MyValue::<init>;
areturn;

There are 2 equivalent references in the stack at the loop entry. When Parse::merge encounters them, it cannot know that these are the same because the back-edge has not been processed yet. As a result, it creates 2 separate Phis for these references. Then, invokespecial will only make the top of the stack a non-larval object, not the next one, which is the one returned to the caller. As a result, we fail with assert(!value->is_InlineType() || !value->as_InlineType()->is_larval(), "returning a larval"). Worse, if the method is osr-compiled at the loop head, we have 2 separate references fed into the compiled function and there is no way we may know that they are of the same object.

Please take a look and leave your reviews, thanks a lot.


Progress

  • Change must not contain extraneous whitespace

Issues

  • JDK-8335256: [lworld] C2: Remove larval InlineTypeNode (Bug - P3)
  • JDK-8325627: [lworld] C2 compilation bailout for TestNullableInlineTypes::test85 (Bug - P4)
  • JDK-8354283: [lworld] TestAllocationMergeAndFolding fails since jdk-25+16, since an allocation is detected (Bug - P4)

Reviewing

Using git

Checkout this PR locally:
$ git fetch https://git.openjdk.org/valhalla.git pull/1447/head:pull/1447
$ git checkout pull/1447

Update a local copy of the PR:
$ git checkout pull/1447
$ git pull https://git.openjdk.org/valhalla.git pull/1447/head

Using Skara CLI tools

Checkout this PR locally:
$ git pr checkout 1447

View PR using the GUI difftool:
$ git pr show -t 1447

Using diff file

Download this PR as a diff file:
https://git.openjdk.org/valhalla/pull/1447.diff

Using Webrev

Link to Webrev Comment

@merykitty
Copy link
Member Author

/issue 8325627
/issue 8354283

@bridgekeeper
Copy link

bridgekeeper bot commented Apr 27, 2025

👋 Welcome back qamai! A progress list of the required criteria for merging this PR into lworld will be added to the body of your pull request. There are additional pull request commands available for use with this pull request.

@openjdk
Copy link

openjdk bot commented Apr 27, 2025

@merykitty This change now passes all automated pre-integration checks.

ℹ️ This project also has non-automated pre-integration requirements. Please see the file CONTRIBUTING.md for details.

After integration, the commit message for the final commit will be:

8335256: [lworld] C2: Remove larval InlineTypeNode
8325627: [lworld] C2 compilation bailout for TestNullableInlineTypes::test85
8354283: [lworld] TestAllocationMergeAndFolding fails since jdk-25+16, since an allocation is detected

You can use pull request commands such as /summary, /contributor and /issue to adjust it as needed.

At the time when this comment was updated there had been no new commits pushed to the lworld branch. If another commit should be pushed before you perform the /integrate command, your PR will be automatically rebased. If you prefer to avoid any potential automatic rebasing, please check the documentation for the /integrate command for further details.

As you do not have Committer status in this project an existing Committer must agree to sponsor your change.

➡️ To flag this PR as ready for integration with the above commit message, type /integrate in a new comment. (Afterwards, your sponsor types /sponsor in a new comment to perform the integration).

@openjdk
Copy link

openjdk bot commented Apr 27, 2025

@merykitty
Adding additional issue to issue list: 8325627: [lworld] C2 compilation bailout for TestNullableInlineTypes::test85.

@openjdk
Copy link

openjdk bot commented Apr 27, 2025

@merykitty
Adding additional issue to issue list: 8354283: [lworld] TestAllocationMergeAndFolding fails since jdk-25+16, since an allocation is detected.

@mlbridge
Copy link

mlbridge bot commented Apr 27, 2025

Webrevs

@TobiHartmann
Copy link
Member

Great work @merykitty! Thanks a lot for the investigation. When working on the new value object construction model, I was concerned that we might end up with adding identity back to the larvals but I was still naively hoping that we could get around that. Looks like we can't. Maybe you could change the title to something more descriptive for future reference / search.

I run this through testing and there are a few issues:

applications/ctw/modules/jdk_internal_le.java
-ea -esa -XX:CompileThreshold=100 -XX:+UnlockExperimentalVMOptions -server -XX:-TieredCompilation

# A fatal error has been detected by the Java Runtime Environment:
#
#  Internal Error (/workspace/open/src/hotspot/share/opto/macro.cpp:2970), pid=1140043, tid=1140412
#  assert(!n->as_AbstractLock()->is_eliminated()) failed: sanity
#
# JRE version: Java(TM) SE Runtime Environment (25.0) (fastdebug build 25-lworld5ea-LTS-2025-04-28-0856180.tobias.hartmann.valhalla2)
# Java VM: Java HotSpot(TM) 64-Bit Server VM (fastdebug 25-lworld5ea-LTS-2025-04-28-0856180.tobias.hartmann.valhalla2, mixed mode, sharing, compressed oops, compressed class ptrs, g1 gc, linux-amd64)
# Problematic frame:
# V  [libjvm.so+0x15359a4]  PhaseMacroExpand::eliminate_macro_nodes()+0x714

Current CompileTask:
C2:26441 3356   !b        jdk.internal.org.jline.utils.NonBlockingInputStreamImpl::run (312 bytes)

Stack: [0x00007f27dbbfd000,0x00007f27dbcfd000],  sp=0x00007f27dbcf8250,  free space=1004k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
V  [libjvm.so+0x15359a4]  PhaseMacroExpand::eliminate_macro_nodes()+0x714  (macro.cpp:2970)
V  [libjvm.so+0xb26617]  Compile::Optimize()+0x1867  (compile.cpp:2903)
V  [libjvm.so+0xb28ceb]  Compile::Compile(ciEnv*, ciMethod*, int, Options, DirectiveSet*)+0x1feb  (compile.cpp:874)
V  [libjvm.so+0x94e98d]  C2Compiler::compile_method(ciEnv*, ciMethod*, int, bool, DirectiveSet*)+0x46d  (c2compiler.cpp:142)
V  [libjvm.so+0xb379f2]  CompileBroker::invoke_compiler_on_method(CompileTask*)+0xb22  (compileBroker.cpp:2307)
V  [libjvm.so+0xb389f8]  CompileBroker::compiler_thread_loop()+0x588  (compileBroker.cpp:1951)
V  [libjvm.so+0x109191f]  JavaThread::thread_main_inner()+0x12f  (javaThread.cpp:773)
V  [libjvm.so+0x1abf606]  Thread::call_run()+0xb6  (thread.cpp:231)
V  [libjvm.so+0x17466d8]  thread_native_entry(Thread*)+0x128  (os_linux.cpp:877)
compiler/valhalla/inlinetypes/TestValueClasses.java
-DWarmup=0 -DVerifyIR=false 
OR
-Xcomp -XX:-TieredCompilation -DIgnoreCompilerControls=true

Caused by: java.lang.RuntimeException: assertEquals expected: compiler.valhalla.inlinetypes.TestValueClasses$SmallNullable1@b0186fd4 but was: compiler.valhalla.inlinetypes.TestValueClasses$SmallNullable1@6279ef0a
	at jdk.test.lib.Asserts.fail(Asserts.java:715)
	at jdk.test.lib.Asserts.assertEquals(Asserts.java:208)
	at jdk.test.lib.Asserts.assertEquals(Asserts.java:195)
	at jdk.test.lib.Asserts.assertEQ(Asserts.java:172)
	at compiler.valhalla.inlinetypes.TestValueClasses.test9_verifier(TestValueClasses.java:434)
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
	... 7 more
compiler/valhalla/inlinetypes/TestValueConstruction.java
-XX:+UnlockDiagnosticVMOptions -XX:+AbortVMOnCompilationFailure

This is expected but to be able to run this test with `-XX:+AbortVMOnCompilationFailure`, which is valuable, maybe we should put your new test in another jtreg test and hardcode `-XX:-AbortVMOnCompilationFailure` there?

# A fatal error has been detected by the Java Runtime Environment:
#
#  Internal Error (workspace/open/src/hotspot/share/compiler/compileBroker.cpp:2114), pid=2843210, tid=2843229
#  fatal error: Not compilable at tier 4: OSR starts with non-empty stack
#
# JRE version: Java(TM) SE Runtime Environment (25.0) (fastdebug build 25-lworld5ea-LTS-2025-04-28-0856180.tobias.hartmann.valhalla2)
# Java VM: Java HotSpot(TM) 64-Bit Server VM (fastdebug 25-lworld5ea-LTS-2025-04-28-0856180.tobias.hartmann.valhalla2, mixed mode, sharing, tiered, compressed oops, compressed class ptrs, g1 gc, linux-amd64)
# Problematic frame:
# V  [libjvm.so+0xb30beb]  CompileBroker::handle_compile_error(CompilerThread*, CompileTask*, ciEnv*, int, char const*)+0x6b

Current CompileTask:
C2:6345 1087 %  b  4       compiler.valhalla.inlinetypes.TestValueConstruction$Code_0::multipleOccurrencesInJVMSReturnStack @ 5 (22 bytes)

Stack: [0x00007fc85457f000,0x00007fc85467f000],  sp=0x00007fc85467d450,  free space=1017k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
V  [libjvm.so+0xb30beb]  CompileBroker::handle_compile_error(CompilerThread*, CompileTask*, ciEnv*, int, char const*)+0x6b  (compileBroker.cpp:2114)
V  [libjvm.so+0xb3734c]  CompileBroker::invoke_compiler_on_method(CompileTask*)+0x47c  (compileBroker.cpp:2340)
V  [libjvm.so+0xb389f8]  CompileBroker::compiler_thread_loop()+0x588  (compileBroker.cpp:1951)
V  [libjvm.so+0x109191f]  JavaThread::thread_main_inner()+0x12f  (javaThread.cpp:773)
V  [libjvm.so+0x1abf606]  Thread::call_run()+0xb6  (thread.cpp:231)
V  [libjvm.so+0x17466d8]  thread_native_entry(Thread*)+0x128  (os_linux.cpp:877)
compiler/valhalla/inlinetypes/TestValueConstruction.java

Various flags:
- No flags
- "-XX:+UnlockDiagnosticVMOptions -XX:-TieredCompilation -XX:+StressArrayCopyMacroNode -XX:+StressCallingConvention -XX:+StressLCM -XX:+StressGCM -XX:+StressCCP -XX:+StressIGVN -XX:+StressReflectiveCode -XX:+StressMethodHandleLinkerInlining -XX:+StressCompiledExceptionHandlers -XX:MaxNodeLimit=100000"

java.lang.RuntimeException: assertEquals expected: x: 0 but was: x: 50000
	at jdk.test.lib.Asserts.fail(Asserts.java:715)
	at jdk.test.lib.Asserts.assertEquals(Asserts.java:208)
	at jdk.test.lib.Asserts.assertEquals(Asserts.java:195)
	at jdk.test.lib.Asserts.assertEQ(Asserts.java:172)
	at compiler.valhalla.inlinetypes.TestValueConstruction.check(TestValueConstruction.java:1851)
	at compiler.valhalla.inlinetypes.TestValueConstruction.run(TestValueConstruction.java:1846)
	at compiler.valhalla.inlinetypes.TestValueConstruction.main(TestValueConstruction.java:1773)
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
	at java.base/java.lang.reflect.Method.invoke(Method.java:565)
	at com.sun.javatest.regtest.agent.MainWrapper$MainTask.run(MainWrapper.java:138)
	at java.base/java.lang.Thread.run(Thread.java:1447)

@merykitty
Copy link
Member Author

@TobiHartmann Thanks a lot for the comprehensive testing, it is really helpful.

applications/ctw/modules/jdk_internal_le.java
-ea -esa -XX:CompileThreshold=100 -XX:+UnlockExperimentalVMOptions -server -XX:-TieredCompilation

This one fails because after removal of some allocations, not only other allocations become eligible for elimination, locks can also be eliminated. As a result, we need to do the whole macro elimination again. I noticed that _has_lock is unused, which makes it trivial to merge the 2 loops, simplify the implementation there.

compiler/valhalla/inlinetypes/TestValueClasses.java
-DWarmup=0 -DVerifyIR=false
OR
-Xcomp -XX:-TieredCompilation -DIgnoreCompilerControls=true

This one is an oversight by me. When exiting a constructor, the larval oop is aggressively replaced by the non-larval one in all the frames. This relies on the assumption that all blocks in which the oop is larval has been processed. This is incorrect when we have uncommon traps, which can be processed at any time. As a result, we can only replace the larval oop with the non-larval one in the current frame.

compiler/valhalla/inlinetypes/TestValueConstruction.java
-XX:+UnlockDiagnosticVMOptions -XX:+AbortVMOnCompilationFailure

I modified the test to push everything into the local slots, 2 distinct slots are present into the loop, keep the original intention of the test.

compiler/valhalla/inlinetypes/TestValueConstruction.java
Various flags:

  • No flags
  • "-XX:+UnlockDiagnosticVMOptions -XX:-TieredCompilation

This is interesting. This is an oversight from #1424. The issue is that it is hard to decide that 2 nodes are definitely different or definitely the same, especially when the graph may be non-canonical during IGVN. As a result, I resort to a more conservative approach there:

  • Give up finding a matching constructor for a local allocation.
  • When deciding if a call can modify a field of a local allocation, don't take into account the receiver and return true for any constructor of a subclass regardless of whether the receiver is actually the object we are loading from.

@merykitty merykitty changed the title 8335256: [lworld] compiler/valhalla/inlinetypes/TestValueConstruction.java fails intermittently 8335256: [lworld] C2: Remove larval InlineTypeNode Apr 30, 2025
@TobiHartmann
Copy link
Member

Thanks for quickly fixing these issues. I ran another round of testing and there's only one issue left:

compiler/arraycopy/TestEliminatedArrayCopyPhi.java
-ea -esa -XX:CompileThreshold=100 -XX:+UnlockExperimentalVMOptions -server -XX:-TieredCompilation

# A fatal error has been detected by the Java Runtime Environment:
#
#  Internal Error (/workspace/open/src/hotspot/share/opto/phaseX.cpp:1821), pid=1040062, tid=1040080
#  Error: assert(_worklist.size() == 0) failed
#
# JRE version: Java(TM) SE Runtime Environment (25.0) (fastdebug build 25-lworld5ea-LTS-2025-04-30-0702055.tobias.hartmann.valhalla2)
# Java VM: Java HotSpot(TM) 64-Bit Server VM (fastdebug 25-lworld5ea-LTS-2025-04-30-0702055.tobias.hartmann.valhalla2, mixed mode, tiered, compressed oops, compressed class ptrs, g1 gc, linux-amd64)
# Problematic frame:
# V  [libjvm.so+0x17de609]  PhaseCCP::PhaseCCP(PhaseIterGVN*)+0x169

Current CompileTask:
C2:455  160    b  4       compiler.arraycopy.TestEliminatedArrayCopyPhi::test (27 bytes)

Stack: [0x00007fadf8385000,0x00007fadf8485000],  sp=0x00007fadf8480270,  free space=1004k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
V  [libjvm.so+0x17de609]  PhaseCCP::PhaseCCP(PhaseIterGVN*)+0x169  (phaseX.cpp:1821)
V  [libjvm.so+0xb2573a]  Compile::Optimize()+0xa0a  (compile.cpp:2950)
V  [libjvm.so+0xb28b7b]  Compile::Compile(ciEnv*, ciMethod*, int, Options, DirectiveSet*)+0x1feb  (compile.cpp:874)
V  [libjvm.so+0x94e98d]  C2Compiler::compile_method(ciEnv*, ciMethod*, int, bool, DirectiveSet*)+0x46d  (c2compiler.cpp:142)
V  [libjvm.so+0xb37882]  CompileBroker::invoke_compiler_on_method(CompileTask*)+0xb22  (compileBroker.cpp:2307)
V  [libjvm.so+0xb38888]  CompileBroker::compiler_thread_loop()+0x588  (compileBroker.cpp:1951)
V  [libjvm.so+0x109182f]  JavaThread::thread_main_inner()+0x12f  (javaThread.cpp:773)
V  [libjvm.so+0x1ac19d6]  Thread::call_run()+0xb6  (thread.cpp:231)
V  [libjvm.so+0x1748888]  thread_native_entry(Thread*)+0x128  (os_linux.cpp:877)

@merykitty
Copy link
Member Author

@TobiHartmann The failure was due to the fact that PhaseMacroExpand::eliminate_allocate_node can push nodes on the igvn worklist even if it does not successfully remove the allocation. As a result, I moved the progress check to after igvn.optimize() so that igvn worklist is cleared.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

Successfully merging this pull request may close these issues.

2 participants