JDK-8028159 : C2: compiler stack overflow during inlining of @ForceInline methods
  • Type: Bug
  • Component: hotspot
  • Sub-Component: compiler
  • Affected Version: hs25
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • Submitted: 2013-11-11
  • Updated: 2015-02-02
  • Resolved: 2013-11-14
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 7 JDK 8 Other
7u80Fixed 8Fixed hs25,port-stage-ppc-aixFixed
Description
C2 may fail to delay inlining of @ForceInline methods. In case call sequence is deep enough, C2 can crash due to stack overflow.

Test case:
http://cr.openjdk.java.net/~vlivanov/8012941/webrev.00/raw_files/new/test/compiler/jsr292/DeepInliningTest.java

Compilation output:
   6451   98    b        DeepInliningTest::f (10 bytes)
                            @ 3   java.lang.invoke.LambdaForm$MH/168423058::invokeExact_MT (13 bytes)   inline (hot)
                              @ 2   java.lang.invoke.Invokers::checkExactType (30 bytes)   inline (hot)
                                @ 11   java.lang.invoke.MethodHandle::type (5 bytes)   accessor
                              @ 9   java.lang.invoke.LambdaForm$MH/1450495309::convert (21 bytes)   inline (hot)
                                @ 5   java.lang.invoke.LambdaForm$MH/1670782018::convert (22 bytes)   inline (hot)
                                  @ 5   java.lang.invoke.LambdaForm$MH/1706377736::convert (21 bytes)   inline (hot)
                                    @ 5   java.lang.invoke.LambdaForm$MH/468121027::convert (22 bytes)   inline (hot)
                                      @ 5   java.lang.invoke.LambdaForm$MH/1804094807::convert (21 bytes)   inline (hot)
                                        @ 5   java.lang.invoke.LambdaForm$MH/951007336::convert (22 bytes)   inline (hot)
                                          @ 5   java.lang.invoke.LambdaForm$MH/2001049719::convert (21 bytes)   inline (hot)
                                            @ 5   java.lang.invoke.LambdaForm$MH/1528902577::convert (22 bytes)   inline (hot)
...

P3 = HLM (ILW)
I = H: VM crash
L = L: very narrow corner case
W = M: increase maximum stack size for compiler threads
Comments
John, the calls aren't recursive. In this particular case, nested asType() conversions produce very long call chain between different LF::convert methods.
13-11-2013

noreg-hard: without additional diagnostic code, it's very time consuming to provoke the bug. See [1] for a test. [1] http://cr.openjdk.java.net/~vlivanov/8012941/webrev.00/raw_files/new/test/compiler/jsr292/DeepInliningTest.java
13-11-2013

In stress tests, method handles can be arbitrarily deep. In typical use cases they are not; they are adapted a fixed number of times before being installed in a call site. It may be that some of these extreme cases can be solved by simply bailing out of the compile and continuing to interpret. A quick solution would be to have ForceInline fail after a larger stack depth than normal. Since part of the problem is the ForceInline directive, we need to ask whether they are all necessary. If we are adjusting heuristics by ForceInline, some of them can be removed, if we can detect the pattern from inside C2. It seems especially odd to have recursive calls through ForceInline methods.
12-11-2013

C2 fails to delay inlining of LF$MH::convert method because it is called using method handle intrinsic and it is forbidden to delay inlining of the method MH intrinsic points to. Call stack: Compile::call_generator (this=0x10e307ab0, callee=0x10e307ab0, vtable_index=238058160, jvms=0x10e307ab0, prof_factor=2.17527468e-30, speculative_receiver_type=0x0, allow_intrinsics=true, delayed_forbidden=true, allow_inline=false, call_does_dispatch=false) at doCall.cpp:178 CallGenerator::for_method_handle_inline (jvms=0x10e307bb0, caller=0x10e307bb0, callee=0x1010e1318, input_not_const=@0x11078a5c8) at callGenerator.cpp:778 CallGenerator::for_method_handle_call (jvms=0x11079e628, caller=0x110789368, callee=0x1100f28e8, delayed_forbidden=false) at callGenerator.cpp:739 Compile::call_generator (this=0x10e307da0, callee=0x10e307da0, vtable_index=238058912, jvms=0x10e307da0, prof_factor=2.17541611e-30, speculative_receiver_type=0x0, allow_intrinsics=true, delayed_forbidden=false, allow_inline=true, call_does_dispatch=false) at doCall.cpp:144 Parse::do_call (this=0x10e3080f0) at doCall.cpp:493 CallGenerator* CallGenerator::for_method_handle_inline(JVMState* jvms, ciMethod* caller, ciMethod* callee, bool& input_not_const) { ... vmIntrinsics::ID iid = callee->intrinsic_id(); ... switch (iid) { case vmIntrinsics::_invokeBasic: { ... CallGenerator* cg = C->call_generator(target, vtable_index, false, jvms, true, PROB_ALWAYS, NULL, true, true); ... case vmIntrinsics::_linkToVirtual: case vmIntrinsics::_linkToStatic: case vmIntrinsics::_linkToSpecial: case vmIntrinsics::_linkToInterface: ... CallGenerator* cg = C->call_generator(target, vtable_index, call_does_dispatch, jvms, true, PROB_ALWAYS, speculative_receiver_type, true, true); and the last argument of ::call_generator forbids late inlining of the method: CallGenerator* Compile::call_generator(ciMethod* callee, int vtable_index, bool call_does_dispatch, JVMState* jvms, bool allow_inline, float prof_factor, ciKlass* speculative_receiver_type, bool allow_intrinsics, bool delayed_forbidden) {
11-11-2013

C2 is stuck trying to inline the whole chain of LF$MH::convert methods: #23 0x000000010195ee96 in InlineTree::ok_to_inline (this=0x1030b2878, callee_method=0x11078a5c8, jvms=0x10e307950, profile=@0x10e307950, initial_wci=0x10e307950, should_delay=@0x10e307950) at bytecodeInfo.cpp:542 #24 0x0000000101b56be5 in Compile::call_generator (this=0x10e307ab0, callee=0x10e307ab0, vtable_index=238058160, jvms=0x10e307ab0, prof_factor=2.17527468e-30, speculative_receiver_type=0x0, allow_intrinsics=true, delayed_forbidden=true, allow_inline=false, call_does_dispatch=false) at doCall.cpp:178 #25 0x0000000101a10b95 in CallGenerator::for_method_handle_inline (jvms=0x10e307bb0, caller=0x10e307bb0, callee=0x1010e1318, input_not_const=@0x11078a5c8) at callGenerator.cpp:778 #26 0x0000000101a1119c in CallGenerator::for_method_handle_call (jvms=0x11079e628, caller=0x110789368, callee=0x1100f28e8, delayed_forbidden=false) at callGenerator.cpp:739 #27 0x0000000101b569b3 in Compile::call_generator (this=0x10e307da0, callee=0x10e307da0, vtable_index=238058912, jvms=0x10e307da0, prof_factor=2.17541611e-30, speculative_receiver_type=0x0, allow_intrinsics=true, delayed_forbidden=false, allow_inline=true, call_does_dispatch=false) at doCall.cpp:144 #28 0x0000000101b576e2 in Parse::do_call (this=0x10e3080f0) at doCall.cpp:493 #29 0x0000000101ef112f in Parse::do_one_bytecode (this=0x10e3080f0) at parse2.cpp:2339 #30 0x0000000101ee5672 in Parse::do_one_block (this=0x10e3080f0) at parse1.cpp:1413 #31 0x0000000101ee5a46 in Parse::failing () at /Users/vladimir/ws/jdk/ws/tl/hotspot/src/share/vm/opto/parse.hpp:682 #32 0x0000000101ee5a46 in Parse::do_all_blocks (this=0x10e402dc0) at parse1.cpp:685 #33 0x0000000101ee8061 in Parse::Parse (this=0x10e3080f0, caller=0x11078a178, parse_method=0x11079e1d8, expected_uses=2.17556959e-30, parent=0x1010e1068) at parse1.cpp:591 #34 0x0000000101a11314 in ParseGenerator::generate (this=0x1030b2908, jvms=0x11079e248, parent_parser=0x3f80000000000000) at callGenerator.cpp:83 #35 0x0000000101b577f1 in Parse::do_call (this=0x10e3085d0) at doCall.cpp:531 #36 0x0000000101ef112f in Parse::do_one_bytecode (this=0x10e3085d0) at parse2.cpp:2339 #37 0x0000000101ee5672 in Parse::do_one_block (this=0x10e3085d0) at parse1.cpp:1413 #38 0x0000000101ee5a46 in Parse::failing () at /Users/vladimir/ws/jdk/ws/tl/hotspot/src/share/vm/opto/parse.hpp:682 #39 0x0000000101ee5a46 in Parse::do_all_blocks (this=0x10e402dc0) at parse1.cpp:685 #40 0x0000000101ee8061 in Parse::Parse (this=0x10e3085d0, caller=0x110788f18, parse_method=0x11079ddf8, expected_uses=2.17580431e-30, parent=0x1010e0850) at parse1.cpp:591 #41 0x0000000101a11314 in ParseGenerator::generate (this=0x1030b27d8, jvms=0x11079de68, parent_parser=0x3f80000000000000) at callGenerator.cpp:83 #42 0x0000000101b577f1 in Parse::do_call (this=0x10e308ab0) at doCall.cpp:531 #43 0x0000000101ef112f in Parse::do_one_bytecode (this=0x10e308ab0) at parse2.cpp:2339 #44 0x0000000101ee5672 in Parse::do_one_block (this=0x10e308ab0) at parse1.cpp:1413 #45 0x0000000101ee5a46 in Parse::failing () at /Users/vladimir/ws/jdk/ws/tl/hotspot/src/share/vm/opto/parse.hpp:682 #46 0x0000000101ee5a46 in Parse::do_all_blocks (this=0x10e402dc0) at parse1.cpp:685 #47 0x0000000101ee8061 in Parse::Parse (this=0x10e308ab0, caller=0x110787cb8, parse_method=0x11079da18, expected_uses=2.17603903e-30, parent=0x1010e0020) at parse1.cpp:591 ...
11-11-2013