8156088: Reintegrate 8153892: Handle unsafe access error directly in signal handler instead of going through a stub

Reviewed-by: stuefe, dholmes
This commit is contained in:
Mikael Vidstedt 2016-05-06 13:00:21 -07:00
parent 4247e12f6b
commit 0588e8953c
17 changed files with 54 additions and 233 deletions

View file

@ -825,17 +825,6 @@ class StubGenerator: public StubCodeGenerator {
return start; 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) #if !defined(PRODUCT)
// Wrapper which calls oopDesc::is_oop_or_null() // Wrapper which calls oopDesc::is_oop_or_null()
// Only called by MacroAssembler::verify_oop // Only called by MacroAssembler::verify_oop
@ -3111,8 +3100,6 @@ class StubGenerator: public StubCodeGenerator {
StubRoutines::_throw_IncompatibleClassChangeError_entry= generate_throw_exception("IncompatibleClassChangeError throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_IncompatibleClassChangeError), false); 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::_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) // support for verify_oop (must happen after universe_init)
StubRoutines::_verify_oop_subroutine_entry = generate_verify_oop(); StubRoutines::_verify_oop_subroutine_entry = generate_verify_oop();

View file

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -64,20 +64,6 @@ static const Register& Lstub_temp = L2;
// ------------------------------------------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------------------------------------------
// Stub Code definitions // 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 { class StubGenerator: public StubCodeGenerator {
private: private:
@ -746,62 +732,6 @@ class StubGenerator: public StubCodeGenerator {
Label _atomic_add_stub; // called from other stubs 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 ); // Support for uint StubRoutine::Sparc::partial_subtype_check( Klass sub, Klass super );
// Arguments : // Arguments :
// //
@ -5380,9 +5310,6 @@ class StubGenerator: public StubCodeGenerator {
StubRoutines::_throw_IncompatibleClassChangeError_entry= generate_throw_exception("IncompatibleClassChangeError throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_IncompatibleClassChangeError)); 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::_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) // support for verify_oop (must happen after universe_init)
StubRoutines::_verify_oop_subroutine_entry = generate_verify_oop_subroutine(); StubRoutines::_verify_oop_subroutine_entry = generate_verify_oop_subroutine();

View file

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -63,21 +63,6 @@ const int FPU_CNTRL_WRD_MASK = 0xFFFF;
// ------------------------------------------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------------------------------------------
// Stub Code definitions // 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 { class StubGenerator: public StubCodeGenerator {
private: private:
@ -623,27 +608,6 @@ class StubGenerator: public StubCodeGenerator {
} }
//---------------------------------------------------------------------------
// 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 // Non-destructive plausibility checks for oops
@ -3865,9 +3829,6 @@ class StubGenerator: public StubCodeGenerator {
// These are currently used by Solaris/Intel // These are currently used by Solaris/Intel
StubRoutines::_atomic_xchg_entry = generate_atomic_xchg(); StubRoutines::_atomic_xchg_entry = generate_atomic_xchg();
StubRoutines::_handler_for_unsafe_access_entry =
generate_handler_for_unsafe_access();
// platform dependent // platform dependent
create_control_words(); create_control_words();

View file

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -61,21 +61,6 @@ const int MXCSR_MASK = 0xFFC0; // Mask out any pending exceptions
// Stub Code definitions // 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 { class StubGenerator: public StubCodeGenerator {
private: private:
@ -989,32 +974,6 @@ class StubGenerator: public StubCodeGenerator {
return start; 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 // Non-destructive plausibility checks for oops
// //
// Arguments: // Arguments:
@ -5136,9 +5095,6 @@ class StubGenerator: public StubCodeGenerator {
StubRoutines::_atomic_add_ptr_entry = generate_atomic_add_ptr(); StubRoutines::_atomic_add_ptr_entry = generate_atomic_add_ptr();
StubRoutines::_fence_entry = generate_orderaccess_fence(); StubRoutines::_fence_entry = generate_orderaccess_fence();
StubRoutines::_handler_for_unsafe_access_entry =
generate_handler_for_unsafe_access();
// platform dependent // platform dependent
StubRoutines::x86::_get_previous_fp_entry = generate_get_previous_fp(); StubRoutines::x86::_get_previous_fp_entry = generate_get_previous_fp();
StubRoutines::x86::_get_previous_sp_entry = generate_get_previous_sp(); StubRoutines::x86::_get_previous_sp_entry = generate_get_previous_sp();

View file

@ -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. * Copyright 2007, 2008, 2010, 2015 Red Hat, Inc.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
@ -261,10 +261,6 @@ class StubGenerator: public StubCodeGenerator {
StubRoutines::_atomic_add_entry = ShouldNotCallThisStub(); StubRoutines::_atomic_add_entry = ShouldNotCallThisStub();
StubRoutines::_atomic_add_ptr_entry = ShouldNotCallThisStub(); StubRoutines::_atomic_add_ptr_entry = ShouldNotCallThisStub();
StubRoutines::_fence_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() { void generate_all() {

View file

@ -392,11 +392,9 @@ JVM_handle_aix_signal(int sig, siginfo_t* info, void* ucVoid, int abort_if_unrec
CodeBlob* cb = CodeCache::find_blob_unsafe(pc); CodeBlob* cb = CodeCache::find_blob_unsafe(pc);
CompiledMethod* nm = cb->as_compiled_method_or_null(); CompiledMethod* nm = cb->as_compiled_method_or_null();
if (nm != NULL && nm->has_unsafe_access()) { if (nm != NULL && nm->has_unsafe_access()) {
// We don't really need a stub here! Just set the pending exeption and address next_pc = pc + 4;
// continue at the next instruction after the faulting read. Returning next_pc = SharedRuntime::handle_unsafe_access(thread, next_pc);
// garbage from this read is ok. os::Aix::ucontext_set_pc(uc, next_pc);
thread->set_pending_unsafe_access_error();
os::Aix::ucontext_set_pc(uc, pc + 4);
return 1; return 1;
} }
} }
@ -415,11 +413,9 @@ JVM_handle_aix_signal(int sig, siginfo_t* info, void* ucVoid, int abort_if_unrec
} }
else if (thread->thread_state() == _thread_in_vm && else if (thread->thread_state() == _thread_in_vm &&
sig == SIGBUS && thread->doing_unsafe_access()) { sig == SIGBUS && thread->doing_unsafe_access()) {
// We don't really need a stub here! Just set the pending exeption and address next_pc = pc + 4;
// continue at the next instruction after the faulting read. Returning next_pc = SharedRuntime::handle_unsafe_access(thread, next_pc);
// garbage from this read is ok. os::Aix::ucontext_set_pc(uc, next_pc);
thread->set_pending_unsafe_access_error();
os::Aix::ucontext_set_pc(uc, pc + 4);
return 1; return 1;
} }
} }

View file

@ -584,7 +584,8 @@ JVM_handle_bsd_signal(int sig,
CodeBlob* cb = CodeCache::find_blob_unsafe(pc); CodeBlob* cb = CodeCache::find_blob_unsafe(pc);
CompiledMethod* nm = (cb != NULL) ? cb->as_compiled_method_or_null() : NULL; CompiledMethod* nm = (cb != NULL) ? cb->as_compiled_method_or_null() : NULL;
if (nm != NULL && nm->has_unsafe_access()) { 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 else
@ -655,7 +656,8 @@ JVM_handle_bsd_signal(int sig,
} else if (thread->thread_state() == _thread_in_vm && } else if (thread->thread_state() == _thread_in_vm &&
sig == SIGBUS && /* info->si_code == BUS_OBJERR && */ sig == SIGBUS && /* info->si_code == BUS_OBJERR && */
thread->doing_unsafe_access()) { 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_Get<Primitive>Field can trap at certain pc's if a GC kicks in // jni_fast_Get<Primitive>Field can trap at certain pc's if a GC kicks in

View file

@ -226,23 +226,6 @@ extern "C" void FetchNPFI () ;
extern "C" void FetchNResume () ; extern "C" void FetchNResume () ;
#endif #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 extern "C" JNIEXPORT int
JVM_handle_linux_signal(int sig, JVM_handle_linux_signal(int sig,
siginfo_t* info, siginfo_t* info,
@ -387,7 +370,8 @@ JVM_handle_linux_signal(int sig,
CodeBlob* cb = CodeCache::find_blob_unsafe(pc); CodeBlob* cb = CodeCache::find_blob_unsafe(pc);
CompiledMethod* nm = (cb != NULL) ? cb->as_compiled_method_or_null() : NULL; CompiledMethod* nm = (cb != NULL) ? cb->as_compiled_method_or_null() : NULL;
if (nm != NULL && nm->has_unsafe_access()) { 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 else
@ -408,7 +392,8 @@ JVM_handle_linux_signal(int sig,
} else if (thread->thread_state() == _thread_in_vm && } else if (thread->thread_state() == _thread_in_vm &&
sig == SIGBUS && /* info->si_code == BUS_OBJERR && */ sig == SIGBUS && /* info->si_code == BUS_OBJERR && */
thread->doing_unsafe_access()) { 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_Get<Primitive>Field can trap at certain pc's if a GC kicks in // jni_fast_Get<Primitive>Field can trap at certain pc's if a GC kicks in

View file

@ -366,11 +366,9 @@ JVM_handle_linux_signal(int sig,
CodeBlob* cb = CodeCache::find_blob_unsafe(pc); CodeBlob* cb = CodeCache::find_blob_unsafe(pc);
CompiledMethod* nm = (cb != NULL) ? cb->as_compiled_method_or_null() : NULL; CompiledMethod* nm = (cb != NULL) ? cb->as_compiled_method_or_null() : NULL;
if (nm != NULL && nm->has_unsafe_access()) { if (nm != NULL && nm->has_unsafe_access()) {
// We don't really need a stub here! Just set the pending exeption and address next_pc = pc + 4;
// continue at the next instruction after the faulting read. Returning next_pc = SharedRuntime::handle_unsafe_access(thread, next_pc);
// garbage from this read is ok. os::Linux::ucontext_set_pc(uc, next_pc);
thread->set_pending_unsafe_access_error();
os::Linux::ucontext_set_pc(uc, pc + 4);
return true; return true;
} }
} }
@ -385,10 +383,8 @@ JVM_handle_linux_signal(int sig,
} }
else if (thread->thread_state() == _thread_in_vm && else if (thread->thread_state() == _thread_in_vm &&
sig == SIGBUS && thread->doing_unsafe_access()) { sig == SIGBUS && thread->doing_unsafe_access()) {
// We don't really need a stub here! Just set the pending exeption and address next_pc = pc + 4;
// continue at the next instruction after the faulting read. Returning next_pc = SharedRuntime::handle_unsafe_access(thread, next_pc);
// garbage from this read is ok.
thread->set_pending_unsafe_access_error();
os::Linux::ucontext_set_pc(uc, pc + 4); os::Linux::ucontext_set_pc(uc, pc + 4);
return true; return true;
} }

View file

@ -433,14 +433,14 @@ inline static bool checkPollingPage(address pc, address fault, address* stub) {
return false; 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 // BugId 4454115: A read from a MappedByteBuffer can fault
// here if the underlying file has been truncated. // here if the underlying file has been truncated.
// Do not crash the VM in such a case. // Do not crash the VM in such a case.
CodeBlob* cb = CodeCache::find_blob_unsafe(pc); CodeBlob* cb = CodeCache::find_blob_unsafe(pc);
CompiledMethod* nm = cb->as_compiled_method_or_null(); CompiledMethod* nm = cb->as_compiled_method_or_null();
if (nm != NULL && nm->has_unsafe_access()) { if (nm != NULL && nm->has_unsafe_access()) {
*stub = StubRoutines::handler_for_unsafe_access(); *stub = SharedRuntime::handle_unsafe_access(thread, npc);
return true; return true;
} }
return false; return false;
@ -613,7 +613,7 @@ JVM_handle_linux_signal(int sig,
if (sig == SIGBUS && if (sig == SIGBUS &&
thread->thread_state() == _thread_in_vm && thread->thread_state() == _thread_in_vm &&
thread->doing_unsafe_access()) { thread->doing_unsafe_access()) {
stub = StubRoutines::handler_for_unsafe_access(); stub = SharedRuntime::handle_unsafe_access(thread, npc);
} }
if (thread->thread_state() == _thread_in_Java) { if (thread->thread_state() == _thread_in_Java) {
@ -625,7 +625,7 @@ JVM_handle_linux_signal(int sig,
break; break;
} }
if ((sig == SIGBUS) && checkByteBuffer(pc, &stub)) { if ((sig == SIGBUS) && checkByteBuffer(pc, npc, &stub)) {
break; break;
} }

View file

@ -420,7 +420,8 @@ JVM_handle_linux_signal(int sig,
CodeBlob* cb = CodeCache::find_blob_unsafe(pc); CodeBlob* cb = CodeCache::find_blob_unsafe(pc);
CompiledMethod* nm = (cb != NULL) ? cb->as_compiled_method_or_null() : NULL; CompiledMethod* nm = (cb != NULL) ? cb->as_compiled_method_or_null() : NULL;
if (nm != NULL && nm->has_unsafe_access()) { 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 else
@ -469,7 +470,8 @@ JVM_handle_linux_signal(int sig,
} else if (thread->thread_state() == _thread_in_vm && } else if (thread->thread_state() == _thread_in_vm &&
sig == SIGBUS && /* info->si_code == BUS_OBJERR && */ sig == SIGBUS && /* info->si_code == BUS_OBJERR && */
thread->doing_unsafe_access()) { 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_Get<Primitive>Field can trap at certain pc's if a GC kicks in // jni_fast_Get<Primitive>Field can trap at certain pc's if a GC kicks in

View file

@ -441,7 +441,7 @@ JVM_handle_solaris_signal(int sig, siginfo_t* info, void* ucVoid,
if (thread->thread_state() == _thread_in_vm) { if (thread->thread_state() == _thread_in_vm) {
if (sig == SIGBUS && info->si_code == BUS_OBJERR && thread->doing_unsafe_access()) { 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 @@ JVM_handle_solaris_signal(int sig, siginfo_t* info, void* ucVoid,
CodeBlob* cb = CodeCache::find_blob_unsafe(pc); CodeBlob* cb = CodeCache::find_blob_unsafe(pc);
CompiledMethod* nm = cb->as_compiled_method_or_null(); CompiledMethod* nm = cb->as_compiled_method_or_null();
if (nm != NULL && nm->has_unsafe_access()) { if (nm != NULL && nm->has_unsafe_access()) {
stub = StubRoutines::handler_for_unsafe_access(); stub = SharedRuntime::handle_unsafe_access(thread, npc);
} }
} }

View file

@ -503,7 +503,8 @@ JVM_handle_solaris_signal(int sig, siginfo_t* info, void* ucVoid,
if (thread->thread_state() == _thread_in_vm) { if (thread->thread_state() == _thread_in_vm) {
if (sig == SIGBUS && info->si_code == BUS_OBJERR && thread->doing_unsafe_access()) { 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 @@ JVM_handle_solaris_signal(int sig, siginfo_t* info, void* ucVoid,
if (cb != NULL) { if (cb != NULL) {
CompiledMethod* nm = cb->as_compiled_method_or_null(); CompiledMethod* nm = cb->as_compiled_method_or_null();
if (nm != NULL && nm->has_unsafe_access()) { 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);
} }
} }
} }

View file

@ -1762,6 +1762,21 @@ methodHandle SharedRuntime::reresolve_call_site(JavaThread *thread, TRAPS) {
return callee_method; 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 #ifdef ASSERT
void SharedRuntime::check_member_name_argument_is_last_argument(const methodHandle& method, void SharedRuntime::check_member_name_argument_is_last_argument(const methodHandle& method,
const BasicType* sig_bt, const BasicType* sig_bt,

View file

@ -522,6 +522,8 @@ class SharedRuntime: AllStatic {
static address handle_wrong_method_abstract(JavaThread* thread); static address handle_wrong_method_abstract(JavaThread* thread);
static address handle_wrong_method_ic_miss(JavaThread* thread); static address handle_wrong_method_ic_miss(JavaThread* thread);
static address handle_unsafe_access(JavaThread* thread, address next_pc);
#ifndef PRODUCT #ifndef PRODUCT
// Collect and print inline cache miss statistics // Collect and print inline cache miss statistics

View file

@ -55,7 +55,6 @@ address StubRoutines::_throw_IncompatibleClassChangeError_entry = NULL;
address StubRoutines::_throw_NullPointerException_at_call_entry = NULL; address StubRoutines::_throw_NullPointerException_at_call_entry = NULL;
address StubRoutines::_throw_StackOverflowError_entry = NULL; address StubRoutines::_throw_StackOverflowError_entry = NULL;
address StubRoutines::_throw_delayed_StackOverflowError_entry = NULL; address StubRoutines::_throw_delayed_StackOverflowError_entry = NULL;
address StubRoutines::_handler_for_unsafe_access_entry = NULL;
jint StubRoutines::_verify_oop_count = 0; jint StubRoutines::_verify_oop_count = 0;
address StubRoutines::_verify_oop_subroutine_entry = NULL; address StubRoutines::_verify_oop_subroutine_entry = NULL;
address StubRoutines::_atomic_xchg_entry = NULL; address StubRoutines::_atomic_xchg_entry = NULL;

View file

@ -111,7 +111,6 @@ class StubRoutines: AllStatic {
static address _throw_NullPointerException_at_call_entry; static address _throw_NullPointerException_at_call_entry;
static address _throw_StackOverflowError_entry; static address _throw_StackOverflowError_entry;
static address _throw_delayed_StackOverflowError_entry; static address _throw_delayed_StackOverflowError_entry;
static address _handler_for_unsafe_access_entry;
static address _atomic_xchg_entry; static address _atomic_xchg_entry;
static address _atomic_xchg_ptr_entry; static address _atomic_xchg_ptr_entry;
@ -288,10 +287,6 @@ class StubRoutines: AllStatic {
static address throw_StackOverflowError_entry() { return _throw_StackOverflowError_entry; } static address throw_StackOverflowError_entry() { return _throw_StackOverflowError_entry; }
static address throw_delayed_StackOverflowError_entry() { return _throw_delayed_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_entry() { return _atomic_xchg_entry; }
static address atomic_xchg_ptr_entry() { return _atomic_xchg_ptr_entry; } static address atomic_xchg_ptr_entry() { return _atomic_xchg_ptr_entry; }
static address atomic_store_entry() { return _atomic_store_entry; } static address atomic_store_entry() { return _atomic_store_entry; }