src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp

Print this page

        

*** 359,368 **** --- 359,410 ---- intptr_t* fp; ExtendedPC epc = fetch_frame_from_context(ucVoid, &sp, &fp); return frame(sp, fp, epc.pc()); } + frame os::fetch_frame_from_ucontext(Thread* thread, void* ucVoid) { + intptr_t* sp; + intptr_t* fp; + ExtendedPC epc = os::Bsd::fetch_frame_from_ucontext(thread, (ucontext_t*)ucVoid, &sp, &fp); + return frame(sp, fp, epc.pc()); + } + + bool os::Bsd::get_frame_at_stack_banging_point(JavaThread* thread, ucontext_t* uc, frame* fr) { + address pc = (address) os::Bsd::ucontext_get_pc(uc); + if (Interpreter::contains(pc)) { + // interpreter performs stack banging after the fixed frame header has + // been generated while the compilers perform it before. To maintain + // semantic consistency between interpreted and compiled frames, the + // method returns the Java sender of the current frame. + *fr = os::fetch_frame_from_ucontext(thread, uc); + assert(fr->safe_for_sender(thread), "Safety check"); + if (!fr->is_first_java_frame()) { + *fr = fr->java_sender(); + } + } else { + // more complex code with compiled code + assert(!Interpreter::contains(pc), "Interpreted methods should have been handled above"); + CodeBlob* cb = CodeCache::find_blob(pc); + if (cb == NULL || !cb->is_nmethod() || cb->is_frame_complete_at(pc)) { + // Not sure where the pc points to, fallback to default + // stack overflow handling + return false; + } else { + *fr = os::fetch_frame_from_ucontext(thread, uc); + // in compiled code, the stack banging is performed just after the return pc + // has been pushed on the stack + *fr = frame(fr->sp() + 1, fr->fp(), (address)*(fr->sp())); + if (!fr->is_java_frame()) { + assert(fr->safe_for_sender(thread), "Safety check"); + *fr = fr->java_sender(); + } + } + } + assert(fr->is_java_frame(), "Safety check"); + return true; + } + // By default, gcc always save frame pointer (%ebp/%rbp) on stack. It may get // turned off by -fomit-frame-pointer, frame os::get_sender_for_C_frame(frame* fr) { return frame(fr->sender_sp(), fr->link(), fr->sender_pc()); }
*** 476,492 **** // check if fault address is within thread stack if (addr < thread->stack_base() && addr >= thread->stack_base() - thread->stack_size()) { // stack overflow if (thread->in_stack_yellow_zone(addr)) { - thread->disable_stack_yellow_zone(); if (thread->thread_state() == _thread_in_Java) { // Throw a stack overflow exception. Guard pages will be reenabled // while unwinding the stack. stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::STACK_OVERFLOW); } else { // Thread was in the vm or native code. Return and try to finish. return 1; } } else if (thread->in_stack_red_zone(addr)) { // Fatal red zone violation. Disable the guard pages and fall through // to handle_unexpected_exception way down below. --- 518,552 ---- // check if fault address is within thread stack if (addr < thread->stack_base() && addr >= thread->stack_base() - thread->stack_size()) { // stack overflow if (thread->in_stack_yellow_zone(addr)) { if (thread->thread_state() == _thread_in_Java) { + if (thread->in_stack_reserved_zone(addr)) { + frame fr; + if (os::Bsd::get_frame_at_stack_banging_point(thread, uc, &fr)) { + assert(fr.is_java_frame(), "Must be a Java frame"); + frame activation = SharedRuntime::look_for_reserved_stack_annotated_method(thread, fr); + if (activation.sp() != NULL) { + thread->disable_stack_reserved_zone(); + if (activation.is_interpreted_frame()) { + thread->set_reserved_stack_activation( + activation.fp() + frame::interpreter_frame_initial_sp_offset); + } else { + thread->set_reserved_stack_activation(activation.unextended_sp()); + } + return 1; + } + } + } // Throw a stack overflow exception. Guard pages will be reenabled // while unwinding the stack. + thread->disable_stack_yellow_zone(); stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::STACK_OVERFLOW); } else { // Thread was in the vm or native code. Return and try to finish. + thread->disable_stack_yellow_zone(); return 1; } } else if (thread->in_stack_red_zone(addr)) { // Fatal red zone violation. Disable the guard pages and fall through // to handle_unexpected_exception way down below.