RFR: 8271055: Crash during deoptimization with "assert(bb->is_reachable()) failed: getting result from unreachable basicblock" with -XX:+VerifyStack [v3]

Yi Yang yyang at openjdk.java.net
Mon Jul 26 14:58:13 UTC 2021


On Mon, 26 Jul 2021 07:43:39 GMT, Yi Yang <yyang at openjdk.org> wrote:

>> Hi, I'm trying to fix JDK-8271055. The root cause is that some basic blocks are not interpreted because there is no trap bytecode inside them, these basic blocks eventually become unreachable and lead to a crash. Maybe we need to coordinate compiler and hotspot groups to fix this crash.
>> 
>> ----
>> 
>> The attached test generates the following bytecode:
>> 
>>   void test();
>>     descriptor: ()V
>>     flags: (0x0000)
>>     Code:
>>       stack=2, locals=3, args_size=1
>>          0: iconst_1
>>          1: istore_1
>>          2: iload_1
>>          3: bipush        100
>>          5: if_icmpge     29
>>          8: iinc          1, 1
>>         11: goto          2
>>         14: astore_2
>>         15: iload_1
>>         16: bipush        100
>>         18: if_icmpge     27
>>         21: iinc          1, 1
>>         24: goto          15
>>         27: aload_2
>>         28: athrow
>>         29: return
>> 
>> 
>> 
>> Javac generates some unreachable basic blocks(BCI 14 - 28), and there is no exception table for them, VM knows nothing about them. I found the same bug report at JDK-8022186 which was marked as `Fixed`, but I think it was not properly fixed, In some similar cases, javac cannot work well, I have filed https://bugs.openjdk.java.net/browse/JDK-8271254 for another javac bug.
>> 
>> Going back to this bug, the proposed change is to insert a nop in empty try-block so that javac can generate the correct exception table. Now generated bytecodes look like this:
>> 
>>   void test();
>>     descriptor: ()V
>>     flags: (0x0000)
>>     Code:
>>       stack=2, locals=3, args_size=1
>>          0: iconst_1
>>          1: istore_1
>>          2: nop
>>          3: iload_1
>>          4: bipush        100
>>          6: if_icmpge     30
>>          9: iinc          1, 1
>>         12: goto          3
>>         15: astore_2
>>         16: iload_1
>>         17: bipush        100
>>         19: if_icmpge     28
>>         22: iinc          1, 1
>>         25: goto          16
>>         28: aload_2
>>         29: athrow
>>         30: return
>>       Exception table:
>>          from    to  target type
>>              2     3    15   any
>> 
>> 
>> However, this is not the end. Even if the exception table is correctly generated, VM only enters GenerateOopMap::do_exception_edge when the bytecode may be trapped. In order to setup handler block, we need to relax this restriction to allow even bytecodes such as nop to correctly enter GenerateOopMap::do_exception_edge. Otherwise, handler block will not be interpreted, its stack is problematic and finally hits the assertion.
>
> Yi Yang has updated the pull request incrementally with one additional commit since the last revision:
> 
>   remove usenewcode

P.S. In summary, I think there are two bugs: one for javac, one for VM.

-- Javac side:
The proposed fix is to insert a "nop".

I'm not good at this area, hope to have more experts' comments.

--- VM side:
To verify what I said, we can consider the below case which does not contain trap bytecodes in some unreachable basic blocks:


public class VerifyStackWithUnreachableBlock {
    public static void main(String[] strArr) {
        VerifyStackWithUnreachableBlock _instance = new VerifyStackWithUnreachableBlock();
        for (int i = 0; i < 10000; i++) {
            _instance.test();
        }
    }

    void test() {
        int i8 = 1;
        try {
            int p=0;
            p++;
        } finally {
            for (; i8 < 100; i8++) {
            }
        }
    }
}


It crashes with the same assertion:

#
# A fatal error has been detected by the Java Runtime Environment:
#
#  Internal Error (/home/qingfeng.yy/jdktip/src/hotspot/share/oops/generateOopMap.cpp:2220), pid=130592, tid=130631
#  assert(bb->is_reachable()) failed: getting result from unreachable basicblock
#
# JRE version: OpenJDK Runtime Environment (18.0) (slowdebug build 18-internal+0-adhoc.qingfengyy.jdktip)
# Java VM: OpenJDK 64-Bit Server VM (slowdebug 18-internal+0-adhoc.qingfengyy.jdktip, mixed mode, sharing, tiered, compressed oops, compressed class ptrs, g1 gc, linux-amd64)
# Problematic frame:
# V  [libjvm.so+0xa505b1]  GenerateOopMap::result_for_basicblock(int)+0xb5
#
# No core dump will be written. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again
#
# If you would like to submit a bug report, please visit:
#   https://bugreport.java.com/bugreport/crash.jsp
#

---------------  S U M M A R Y ------------

Command Line: -Dtest.vm.opts= -Dtest.tool.vm.opts= -Dtest.compiler.opts= -Dtest.java.opts= -Dtest.jdk=/home/qingfeng.yy/jdktip/build/linux-x86_64-server-slowdebug/images/jdk -Dcompile.jdk=/home/qingfeng.yy/jdktip/build/linux-x86_64-server-slowdebug/images/jdk -Dtest.timeout.factor=1.0 -Dtest.root=/home/qingfeng.yy/jdktip/test/hotspot/jtreg -Dtest.name=compiler/interpreter/VerifyStackWithUnreachableBlock.java -Dtest.file=/home/qingfeng.yy/jdktip/test/hotspot/jtreg/compiler/interpreter/VerifyStackWithUnreachableBlock.java -Dtest.src=/home/qingfeng.yy/jdktip/test/hotspot/jtreg/compiler/interpreter -Dtest.src.path=/home/qingfeng.yy/jdktip/test/hotspot/jtreg/compiler/interpreter -Dtest.classes=/home/qingfeng.yy/jdktip/JTwork/classes/0/compiler/interpreter/VerifyStackWithUnreachableBlock.d -Dtest.class.path=/home/qingfeng.yy/jdktip/JTwork/classes/0/compiler/interpreter/VerifyStackWithUnreachableBlock.d -XX:+IgnoreUnrecognizedVMOptions -XX:+VerifyStack com.sun.javatest.regtest.agent.MainWra
 pper /home/qingfeng.yy/jdktip/JTwork/compiler/interpreter/VerifyStackWithUnreachableBlock.d/main.0.jta

Host: e69e13043.et15sqa, Intel(R) Xeon(R) Platinum 8163 CPU @ 2.50GHz, 96 cores, 503G, Alibaba Group Enterprise Linux Server release 7.2 (Paladin)
Time: Mon Jul 26 22:46:38 2021 CST elapsed time: 1.894403 seconds (0d 0h 0m 1s)

---------------  T H R E A D  ---------------

Current thread (0x00007f415c3a5ab0):  JavaThread "MainThread" [_thread_in_Java, id=130631, stack(0x00007f40cd9bc000,0x00007f40cdabd000)]

Stack: [0x00007f40cd9bc000,0x00007f40cdabd000],  sp=0x00007f40cdab8c50,  free space=1011k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
V  [libjvm.so+0xa505b1]  GenerateOopMap::result_for_basicblock(int)+0xb5
V  [libjvm.so+0xfa41b3]  OopMapForCacheEntry::compute_map(Thread*)+0x155
V  [libjvm.so+0xfa4d23]  OopMapCacheEntry::fill(methodHandle const&, int)+0xdd
V  [libjvm.so+0xfa5b4b]  OopMapCache::compute_one_oop_map(methodHandle const&, int, InterpreterOopMap*)+0x4d
V  [libjvm.so+0x83ef0e]  Deoptimization::unpack_frames(JavaThread*, int)+0x642
v  ~DeoptimizationBlob
....

After applying this patch, it works.

-------------

PR: https://git.openjdk.java.net/jdk/pull/4902


More information about the hotspot-compiler-dev mailing list