# HG changeset patch # User mikael # Date 1462564821 25200 # Node ID b2a58604e0467aefc140100ac69fc931b7ead2ae # Parent ff63d43b048051b0ebf2711c8305c76651678522 8156088: Reintegrate 8153892: Handle unsafe access error directly in signal handler instead of going through a stub Reviewed-by: stuefe, dholmes diff -r ff63d43b0480 -r b2a58604e046 hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp --- a/hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp Fri May 06 06:23:29 2016 -0700 +++ b/hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp Fri May 06 13:00:21 2016 -0700 @@ -825,17 +825,6 @@ 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 @@ -3111,8 +3100,6 @@ 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(); diff -r ff63d43b0480 -r b2a58604e046 hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp --- a/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp Fri May 06 06:23:29 2016 -0700 +++ b/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp Fri May 06 13:00:21 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, 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,20 +64,6 @@ // ------------------------------------------------------------------------------------------------------------------------- // 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: @@ -746,62 +732,6 @@ 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 : // @@ -5380,9 +5310,6 @@ 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(); diff -r ff63d43b0480 -r b2a58604e046 hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp --- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp Fri May 06 06:23:29 2016 -0700 +++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp Fri May 06 13:00:21 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2016, 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,21 +63,6 @@ // ------------------------------------------------------------------------------------------------------------------------- // 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: @@ -623,27 +608,6 @@ } - //--------------------------------------------------------------------------- - // 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 @@ -3865,9 +3829,6 @@ // 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(); diff -r ff63d43b0480 -r b2a58604e046 hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp --- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp Fri May 06 06:23:29 2016 -0700 +++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp Fri May 06 13:00:21 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, 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,21 +61,6 @@ // 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: @@ -989,32 +974,6 @@ 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: @@ -5136,9 +5095,6 @@ 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(); diff -r ff63d43b0480 -r b2a58604e046 hotspot/src/cpu/zero/vm/stubGenerator_zero.cpp --- a/hotspot/src/cpu/zero/vm/stubGenerator_zero.cpp Fri May 06 06:23:29 2016 -0700 +++ b/hotspot/src/cpu/zero/vm/stubGenerator_zero.cpp Fri May 06 13:00:21 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, 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,10 +261,6 @@ 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() { diff -r ff63d43b0480 -r b2a58604e046 hotspot/src/os_cpu/aix_ppc/vm/os_aix_ppc.cpp --- a/hotspot/src/os_cpu/aix_ppc/vm/os_aix_ppc.cpp Fri May 06 06:23:29 2016 -0700 +++ b/hotspot/src/os_cpu/aix_ppc/vm/os_aix_ppc.cpp Fri May 06 13:00:21 2016 -0700 @@ -392,11 +392,9 @@ CodeBlob* cb = CodeCache::find_blob_unsafe(pc); CompiledMethod* nm = cb->as_compiled_method_or_null(); if (nm != NULL && nm->has_unsafe_access()) { - // 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); + address next_pc = pc + 4; + next_pc = SharedRuntime::handle_unsafe_access(thread, next_pc); + os::Aix::ucontext_set_pc(uc, next_pc); return 1; } } @@ -415,11 +413,9 @@ } else if (thread->thread_state() == _thread_in_vm && sig == SIGBUS && thread->doing_unsafe_access()) { - // 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); + address next_pc = pc + 4; + next_pc = SharedRuntime::handle_unsafe_access(thread, next_pc); + os::Aix::ucontext_set_pc(uc, next_pc); return 1; } } diff -r ff63d43b0480 -r b2a58604e046 hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp --- a/hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp Fri May 06 06:23:29 2016 -0700 +++ b/hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp Fri May 06 13:00:21 2016 -0700 @@ -584,7 +584,8 @@ 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()) { - stub = StubRoutines::handler_for_unsafe_access(); + address next_pc = Assembler::locate_next_instruction(pc); + stub = SharedRuntime::handle_unsafe_access(thread, next_pc); } } else @@ -655,7 +656,8 @@ } else if (thread->thread_state() == _thread_in_vm && sig == SIGBUS && /* info->si_code == BUS_OBJERR && */ thread->doing_unsafe_access()) { - stub = StubRoutines::handler_for_unsafe_access(); + address next_pc = Assembler::locate_next_instruction(pc); + stub = SharedRuntime::handle_unsafe_access(thread, next_pc); } // jni_fast_GetField can trap at certain pc's if a GC kicks in diff -r ff63d43b0480 -r b2a58604e046 hotspot/src/os_cpu/linux_aarch64/vm/os_linux_aarch64.cpp --- a/hotspot/src/os_cpu/linux_aarch64/vm/os_linux_aarch64.cpp Fri May 06 06:23:29 2016 -0700 +++ b/hotspot/src/os_cpu/linux_aarch64/vm/os_linux_aarch64.cpp Fri May 06 13:00:21 2016 -0700 @@ -226,23 +226,6 @@ 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, @@ -387,7 +370,8 @@ 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()) { - stub = handle_unsafe_access(thread, pc); + address next_pc = pc + NativeCall::instruction_size; + stub = SharedRuntime::handle_unsafe_access(thread, next_pc); } } else @@ -408,7 +392,8 @@ } else if (thread->thread_state() == _thread_in_vm && sig == SIGBUS && /* info->si_code == BUS_OBJERR && */ thread->doing_unsafe_access()) { - stub = handle_unsafe_access(thread, pc); + address next_pc = pc + NativeCall::instruction_size; + stub = SharedRuntime::handle_unsafe_access(thread, next_pc); } // jni_fast_GetField can trap at certain pc's if a GC kicks in diff -r ff63d43b0480 -r b2a58604e046 hotspot/src/os_cpu/linux_ppc/vm/os_linux_ppc.cpp --- a/hotspot/src/os_cpu/linux_ppc/vm/os_linux_ppc.cpp Fri May 06 06:23:29 2016 -0700 +++ b/hotspot/src/os_cpu/linux_ppc/vm/os_linux_ppc.cpp Fri May 06 13:00:21 2016 -0700 @@ -366,11 +366,9 @@ 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()) { - // 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); + address next_pc = pc + 4; + next_pc = SharedRuntime::handle_unsafe_access(thread, next_pc); + os::Linux::ucontext_set_pc(uc, next_pc); return true; } } @@ -385,10 +383,8 @@ } else if (thread->thread_state() == _thread_in_vm && sig == SIGBUS && thread->doing_unsafe_access()) { - // 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(); + address next_pc = pc + 4; + next_pc = SharedRuntime::handle_unsafe_access(thread, next_pc); os::Linux::ucontext_set_pc(uc, pc + 4); return true; } diff -r ff63d43b0480 -r b2a58604e046 hotspot/src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp --- a/hotspot/src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp Fri May 06 06:23:29 2016 -0700 +++ b/hotspot/src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp Fri May 06 13:00:21 2016 -0700 @@ -433,14 +433,14 @@ return false; } -inline static bool checkByteBuffer(address pc, address* stub) { +inline static bool checkByteBuffer(address pc, address npc, 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 = StubRoutines::handler_for_unsafe_access(); + *stub = SharedRuntime::handle_unsafe_access(thread, npc); return true; } return false; @@ -613,7 +613,7 @@ if (sig == SIGBUS && thread->thread_state() == _thread_in_vm && thread->doing_unsafe_access()) { - stub = StubRoutines::handler_for_unsafe_access(); + stub = SharedRuntime::handle_unsafe_access(thread, npc); } if (thread->thread_state() == _thread_in_Java) { @@ -625,7 +625,7 @@ break; } - if ((sig == SIGBUS) && checkByteBuffer(pc, &stub)) { + if ((sig == SIGBUS) && checkByteBuffer(pc, npc, &stub)) { break; } diff -r ff63d43b0480 -r b2a58604e046 hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp --- a/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp Fri May 06 06:23:29 2016 -0700 +++ b/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp Fri May 06 13:00:21 2016 -0700 @@ -420,7 +420,8 @@ 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()) { - stub = StubRoutines::handler_for_unsafe_access(); + address next_pc = Assembler::locate_next_instruction(pc); + stub = SharedRuntime::handle_unsafe_access(thread, next_pc); } } else @@ -469,7 +470,8 @@ } else if (thread->thread_state() == _thread_in_vm && sig == SIGBUS && /* info->si_code == BUS_OBJERR && */ thread->doing_unsafe_access()) { - stub = StubRoutines::handler_for_unsafe_access(); + address next_pc = Assembler::locate_next_instruction(pc); + stub = SharedRuntime::handle_unsafe_access(thread, next_pc); } // jni_fast_GetField can trap at certain pc's if a GC kicks in diff -r ff63d43b0480 -r b2a58604e046 hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp --- a/hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp Fri May 06 06:23:29 2016 -0700 +++ b/hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp Fri May 06 13:00:21 2016 -0700 @@ -441,7 +441,7 @@ if (thread->thread_state() == _thread_in_vm) { if (sig == SIGBUS && info->si_code == BUS_OBJERR && thread->doing_unsafe_access()) { - stub = StubRoutines::handler_for_unsafe_access(); + stub = SharedRuntime::handle_unsafe_access(thread, npc); } } @@ -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 = StubRoutines::handler_for_unsafe_access(); + stub = SharedRuntime::handle_unsafe_access(thread, npc); } } diff -r ff63d43b0480 -r b2a58604e046 hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp --- a/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp Fri May 06 06:23:29 2016 -0700 +++ b/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp Fri May 06 13:00:21 2016 -0700 @@ -503,7 +503,8 @@ if (thread->thread_state() == _thread_in_vm) { if (sig == SIGBUS && info->si_code == BUS_OBJERR && thread->doing_unsafe_access()) { - stub = StubRoutines::handler_for_unsafe_access(); + address next_pc = Assembler::locate_next_instruction(pc); + stub = SharedRuntime::handle_unsafe_access(thread, next_pc); } } @@ -520,7 +521,8 @@ if (cb != NULL) { CompiledMethod* nm = cb->as_compiled_method_or_null(); if (nm != NULL && nm->has_unsafe_access()) { - stub = StubRoutines::handler_for_unsafe_access(); + address next_pc = Assembler::locate_next_instruction(pc); + stub = SharedRuntime::handle_unsafe_access(thread, next_pc); } } } diff -r ff63d43b0480 -r b2a58604e046 hotspot/src/share/vm/runtime/sharedRuntime.cpp --- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp Fri May 06 06:23:29 2016 -0700 +++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp Fri May 06 13:00:21 2016 -0700 @@ -1762,6 +1762,21 @@ 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, diff -r ff63d43b0480 -r b2a58604e046 hotspot/src/share/vm/runtime/sharedRuntime.hpp --- a/hotspot/src/share/vm/runtime/sharedRuntime.hpp Fri May 06 06:23:29 2016 -0700 +++ b/hotspot/src/share/vm/runtime/sharedRuntime.hpp Fri May 06 13:00:21 2016 -0700 @@ -522,6 +522,8 @@ 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 diff -r ff63d43b0480 -r b2a58604e046 hotspot/src/share/vm/runtime/stubRoutines.cpp --- a/hotspot/src/share/vm/runtime/stubRoutines.cpp Fri May 06 06:23:29 2016 -0700 +++ b/hotspot/src/share/vm/runtime/stubRoutines.cpp Fri May 06 13:00:21 2016 -0700 @@ -55,7 +55,6 @@ 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; diff -r ff63d43b0480 -r b2a58604e046 hotspot/src/share/vm/runtime/stubRoutines.hpp --- a/hotspot/src/share/vm/runtime/stubRoutines.hpp Fri May 06 06:23:29 2016 -0700 +++ b/hotspot/src/share/vm/runtime/stubRoutines.hpp Fri May 06 13:00:21 2016 -0700 @@ -111,7 +111,6 @@ 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; @@ -288,10 +287,6 @@ 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; }