Implement handler_for_unsafe_access()
Something we missed before now. It won't work with the built-in simulator, but is fine with the model. Making it work with the built- in simulator would be very fiddly, so I'm not going to attempt it. Andrew. # HG changeset patch # User aph # Date 1389882889 18000 # Thu Jan 16 09:34:49 2014 -0500 # Node ID f930dd00af0bd1592cccfd47b1f79b85b3e6d48a # Parent c40a7ed7df16bf529d6cd1b281699c7c520eaea5 Implement handler_for_unsafe_access(). diff -r c40a7ed7df16 -r f930dd00af0b src/cpu/aarch64/vm/stubGenerator_aarch64.cpp --- a/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp Fri Jan 10 11:31:09 2014 +0000 +++ b/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp Thu Jan 16 09:34:49 2014 -0500 @@ -67,9 +67,20 @@ // Stub Code definitions -#if 0 -static address handle_unsafe_access() { Unimplemented(); return 0; } -#endif +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 = pc + NativeCall::instruction_size; + + // request an async exception + thread->set_pending_unsafe_access_error(); + + // return address of next instruction to execute + return npc; +} class StubGenerator: public StubCodeGenerator { private: @@ -693,15 +704,19 @@ // 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(); - // NOTE: this is used by the signal handler code as a return address - // to re-enter Java execution so it needs an x86 prolog which will - // reenter the simulator executing the generated handler code. so - // the prolog needs to adjust the sim's restart pc to enter the - // generated code at the start position then return from native to - // simulated execution. + __ push(0x3fffffff, sp); // integer registers except lr & sp + BLOCK_COMMENT("call handle_unsafe_access"); + __ call_VM_leaf(CAST_FROM_FN_PTR(address, handle_unsafe_access)); + __ mov(lr, r0); + __ pop (0x3fffffff, sp); // integer registers except lr & sp + __ br(lr); - address generate_handler_for_unsafe_access() { return 0; } + return start; + } // Non-destructive plausibility checks for oops // @@ -893,7 +908,7 @@ __ mov(c_rarg0, start); __ mov(c_rarg1, scratch); __ call_VM_leaf(CAST_FROM_FN_PTR(address, BarrierSet::static_write_ref_array_post), 2); - __ pop(0x3fffffff, sp); // integer registers except lr & sp } + __ pop(0x3fffffff, sp); // integer registers except lr & sp } break; case BarrierSet::CardTableModRef:
Yesterday's patch was broken in that it trashed LR, which breaks traps from leaf functions. This patch is simpler and returns directly from the fault handler to the instruction after the fault, preserving LR. Andrew. # HG changeset patch # User aph # Date 1389981621 18000 # Fri Jan 17 13:00:21 2014 -0500 # Node ID ebe1eb322f481c62c29ee8a823a6be8a9e7508d8 # Parent e11bc6e52e678ca5cb6c7d7688838221ed55fe92 Implement handler for unsafe access by returning directly just after the faulting insn. diff -r e11bc6e52e67 -r ebe1eb322f48 src/os_cpu/linux_aarch64/vm/os_linux_aarch64.cpp --- a/src/os_cpu/linux_aarch64/vm/os_linux_aarch64.cpp Fri Jan 17 12:58:25 2014 -0500 +++ b/src/os_cpu/linux_aarch64/vm/os_linux_aarch64.cpp Fri Jan 17 13:00:21 2014 -0500 @@ -211,6 +211,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, @@ -363,7 +380,7 @@ CodeBlob* cb = CodeCache::find_blob_unsafe(pc); nmethod* nm = (cb != NULL && cb->is_nmethod()) ? (nmethod*)cb : NULL; if (nm != NULL && nm->has_unsafe_access()) { - stub = StubRoutines::handler_for_unsafe_access(); + stub = handle_unsafe_access(thread, pc); } } else @@ -384,7 +401,7 @@ } 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(); + stub = handle_unsafe_access(thread, pc); } // jni_fast_Get<Primitive>Field can trap at certain pc's if a GC kicks in
participants (1)
-
Andrew Haley