8156066: Backout JDK-8153892
authorctornqvi
Wed, 04 May 2016 15:32:26 -0400
changeset 38190 ff9ac612c723
parent 38187 f1879f6d7e63
child 38191 3c2ae71d9b63
8156066: Backout JDK-8153892 Reviewed-by: coleenp, mikael
hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp
hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp
hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp
hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp
hotspot/src/cpu/zero/vm/stubGenerator_zero.cpp
hotspot/src/os_cpu/aix_ppc/vm/os_aix_ppc.cpp
hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp
hotspot/src/os_cpu/linux_aarch64/vm/os_linux_aarch64.cpp
hotspot/src/os_cpu/linux_ppc/vm/os_linux_ppc.cpp
hotspot/src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp
hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp
hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp
hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp
hotspot/src/share/vm/runtime/sharedRuntime.cpp
hotspot/src/share/vm/runtime/sharedRuntime.hpp
hotspot/src/share/vm/runtime/stubRoutines.cpp
hotspot/src/share/vm/runtime/stubRoutines.hpp
--- a/hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp	Wed May 04 17:47:05 2016 +0300
+++ b/hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp	Wed May 04 15:32:26 2016 -0400
@@ -825,6 +825,17 @@
     return start;
   }
 
+  // The following routine generates a subroutine to throw an asynchronous
+  // UnknownError when an unsafe access gets a fault that could not be
+  // reasonably prevented by the programmer.  (Example: SIGBUS/OBJERR.)
+  //
+  address generate_handler_for_unsafe_access() {
+    StubCodeMark mark(this, "StubRoutines", "handler_for_unsafe_access");
+    address start = __ function_entry();
+    __ unimplemented("StubRoutines::handler_for_unsafe_access", 93);
+    return start;
+  }
+
 #if !defined(PRODUCT)
   // Wrapper which calls oopDesc::is_oop_or_null()
   // Only called by MacroAssembler::verify_oop
@@ -3100,6 +3111,8 @@
     StubRoutines::_throw_IncompatibleClassChangeError_entry= generate_throw_exception("IncompatibleClassChangeError throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_IncompatibleClassChangeError),  false);
     StubRoutines::_throw_NullPointerException_at_call_entry= generate_throw_exception("NullPointerException at call throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_NullPointerException_at_call), false);
 
+    StubRoutines::_handler_for_unsafe_access_entry         = generate_handler_for_unsafe_access();
+
     // support for verify_oop (must happen after universe_init)
     StubRoutines::_verify_oop_subroutine_entry             = generate_verify_oop();
 
--- a/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp	Wed May 04 17:47:05 2016 +0300
+++ b/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp	Wed May 04 15:32:26 2016 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -64,6 +64,20 @@
 // -------------------------------------------------------------------------------------------------------------------------
 // Stub Code definitions
 
+static address handle_unsafe_access() {
+  JavaThread* thread = JavaThread::current();
+  address pc  = thread->saved_exception_pc();
+  address npc = thread->saved_exception_npc();
+  // pc is the instruction which we must emulate
+  // doing a no-op is fine:  return garbage from the load
+
+  // request an async exception
+  thread->set_pending_unsafe_access_error();
+
+  // return address of next instruction to execute
+  return npc;
+}
+
 class StubGenerator: public StubCodeGenerator {
  private:
 
@@ -732,6 +746,62 @@
   Label _atomic_add_stub;  // called from other stubs
 
 
+  //------------------------------------------------------------------------------------------------------------------------
+  // The following routine generates a subroutine to throw an asynchronous
+  // UnknownError when an unsafe access gets a fault that could not be
+  // reasonably prevented by the programmer.  (Example: SIGBUS/OBJERR.)
+  //
+  // Arguments :
+  //
+  //      trapping PC:    O7
+  //
+  // Results:
+  //     posts an asynchronous exception, skips the trapping instruction
+  //
+
+  address generate_handler_for_unsafe_access() {
+    StubCodeMark mark(this, "StubRoutines", "handler_for_unsafe_access");
+    address start = __ pc();
+
+    const int preserve_register_words = (64 * 2);
+    Address preserve_addr(FP, (-preserve_register_words * wordSize) + STACK_BIAS);
+
+    Register Lthread = L7_thread_cache;
+    int i;
+
+    __ save_frame(0);
+    __ mov(G1, L1);
+    __ mov(G2, L2);
+    __ mov(G3, L3);
+    __ mov(G4, L4);
+    __ mov(G5, L5);
+    for (i = 0; i < 64; i += 2) {
+      __ stf(FloatRegisterImpl::D, as_FloatRegister(i), preserve_addr, i * wordSize);
+    }
+
+    address entry_point = CAST_FROM_FN_PTR(address, handle_unsafe_access);
+    BLOCK_COMMENT("call handle_unsafe_access");
+    __ call(entry_point, relocInfo::runtime_call_type);
+    __ delayed()->nop();
+
+    __ mov(L1, G1);
+    __ mov(L2, G2);
+    __ mov(L3, G3);
+    __ mov(L4, G4);
+    __ mov(L5, G5);
+    for (i = 0; i < 64; i += 2) {
+      __ ldf(FloatRegisterImpl::D, preserve_addr, as_FloatRegister(i), i * wordSize);
+    }
+
+    __ verify_thread();
+
+    __ jmp(O0, 0);
+    __ delayed()->restore();
+
+    return start;
+  }
+
+
   // Support for uint StubRoutine::Sparc::partial_subtype_check( Klass sub, Klass super );
   // Arguments :
   //
@@ -5310,6 +5380,9 @@
     StubRoutines::_throw_IncompatibleClassChangeError_entry= generate_throw_exception("IncompatibleClassChangeError throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_IncompatibleClassChangeError));
     StubRoutines::_throw_NullPointerException_at_call_entry= generate_throw_exception("NullPointerException at call throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_NullPointerException_at_call));
 
+    StubRoutines::_handler_for_unsafe_access_entry =
+      generate_handler_for_unsafe_access();
+
     // support for verify_oop (must happen after universe_init)
     StubRoutines::_verify_oop_subroutine_entry     = generate_verify_oop_subroutine();
 
--- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp	Wed May 04 17:47:05 2016 +0300
+++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp	Wed May 04 15:32:26 2016 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -63,6 +63,21 @@
 // -------------------------------------------------------------------------------------------------------------------------
 // Stub Code definitions
 
+static address handle_unsafe_access() {
+  JavaThread* thread = JavaThread::current();
+  address pc  = thread->saved_exception_pc();
+  // pc is the instruction which we must emulate
+  // doing a no-op is fine:  return garbage from the load
+  // therefore, compute npc
+  address npc = Assembler::locate_next_instruction(pc);
+
+  // request an async exception
+  thread->set_pending_unsafe_access_error();
+
+  // return address of next instruction to execute
+  return npc;
+}
+
 class StubGenerator: public StubCodeGenerator {
  private:
 
@@ -608,6 +623,27 @@
   }
 
 
+  //---------------------------------------------------------------------------
+  // The following routine generates a subroutine to throw an asynchronous
+  // UnknownError when an unsafe access gets a fault that could not be
+  // reasonably prevented by the programmer.  (Example: SIGBUS/OBJERR.)
+  address generate_handler_for_unsafe_access() {
+    StubCodeMark mark(this, "StubRoutines", "handler_for_unsafe_access");
+    address start = __ pc();
+
+    __ push(0);                       // hole for return address-to-be
+    __ pusha();                       // push registers
+    Address next_pc(rsp, RegisterImpl::number_of_registers * BytesPerWord);
+    BLOCK_COMMENT("call handle_unsafe_access");
+    __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, handle_unsafe_access)));
+    __ movptr(next_pc, rax);          // stuff next address
+    __ popa();
+    __ ret(0);                        // jump to next address
+
+    return start;
+  }
+
+
   //----------------------------------------------------------------------------------------------------
   // Non-destructive plausibility checks for oops
 
@@ -3829,6 +3865,9 @@
     // These are currently used by Solaris/Intel
     StubRoutines::_atomic_xchg_entry            = generate_atomic_xchg();
 
+    StubRoutines::_handler_for_unsafe_access_entry =
+      generate_handler_for_unsafe_access();
+
     // platform dependent
     create_control_words();
 
--- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp	Wed May 04 17:47:05 2016 +0300
+++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp	Wed May 04 15:32:26 2016 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -61,6 +61,21 @@
 
 // Stub Code definitions
 
+static address handle_unsafe_access() {
+  JavaThread* thread = JavaThread::current();
+  address pc = thread->saved_exception_pc();
+  // pc is the instruction which we must emulate
+  // doing a no-op is fine:  return garbage from the load
+  // therefore, compute npc
+  address npc = Assembler::locate_next_instruction(pc);
+
+  // request an async exception
+  thread->set_pending_unsafe_access_error();
+
+  // return address of next instruction to execute
+  return npc;
+}
+
 class StubGenerator: public StubCodeGenerator {
  private:
 
@@ -974,6 +989,32 @@
     return start;
   }
 
+  // The following routine generates a subroutine to throw an
+  // asynchronous UnknownError when an unsafe access gets a fault that
+  // could not be reasonably prevented by the programmer.  (Example:
+  // SIGBUS/OBJERR.)
+  address generate_handler_for_unsafe_access() {
+    StubCodeMark mark(this, "StubRoutines", "handler_for_unsafe_access");
+    address start = __ pc();
+
+    __ push(0);                       // hole for return address-to-be
+    __ pusha();                       // push registers
+    Address next_pc(rsp, RegisterImpl::number_of_registers * BytesPerWord);
+
+    // FIXME: this probably needs alignment logic
+
+    __ subptr(rsp, frame::arg_reg_save_area_bytes);
+    BLOCK_COMMENT("call handle_unsafe_access");
+    __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, handle_unsafe_access)));
+    __ addptr(rsp, frame::arg_reg_save_area_bytes);
+
+    __ movptr(next_pc, rax);          // stuff next address
+    __ popa();
+    __ ret(0);                        // jump to next address
+
+    return start;
+  }
+
   // Non-destructive plausibility checks for oops
   //
   // Arguments:
@@ -5095,6 +5136,9 @@
     StubRoutines::_atomic_add_ptr_entry      = generate_atomic_add_ptr();
     StubRoutines::_fence_entry               = generate_orderaccess_fence();
 
+    StubRoutines::_handler_for_unsafe_access_entry =
+      generate_handler_for_unsafe_access();
+
     // platform dependent
     StubRoutines::x86::_get_previous_fp_entry = generate_get_previous_fp();
     StubRoutines::x86::_get_previous_sp_entry = generate_get_previous_sp();
--- a/hotspot/src/cpu/zero/vm/stubGenerator_zero.cpp	Wed May 04 17:47:05 2016 +0300
+++ b/hotspot/src/cpu/zero/vm/stubGenerator_zero.cpp	Wed May 04 15:32:26 2016 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
  * Copyright 2007, 2008, 2010, 2015 Red Hat, Inc.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
@@ -261,6 +261,10 @@
     StubRoutines::_atomic_add_entry          = ShouldNotCallThisStub();
     StubRoutines::_atomic_add_ptr_entry      = ShouldNotCallThisStub();
     StubRoutines::_fence_entry               = ShouldNotCallThisStub();
+
+    // amd64 does this here, sparc does it in generate_all()
+    StubRoutines::_handler_for_unsafe_access_entry =
+      ShouldNotCallThisStub();
   }
 
   void generate_all() {
--- a/hotspot/src/os_cpu/aix_ppc/vm/os_aix_ppc.cpp	Wed May 04 17:47:05 2016 +0300
+++ b/hotspot/src/os_cpu/aix_ppc/vm/os_aix_ppc.cpp	Wed May 04 15:32:26 2016 -0400
@@ -392,9 +392,11 @@
         CodeBlob* cb = CodeCache::find_blob_unsafe(pc);
         CompiledMethod* nm = cb->as_compiled_method_or_null();
         if (nm != NULL && nm->has_unsafe_access()) {
-          address next_pc = pc + 4;
-          next_pc = SharedRuntime::handle_unsafe_access(thread, next_pc);
-          os::Aix::ucontext_set_pc(uc, next_pc);
+          // We don't really need a stub here! Just set the pending exeption and
+          // continue at the next instruction after the faulting read. Returning
+          // garbage from this read is ok.
+          thread->set_pending_unsafe_access_error();
+          os::Aix::ucontext_set_pc(uc, pc + 4);
           return 1;
         }
       }
@@ -413,9 +415,11 @@
       }
       else if (thread->thread_state() == _thread_in_vm &&
                sig == SIGBUS && thread->doing_unsafe_access()) {
-        address next_pc = pc + 4;
-        next_pc = SharedRuntime::handle_unsafe_access(thread, next_pc);
-        os::Aix::ucontext_set_pc(uc, next_pc);
+        // We don't really need a stub here! Just set the pending exeption and
+        // continue at the next instruction after the faulting read. Returning
+        // garbage from this read is ok.
+        thread->set_pending_unsafe_access_error();
+        os::Aix::ucontext_set_pc(uc, pc + 4);
         return 1;
       }
     }
--- a/hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp	Wed May 04 17:47:05 2016 +0300
+++ b/hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp	Wed May 04 15:32:26 2016 -0400
@@ -584,8 +584,7 @@
         CodeBlob* cb = CodeCache::find_blob_unsafe(pc);
         CompiledMethod* nm = (cb != NULL) ? cb->as_compiled_method_or_null() : NULL;
         if (nm != NULL && nm->has_unsafe_access()) {
-          address next_pc = Assembler::locate_next_instruction(pc);
-          stub = SharedRuntime::handle_unsafe_access(thread, next_pc);
+          stub = StubRoutines::handler_for_unsafe_access();
         }
       }
       else
@@ -656,8 +655,7 @@
     } else if (thread->thread_state() == _thread_in_vm &&
                sig == SIGBUS && /* info->si_code == BUS_OBJERR && */
                thread->doing_unsafe_access()) {
-        address next_pc = Assembler::locate_next_instruction(pc);
-        stub = SharedRuntime::handle_unsafe_access(thread, next_pc);
+        stub = StubRoutines::handler_for_unsafe_access();
     }
 
     // jni_fast_Get<Primitive>Field can trap at certain pc's if a GC kicks in
--- a/hotspot/src/os_cpu/linux_aarch64/vm/os_linux_aarch64.cpp	Wed May 04 17:47:05 2016 +0300
+++ b/hotspot/src/os_cpu/linux_aarch64/vm/os_linux_aarch64.cpp	Wed May 04 15:32:26 2016 -0400
@@ -226,6 +226,23 @@
 extern "C" void FetchNResume () ;
 #endif
 
+// An operation in Unsafe has faulted.  We're going to return to the
+// instruction after the faulting load or store.  We also set
+// pending_unsafe_access_error so that at some point in the future our
+// user will get a helpful message.
+static address handle_unsafe_access(JavaThread* thread, address pc) {
+  // pc is the instruction which we must emulate
+  // doing a no-op is fine:  return garbage from the load
+  // therefore, compute npc
+  address npc = pc + NativeCall::instruction_size;
+
+  // request an async exception
+  thread->set_pending_unsafe_access_error();
+
+  // return address of next instruction to execute
+  return npc;
+}
+
 extern "C" JNIEXPORT int
 JVM_handle_linux_signal(int sig,
                         siginfo_t* info,
@@ -370,8 +387,7 @@
         CodeBlob* cb = CodeCache::find_blob_unsafe(pc);
         CompiledMethod* nm = (cb != NULL) ? cb->as_compiled_method_or_null() : NULL;
         if (nm != NULL && nm->has_unsafe_access()) {
-          address next_pc = pc + NativeCall::instruction_size;
-          stub = SharedRuntime::handle_unsafe_access(thread, next_pc);
+          stub = handle_unsafe_access(thread, pc);
         }
       }
       else
@@ -392,8 +408,7 @@
     } else if (thread->thread_state() == _thread_in_vm &&
                sig == SIGBUS && /* info->si_code == BUS_OBJERR && */
                thread->doing_unsafe_access()) {
-      address next_pc = pc + NativeCall::instruction_size;
-      stub = SharedRuntime::handle_unsafe_access(thread, next_pc);
+        stub = handle_unsafe_access(thread, pc);
     }
 
     // jni_fast_Get<Primitive>Field can trap at certain pc's if a GC kicks in
--- a/hotspot/src/os_cpu/linux_ppc/vm/os_linux_ppc.cpp	Wed May 04 17:47:05 2016 +0300
+++ b/hotspot/src/os_cpu/linux_ppc/vm/os_linux_ppc.cpp	Wed May 04 15:32:26 2016 -0400
@@ -366,9 +366,11 @@
         CodeBlob* cb = CodeCache::find_blob_unsafe(pc);
         CompiledMethod* nm = (cb != NULL) ? cb->as_compiled_method_or_null() : NULL;
         if (nm != NULL && nm->has_unsafe_access()) {
-          address next_pc = pc + 4;
-          next_pc = SharedRuntime::handle_unsafe_access(thread, next_pc);
-          os::Linux::ucontext_set_pc(uc, next_pc);
+          // We don't really need a stub here! Just set the pending exeption and
+          // continue at the next instruction after the faulting read. Returning
+          // garbage from this read is ok.
+          thread->set_pending_unsafe_access_error();
+          os::Linux::ucontext_set_pc(uc, pc + 4);
           return true;
         }
       }
@@ -383,8 +385,10 @@
       }
       else if (thread->thread_state() == _thread_in_vm &&
                sig == SIGBUS && thread->doing_unsafe_access()) {
-        address next_pc = pc + 4;
-        next_pc = SharedRuntime::handle_unsafe_access(thread, next_pc);
+        // We don't really need a stub here! Just set the pending exeption and
+        // continue at the next instruction after the faulting read. Returning
+        // garbage from this read is ok.
+        thread->set_pending_unsafe_access_error();
         os::Linux::ucontext_set_pc(uc, pc + 4);
         return true;
       }
--- a/hotspot/src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp	Wed May 04 17:47:05 2016 +0300
+++ b/hotspot/src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp	Wed May 04 15:32:26 2016 -0400
@@ -433,14 +433,14 @@
   return false;
 }
 
-inline static bool checkByteBuffer(address pc, address npc, address* stub) {
+inline static bool checkByteBuffer(address pc, address* stub) {
   // BugId 4454115: A read from a MappedByteBuffer can fault
   // here if the underlying file has been truncated.
   // Do not crash the VM in such a case.
   CodeBlob* cb = CodeCache::find_blob_unsafe(pc);
   CompiledMethod* nm = cb->as_compiled_method_or_null();
   if (nm != NULL && nm->has_unsafe_access()) {
-    *stub = SharedRuntime::handle_unsafe_access(thread, npc);
+    *stub = StubRoutines::handler_for_unsafe_access();
     return true;
   }
   return false;
@@ -613,7 +613,7 @@
     if (sig == SIGBUS &&
         thread->thread_state() == _thread_in_vm &&
         thread->doing_unsafe_access()) {
-      stub = SharedRuntime::handle_unsafe_access(thread, npc);
+      stub = StubRoutines::handler_for_unsafe_access();
     }
 
     if (thread->thread_state() == _thread_in_Java) {
@@ -625,7 +625,7 @@
           break;
         }
 
-        if ((sig == SIGBUS) && checkByteBuffer(pc, npc, &stub)) {
+        if ((sig == SIGBUS) && checkByteBuffer(pc, &stub)) {
           break;
         }
 
--- a/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp	Wed May 04 17:47:05 2016 +0300
+++ b/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp	Wed May 04 15:32:26 2016 -0400
@@ -420,8 +420,7 @@
         CodeBlob* cb = CodeCache::find_blob_unsafe(pc);
         CompiledMethod* nm = (cb != NULL) ? cb->as_compiled_method_or_null() : NULL;
         if (nm != NULL && nm->has_unsafe_access()) {
-          address next_pc = Assembler::locate_next_instruction(pc);
-          stub = SharedRuntime::handle_unsafe_access(thread, next_pc);
+          stub = StubRoutines::handler_for_unsafe_access();
         }
       }
       else
@@ -470,8 +469,7 @@
     } else if (thread->thread_state() == _thread_in_vm &&
                sig == SIGBUS && /* info->si_code == BUS_OBJERR && */
                thread->doing_unsafe_access()) {
-        address next_pc = Assembler::locate_next_instruction(pc);
-        stub = SharedRuntime::handle_unsafe_access(thread, next_pc);
+        stub = StubRoutines::handler_for_unsafe_access();
     }
 
     // jni_fast_Get<Primitive>Field can trap at certain pc's if a GC kicks in
--- a/hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp	Wed May 04 17:47:05 2016 +0300
+++ b/hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp	Wed May 04 15:32:26 2016 -0400
@@ -441,7 +441,7 @@
 
     if (thread->thread_state() == _thread_in_vm) {
       if (sig == SIGBUS && info->si_code == BUS_OBJERR && thread->doing_unsafe_access()) {
-        stub = SharedRuntime::handle_unsafe_access(thread, npc);
+        stub = StubRoutines::handler_for_unsafe_access();
       }
     }
 
@@ -480,7 +480,7 @@
         CodeBlob* cb = CodeCache::find_blob_unsafe(pc);
         CompiledMethod* nm = cb->as_compiled_method_or_null();
         if (nm != NULL && nm->has_unsafe_access()) {
-          stub = SharedRuntime::handle_unsafe_access(thread, npc);
+          stub = StubRoutines::handler_for_unsafe_access();
         }
       }
 
--- a/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp	Wed May 04 17:47:05 2016 +0300
+++ b/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp	Wed May 04 15:32:26 2016 -0400
@@ -503,8 +503,7 @@
 
     if (thread->thread_state() == _thread_in_vm) {
       if (sig == SIGBUS && info->si_code == BUS_OBJERR && thread->doing_unsafe_access()) {
-        address next_pc = Assembler::locate_next_instruction(pc);
-        stub = SharedRuntime::handle_unsafe_access(thread, next_pc);
+        stub = StubRoutines::handler_for_unsafe_access();
       }
     }
 
@@ -521,8 +520,7 @@
         if (cb != NULL) {
           CompiledMethod* nm = cb->as_compiled_method_or_null();
           if (nm != NULL && nm->has_unsafe_access()) {
-            address next_pc = Assembler::locate_next_instruction(pc);
-            stub = SharedRuntime::handle_unsafe_access(thread, next_pc);
+            stub = StubRoutines::handler_for_unsafe_access();
           }
         }
       }
--- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp	Wed May 04 17:47:05 2016 +0300
+++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp	Wed May 04 15:32:26 2016 -0400
@@ -1762,21 +1762,6 @@
   return callee_method;
 }
 
-address SharedRuntime::handle_unsafe_access(JavaThread* thread, address next_pc) {
-  // The faulting unsafe accesses should be changed to throw the error
-  // synchronously instead. Meanwhile the faulting instruction will be
-  // skipped over (effectively turning it into a no-op) and an
-  // asynchronous exception will be raised which the thread will
-  // handle at a later point. If the instruction is a load it will
-  // return garbage.
-
-  // Request an async exception.
-  thread->set_pending_unsafe_access_error();
-
-  // Return address of next instruction to execute.
-  return next_pc;
-}
-
 #ifdef ASSERT
 void SharedRuntime::check_member_name_argument_is_last_argument(const methodHandle& method,
                                                                 const BasicType* sig_bt,
--- a/hotspot/src/share/vm/runtime/sharedRuntime.hpp	Wed May 04 17:47:05 2016 +0300
+++ b/hotspot/src/share/vm/runtime/sharedRuntime.hpp	Wed May 04 15:32:26 2016 -0400
@@ -522,8 +522,6 @@
   static address handle_wrong_method_abstract(JavaThread* thread);
   static address handle_wrong_method_ic_miss(JavaThread* thread);
 
-  static address handle_unsafe_access(JavaThread* thread, address next_pc);
-
 #ifndef PRODUCT
 
   // Collect and print inline cache miss statistics
--- a/hotspot/src/share/vm/runtime/stubRoutines.cpp	Wed May 04 17:47:05 2016 +0300
+++ b/hotspot/src/share/vm/runtime/stubRoutines.cpp	Wed May 04 15:32:26 2016 -0400
@@ -55,6 +55,7 @@
 address StubRoutines::_throw_NullPointerException_at_call_entry = NULL;
 address StubRoutines::_throw_StackOverflowError_entry           = NULL;
 address StubRoutines::_throw_delayed_StackOverflowError_entry   = NULL;
+address StubRoutines::_handler_for_unsafe_access_entry          = NULL;
 jint    StubRoutines::_verify_oop_count                         = 0;
 address StubRoutines::_verify_oop_subroutine_entry              = NULL;
 address StubRoutines::_atomic_xchg_entry                        = NULL;
--- a/hotspot/src/share/vm/runtime/stubRoutines.hpp	Wed May 04 17:47:05 2016 +0300
+++ b/hotspot/src/share/vm/runtime/stubRoutines.hpp	Wed May 04 15:32:26 2016 -0400
@@ -111,6 +111,7 @@
   static address _throw_NullPointerException_at_call_entry;
   static address _throw_StackOverflowError_entry;
   static address _throw_delayed_StackOverflowError_entry;
+  static address _handler_for_unsafe_access_entry;
 
   static address _atomic_xchg_entry;
   static address _atomic_xchg_ptr_entry;
@@ -287,6 +288,10 @@
   static address throw_StackOverflowError_entry()          { return _throw_StackOverflowError_entry; }
   static address throw_delayed_StackOverflowError_entry()  { return _throw_delayed_StackOverflowError_entry; }
 
+  // Exceptions during unsafe access - should throw Java exception rather
+  // than crash.
+  static address handler_for_unsafe_access()               { return _handler_for_unsafe_access_entry; }
+
   static address atomic_xchg_entry()                       { return _atomic_xchg_entry; }
   static address atomic_xchg_ptr_entry()                   { return _atomic_xchg_ptr_entry; }
   static address atomic_store_entry()                      { return _atomic_store_entry; }