[9] RFR(S): 8150821: Crash with assert(!((nmethod*)_cb)->is_deopt_pc(_pc)) failed: invariant broken

Tobias Hartmann tobias.hartmann at oracle.com
Wed Mar 23 13:27:55 UTC 2016


please review the following patch:

We crash on SPARC in the frame constructor called for compiled code in os::Solaris::get_frame_at_stack_banging_point() (line 280). This code was introduced by "JEP 270: Reserved Stack Areas for Critical Sections" [1] to get the stack banging Java frame and scan the call stack for methods that are annotated with ReservedStackAccess (those are allowed to continue execution). The StackOverflowException we are handling was thrown here:

 Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
 V  [libjvm.so+0x14d8cc4]  JVM_handle_solaris_signal+0x4f4
 V  [libjvm.so+0x14d18c4]  signalHandler+0x24
 C  [libc.so.1+0xe26b4]  __sighndlr+0x14
 C  [libc.so.1+0xd5ce8]  call_user_handler+0x36c
 C  [libc.so.1+0xd5f18]  sigacthandler+0x64
 J 277 C1 java.lang.Throwable.fillInStackTrace()Ljava/lang/Throwable; (54 bytes) @ 0xffffffff690cfdec [0xffffffff690cfda0+0x000000000000004c]
 J 1535 C1 java.lang.ReflectiveOperationException.<init>(Ljava/lang/Throwable;)V (6 bytes) @ 0xffffffff69448d90 [0xffffffff69448d00+0x0000000000000090]
 J 1534 C2 java.lang.reflect.InvocationTargetException.<init>(Ljava/lang/Throwable;)V (14 bytes) @ 0xffffffff704afe3c [0xffffffff704afe00+0x000000000000003c]
 j  sun.reflect.GeneratedMethodAccessor1.invoke(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;+69
 J 826 C2 sun.reflect.DelegatingMethodAccessorImpl.invoke(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object; (10 bytes) @ 0xffffffff7045d5b8 [0xffffffff7045d560+0x0000000000000058]
 J 817 C1 java.lang.reflect.Method.invoke(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object; (62 bytes) @ 0xffffffff692353f4 [0xffffffff692352c0+0x0000000000000134]
 J 1532 C2 sun.reflect.GeneratedMethodAccessor1.invoke(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object; (73 bytes) @ 0xffffffff704af838 [0xffffffff704af7a0+0x0000000000000098]
 J 826 C2 sun.reflect.DelegatingMethodAccessorImpl.invoke(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object; (10 bytes) @ 0xffffffff7045d5b8 [0xffffffff7045d560+0x0000000000000058]

The offending frame returned by os::fetch_frame_from_ucontext() in line 279 is "java.lang.Throwable::fillInStackTrace()". In line 280, we try to create the sender frame "java.lang.ReflectiveOperationException::<init>()" by using the deficient frame constructor. We hit the assert in frame::init() because the frame was deoptimized and the PC was patched. The frame was deoptimized because we run with -XX:+DeoptimizeALot.

For deoptimized frames we use nm->get_original_pc(frame) to get the original/unpatched PC. In contrast to x86, on SPARC the saved PC is stored at a variable distance from the SP (see comment in frame_sparc.hpp [2]). To determine the original PC for a deoptimized frame, we need information about the sender frame: nmethod::orig_pc_addr() is using the original SP "frame::unextended_sp()" (before any extension by an interpreted callee) which depends on "Frame::_sp_adjustment_by_callee". This value is not set by the constructor because there is no information about the callee frame.

I fixed this by using a different constructor that fully initializes the frame.

Tested manually with failing test and JRPT.


[1] https://bugs.openjdk.java.net/browse/JDK-8046936
[2] Comment in frame_sparc.hpp:
  // Note:  On SPARC, unlike Intel, the saved PC for a stack frame
  // is stored at a __variable__ distance from that frame's SP.
  // (In fact, it may be in the register save area of the callee frame,
  // but that fact need not bother us.)  Thus, we must store the
  // address of that saved PC explicitly.

More information about the hotspot-dev mailing list