JDK-8130309 : Need to bailout cleanly if creation of stubs fails when codecache is out of space
  • Type: Bug
  • Component: hotspot
  • Sub-Component: compiler
  • Affected Version: 8,9
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • Submitted: 2015-07-02
  • Updated: 2017-02-13
  • Resolved: 2015-07-29
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.
8u112Fixed 9 b78Fixed
Related Reports
Duplicate :  
Relates :  
Relates :  
CompiledStaticCall::emit_to_interp_stub calls start_a_stub(), which can cause codecache expansion.  We bail out of emit_to_interp_stub, but the caller continues blindly on.

# A fatal error has been detected by the Java Runtime Environment:
#  Internal Error (/opt/jprt/T/P1/220303.vkozlov/s/hotspot/src/share/vm/opto/output.cpp:1510), pid=22959, tid=0x0000007f32f4d1f0
#  assert(false) failed: wrong size of mach node
# JRE version: Java(TM) SE Runtime Environment (9.0) (build 1.9.0-internal-fastdebug-20150706220303.vkozlov.8086069-b00)
# Java VM: Java HotSpot(TM) 64-Bit Server VM (1.9.0-internal-fastdebug-20150706220303.vkozlov.8086069-b00 compiled mode linux-aarch64 compressed oops)
# Core dump will be written. Default location: Core dumps may be processed with "/usr/share/apport/apport %p %s %c %P" (or dumping to /export/local/aurora/sandbox/results/workDir/compiler/profiling/spectrapredefineclass/Launcher/core.22959)
# 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 (0x0000007f8c2eb800):  JavaThread "C2 CompilerThread1" daemon [_thread_in_native, id=22989, stack(0x0000007f32e4e000,0x0000007f32f4e000)]

Stack: [0x0000007f32e4e000,0x0000007f32f4e000],  sp=0x0000007f32f48880,  free space=1002k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
V  [libjvm.so+0xde36f0]  VMError::report(outputStream*)+0x162c;;  VMError::report(outputStream*)+0x162c
V  [libjvm.so+0xde39bc]  VMError::report_and_die()+0x130;;  VMError::report_and_die()+0x130
V  [libjvm.so+0x5df2c8]  report_vm_error(char const*, int, char const*, char const*)+0x74;;  report_vm_error(char const*, int, char const*, char const*)+0x74
V  [libjvm.so+0xba3f9c]  Compile::fill_buffer(CodeBuffer*, unsigned int*)+0x109c;;  Compile::fill_buffer(CodeBuffer*, unsigned int*)+0x109c
V  [libjvm.so+0xba505c]  Compile::Output()+0x3f0;;  Compile::Output()+0x3f0
V  [libjvm.so+0x565948]  Compile::Code_Gen()+0x4e0;;  Compile::Code_Gen()+0x4e0
V  [libjvm.so+0x5691b8]  Compile::Compile(ciEnv*, C2Compiler*, ciMethod*, int, bool, bool, bool)+0x1094;;  Compile::Compile(ciEnv*, C2Compiler*, ciMethod*, int, bool, bool, bool)+0x1094
V  [libjvm.so+0x41e6d4]  C2Compiler::compile_method(ciEnv*, ciMethod*, int)+0x134;;  C2Compiler::compile_method(ciEnv*, ciMethod*, int)+0x134
V  [libjvm.so+0x572d24]  CompileBroker::invoke_compiler_on_method(CompileTask*)+0x3c8;;  CompileBroker::invoke_compiler_on_method(CompileTask*)+0x3c8
V  [libjvm.so+0x5739e4]  CompileBroker::compiler_thread_loop()+0x378;;  CompileBroker::compiler_thread_loop()+0x378
V  [libjvm.so+0xd6f780]  JavaThread::thread_main_inner()+0x1bc;;  JavaThread::thread_main_inner()+0x1bc
V  [libjvm.so+0xd6f9d4]  JavaThread::run()+0x1e0;;  JavaThread::run()+0x1e0
V  [libjvm.so+0xb7f928]  java_start(Thread*)+0xd8;;  java_start(Thread*)+0xd8
C  [libpthread.so.0+0x7e2c]  start_thread+0xb0

Current CompileTask:
C2:  29729 2353   !b        java.lang.invoke.DirectMethodHandle::makePreparedFieldLambdaForm (1079 bytes)

One can easily reproduce the issue with "java -XX:+StressCodeBuffers -Xcomp -version".

While C2 is emitting code, an assert is hit because the emitted code size does not correspond to the size of the instruction. The problem is that the code cache is full and therefore the creation of a to-interpreter stub failed. Instead of bailing out we continue and hit the assert. More precisely, we emit code for a CallStaticJavaDirectNode on aarch64 and emit two stubs (see 'aarch64_enc_java_static_call' in aarch64.ad): - MacroAssembler::emit_trampoline_stub() -> requires 64 bytes - CompiledStaticCall::emit_to_interp_stub() -> requires 56 bytes However, we only have 112 bytes of free space in the stub section of the code buffer and need to expand it. Since the code cache is full, the expansion fails and the corresponding code blob is freed. In CodeBuffer::free_blob() -> CodeBuffer::set_blob() we set addresses to 'badAddress' and therefore hit the assert. Even if we have enough space in the instruction section, we should check for a failed expansion of the stub section and bail out immediately: http://cr.openjdk.java.net/~thartmann/8130309/webrev.00/

Able to reproduce.

ILW=assert in debug-code;codecache exhaustion;none=MMH=>P3