JDK-8181872 : C1: possible overflow when strength reducing integer multiply by constant
  • Type: Bug
  • Component: hotspot
  • Sub-Component: compiler
  • Affected Version: 8,8-aarch64,9,10
  • Priority: P2
  • Status: Closed
  • Resolution: Fixed
  • Submitted: 2017-06-09
  • Updated: 2022-06-27
  • Resolved: 2017-06-20
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 10 JDK 8 JDK 9 Other
10Fixed 8u251Fixed 9 b175Fixed openjdk8u252Fixed
Related Reports
Relates :  
Description
The tests I've seen fail are:

TEST: java/util/concurrent/BlockingQueue/CancelledProducerConsumerLoops.java
TEST: java/util/concurrent/BlockingQueue/MultipleProducersSingleConsumerLoops.java
TEST: java/util/concurrent/BlockingQueue/ProducerConsumerLoops.java
TEST: java/util/concurrent/ConcurrentQueues/ConcurrentQueueLoops.java
TEST: java/util/concurrent/Exchanger/ExchangeLoops.java
TEST: java/util/concurrent/ExecutorCompletionService/ExecutorCompletionServiceLoops.java
TEST: java/util/concurrent/FutureTask/CancelledFutureLoops.java
TEST: java/util/concurrent/locks/ReentrantLock/LockOncePerThreadLoops.java
TEST: java/util/concurrent/locks/ReentrantLock/SimpleReentrantLockLoops.java
TEST: java/util/concurrent/locks/ReentrantLock/TimeoutLockLoops.java
TEST: java/util/concurrent/locks/ReentrantReadWriteLock/MapLoops.java

This bug is easily reproducible with:

jtreg -verbose:all -noreport -jdk:$PWD/build/macosx-x86_64-normal-server-release/images/jdk -vmoptions:"-XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI -XX:+UseJVMCICompiler" jdk/test/java/util/concurrent/BlockingQueue/CancelledProducerConsumerLoops.java

#
# A fatal error has been detected by the Java Runtime Environment:
#
#  Internal Error (c1_LIRAssembler_x86.cpp:2032), pid=21760, tid=28419
#  Error: ShouldNotReachHere()
#
# JRE version: OpenJDK Runtime Environment (10.0) (build 10-internal+0-adhoc.cthalinger.hs)
# Java VM: OpenJDK 64-Bit Server VM (10-internal+0-adhoc.cthalinger.hs, mixed mode, tiered, jvmci, jvmci compiler, compressed oops, g1 gc, bsd-amd64)
# No core dump will be written. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again
#
# An error report file with more information is saved as:
# /Users/cthalinger/jdk10/hs/JTwork/scratch/hs_err_pid21760.log
#
# Compiler replay data is saved as:
# /Users/cthalinger/jdk10/hs/JTwork/scratch/replay_pid21760.log
#
# If you would like to submit a bug report, please visit:
#   http://bugreport.java.com/bugreport/crash.jsp
#

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

Current thread (0x00007fcaf58e5800):  JavaThread "C1 CompilerThread3" daemon [_thread_in_native, id=28419, stack(0x000070000ba8a000,0x000070000bb8a000)]


Current CompileTask:
C1:    128  274       3       LoopHelpers::compute2 (28 bytes)

Stack: [0x000070000ba8a000,0x000070000bb8a000],  sp=0x000070000bb88e90,  free space=1019k
Native frames: (J=compiled Java code, A=aot compiled Java code, j=interpreted, Vv=VM code, C=native code)
V  [libjvm.dylib+0x6e665a]  VMError::report_and_die(int, char const*, char const*, __va_list_tag*, Thread*, unsigned char*, void*, void*, char const*, int, unsigned long)+0x4ca
V  [libjvm.dylib+0x6e6cce]  VMError::report_and_die(Thread*, char const*, int, char const*, char const*, __va_list_tag*)+0x3c
V  [libjvm.dylib+0x26e1e6]  report_vm_error(char const*, int, char const*, char const*, ...)+0xa2
V  [libjvm.dylib+0x17cec4]  LIR_Assembler::arith_op(LIR_Code, LIR_OprDesc*, LIR_OprDesc*, LIR_OprDesc*, CodeEmitInfo*, bool)+0x1134
V  [libjvm.dylib+0x172f7f]  LIR_Assembler::emit_op2(LIR_Op2*)+0x61
V  [libjvm.dylib+0x171ff3]  LIR_Assembler::emit_lir_list(LIR_List*)+0x4b
V  [libjvm.dylib+0x17204f]  LIR_Assembler::emit_code(BlockList*)+0x2b
V  [libjvm.dylib+0x153163]  Compilation::emit_code_body()+0x127
V  [libjvm.dylib+0x153498]  Compilation::compile_java_method()+0x10a
V  [libjvm.dylib+0x153647]  Compilation::compile_method()+0x71
V  [libjvm.dylib+0x15383e]  Compilation::Compilation(AbstractCompiler*, ciEnv*, ciMethod*, int, BufferBlob*, DirectiveSet*)+0x184
V  [libjvm.dylib+0x154c31]  Compiler::compile_method(ciEnv*, ciMethod*, int, DirectiveSet*)+0x61
V  [libjvm.dylib+0x2425fb]  CompileBroker::invoke_compiler_on_method(CompileTask*)+0x539
V  [libjvm.dylib+0x241ebf]  CompileBroker::compiler_thread_loop()+0x1b3
V  [libjvm.dylib+0x6a6fe0]  JavaThread::thread_main_inner()+0x82
V  [libjvm.dylib+0x6a6e53]  JavaThread::run()+0x18b
V  [libjvm.dylib+0x5ae8ac]  thread_native_entry(Thread*)+0x135
C  [libsystem_pthread.dylib+0x393b]  _pthread_body+0xb4
C  [libsystem_pthread.dylib+0x3887]  _pthread_body+0x0
C  [libsystem_pthread.dylib+0x308d]  thread_start+0xd
C  0x0000000000000000

Comments
Fix Request (8u) This fixes the C1 miscompilation. Patch applies with reshuffling, dropping aarch64 and arm hunks. 8u RFR (reviewed by andrew): https://mail.openjdk.java.net/pipermail/jdk8u-dev/2020-February/011205.html
20-02-2020

URL: http://hg.openjdk.java.net/jdk9/jdk9/hotspot/rev/16c9c159df90 User: lana Date: 2017-06-21 18:31:05 +0000
21-06-2017

URL: http://hg.openjdk.java.net/jdk9/dev/hotspot/rev/16c9c159df90 User: vlivanov Date: 2017-06-20 13:46:45 +0000
20-06-2017

I think the fix is safe it limits when optimization is used. Approved for JDK 9.
19-06-2017

Webrev: http://cr.openjdk.java.net/~vlivanov/8181872/webrev.00/
19-06-2017

Fix Request The crash is caused by a long standing bug: optimization implementation hits int overflow (which behavior is undefined in C/C++) and it leads to broken IR being generated which causes a JVM crash. It's hard to estimate the impact (after C/C++ compiler upgrade in jdk 9), so it's safer to fix the bug. The fix is small and focused: it reduces optimization scope by disabling the problematic optimization for corner cases: constant < 0 && constant == Integer.MAX_VALUE.
19-06-2017

The crash happens when compiling the following method: public static int compute2(int x) { int loops = (x >>> 4) & 7; while (loops-- > 0) { x = (x * 2147483647) % 16807; } return x; } It crashes because LIR_Assembler::arith_op encounters "mul reg const reg" LIR op shape, but can't handle it: 70 mul [rsi|I] [int:2147483647|I] [rsi|I] The problem is that LIRGenerator::do_ArithmeticOp_Int doesn't check for integer overflow and is_power_of_2(iconst + 1) can return true when iconst == max_jint: if (x->op() == Bytecodes::_imul ) { ... int iconst = right_arg->get_jint_constant(); if (iconst > 0) { if (is_power_of_2(iconst)) { use_constant = true; } else if (is_power_of_2(iconst - 1) || is_power_of_2(iconst + 1)) { use_constant = true; use_tmp = true; } } }
14-06-2017

I'm able to reliably reproduce the crash with the following change: diff --git a/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp b/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp --- a/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp +++ b/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp @@ -603,7 +603,7 @@ bool use_constant = false; bool use_tmp = false; if (right_arg->is_constant()) { - int iconst = right_arg->get_jint_constant(); + jlong iconst = right_arg->get_jint_constant(); if (iconst > 0) { if (is_power_of_2(iconst)) { use_constant = true;
14-06-2017

Hi Vladimir, could you please look into this problem? Thank you! Best regards, Zoltan
12-06-2017

ILW=crash,few tests,no workaround=HLH=P2
12-06-2017

Looks like this only fails on Mac. Here is the compiler I am using: $ clang -v Apple LLVM version 8.1.0 (clang-802.0.42) Target: x86_64-apple-darwin16.6.0 Thread model: posix InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
09-06-2017

I can get it to fail with fastdebug and here is some debugging information: (lldb) frame select 9 libjvm.dylib was compiled with optimization - stepping may behave oddly; variables may not be available. frame #9: 0x0000000110098366 libjvm.dylib`LIR_Assembler::arith_op(this=<unavailable>, code=<unavailable>, left=<unavailable>, right=0x00007faeb60c8690, dest=0x000000000000000b, info=<unavailable>, pop_fpu_stack=<unavailable>) at c1_LIRAssembler_x86.cpp:2008 [opt] 2005 case lir_add: __ addl (lreg, rreg); break; 2006 case lir_sub: __ subl (lreg, rreg); break; 2007 case lir_mul: __ imull(lreg, rreg); break; -> 2008 default: ShouldNotReachHere(); 2009 } 2010 2011 } else if (right->is_stack()) { (lldb) frame variable (LIR_Assembler *) this = <variable not available> (LIR_Code) code = <variable not available> (LIR_Opr) left = <variable not available> (LIR_Opr) right = 0x00007faeb60c8690 (LIR_Opr) dest = 0x000000000000000b (CodeEmitInfo *) info = <variable not available> (bool) pop_fpu_stack = <unable to extract DW_OP_bit_piece(bit_size = 1, bit_offset = 0) from an addresss value.> (Register) lreg = <variable not available> (Register) rreg = <variable not available> (lldb) up frame #10: 0x000000011008c339 libjvm.dylib`LIR_Assembler::emit_op2(this=0x000070000ed9a408, op=0x00007faeb60c8700) at c1_LIRAssembler.cpp:731 [opt] 728 case lir_div_strictfp: 729 case lir_rem: 730 assert(op->fpu_pop_count() < 2, ""); -> 731 arith_op( 732 op->code(), 733 op->in_opr1(), 734 op->in_opr2(), (lldb) frame variable (LIR_Assembler *) this = 0x000070000ed9a408 (LIR_Op2 *) op = 0x00007faeb60c8700 (lldb) p op (LIR_Op2 *) $0 = 0x00007faeb60c8700 (lldb) p *op (LIR_Op2) $1 = { LIR_Op = { _file = 0x000000011099b14a "c1_LIRGenerator.cpp" _line = 562 _result = 0x000000000000000b _code = 54 _flags = 0 _info = 0x0000000000000000 _id = 70 _fpu_pop_count = 0 _source = 0x00007faeb701ef70 } _fpu_stack_size = 0 _opr1 = 0x000000000000000b _opr2 = 0x00007faeb60c8690 _type = T_ILLEGAL _tmp1 = 0xffffffffffffffff _tmp2 = 0xffffffffffffffff _tmp3 = 0xffffffffffffffff _tmp4 = 0xffffffffffffffff _tmp5 = 0xffffffffffffffff _condition = lir_cond_unknown } (lldb) LIR_Code 54 is lir_mul. The line number 2008 above is wrong; it should be 2032.
09-06-2017

$ jtreg -verbose:all -noreport -jdk:$PRODUCT_HOME jdk/test/java/util/concurrent/BlockingQueue/CancelledProducerConsumerLoops.java -------------------------------------------------- TEST: java/util/concurrent/BlockingQueue/CancelledProducerConsumerLoops.java TEST JDK: /Users/cthalinger/jdk9/build/macosx-x86_64-normal-server-release/images/jdk ACTION: build -- Passed. All files up to date REASON: Named class compiled on demand TIME: 0.001 seconds messages: command: build CancelledProducerConsumerLoops reason: Named class compiled on demand elapsed time (seconds): 0.001 ACTION: main -- Failed. Unexpected exit from test [exit code: 134] REASON: Assumed action based on file name: run main CancelledProducerConsumerLoops TIME: 0.204 seconds messages: command: main CancelledProducerConsumerLoops reason: Assumed action based on file name: run main CancelledProducerConsumerLoops Mode: othervm elapsed time (seconds): 0.204 configuration: STDOUT: # # A fatal error has been detected by the Java Runtime Environment: # # Internal Error (c1_LIRAssembler_x86.cpp:2032), pid=81016, tid=28419 # Error: ShouldNotReachHere() # # JRE version: OpenJDK Runtime Environment (9.0) (build 9-internal+0-adhoc.cthalinger.jdk9) # Java VM: OpenJDK 64-Bit Server VM (9-internal+0-adhoc.cthalinger.jdk9, mixed mode, tiered, compressed oops, g1 gc, bsd-amd64) # No core dump will be written. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again # # An error report file with more information is saved as: # /Users/cthalinger/jdk9/JTwork/scratch/hs_err_pid81016.log # # Compiler replay data is saved as: # /Users/cthalinger/jdk9/JTwork/scratch/replay_pid81016.log # # If you would like to submit a bug report, please visit: # http://bugreport.java.com/bugreport/crash.jsp # STDERR: rerun: DISPLAY=/private/tmp/com.apple.launchd.5rhds7TjSD/org.macosforge.xquartz:0 \ HOME=/Users/cthalinger \ LANG=en_US.UTF-8 \ LC_CTYPE=en_US.UTF-8 \ PATH=/bin:/usr/bin \ CLASSPATH=/Users/cthalinger/jdk9/JTwork/classes/java/util/concurrent/BlockingQueue:/Users/cthalinger/jdk9/jdk/test/java/util/concurrent/BlockingQueue:/Users/cthalinger/jdk9/JTwork/classes/lib/testlibrary:/Users/cthalinger/jdk9/jdk/test/lib/testlibrary:/Users/cthalinger/jtreg/lib/javatest.jar:/Users/cthalinger/jtreg/lib/jtreg.jar \ /Users/cthalinger/jdk9/build/macosx-x86_64-normal-server-release/images/jdk/bin/java \ -Dtest.src=/Users/cthalinger/jdk9/jdk/test/java/util/concurrent/BlockingQueue \ -Dtest.src.path=/Users/cthalinger/jdk9/jdk/test/java/util/concurrent/BlockingQueue:/Users/cthalinger/jdk9/jdk/test/lib/testlibrary \ -Dtest.classes=/Users/cthalinger/jdk9/JTwork/classes/java/util/concurrent/BlockingQueue \ -Dtest.class.path=/Users/cthalinger/jdk9/JTwork/classes/java/util/concurrent/BlockingQueue:/Users/cthalinger/jdk9/JTwork/classes/lib/testlibrary \ -Dtest.vm.opts= \ -Dtest.tool.vm.opts= \ -Dtest.compiler.opts= \ -Dtest.java.opts= \ -Dtest.jdk=/Users/cthalinger/jdk9/build/macosx-x86_64-normal-server-release/images/jdk \ -Dcompile.jdk=/Users/cthalinger/jdk9/build/macosx-x86_64-normal-server-release/images/jdk \ -Dtest.timeout.factor=1.0 \ com.sun.javatest.regtest.agent.MainWrapper /Users/cthalinger/jdk9/JTwork/java/util/concurrent/BlockingQueue/CancelledProducerConsumerLoops.d/main.0.jta TEST RESULT: Failed. Unexpected exit from test [exit code: 134] -------------------------------------------------- Test results: failed: 1 Results written to /Users/cthalinger/jdk9/JTwork Error: Some tests failed or other problems occurred.
09-06-2017

Oh, wait. It's not Graal related at all. That's weird.
09-06-2017

I can't get it to crash with a slow debug build.
09-06-2017