--- old/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp 2015-11-04 14:32:35.870028698 +0100 +++ new/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp 2015-11-04 14:32:35.701011857 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2014, 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 @@ -252,6 +252,38 @@ return frame(sp, frame::unpatchable, epc.pc()); } +frame os::fetch_frame_from_ucontext(Thread* thread, void* ucVoid) { + intptr_t* sp; + ExtendedPC epc = os::Solaris::fetch_frame_from_ucontext(thread, (ucontext_t*)ucVoid, &sp, NULL); + return frame(sp, frame::unpatchable, epc.pc()); +} + +bool os::Solaris::get_frame_at_stack_banging_point(JavaThread* thread, ucontext_t* uc, frame* fr) { + address pc = (address) os::Solaris::ucontext_get_pc(uc); + if (Interpreter::contains(pc)) { + *fr = os::fetch_frame_from_ucontext(thread, uc); + assert(fr->safe_for_sender(thread), "Safety check"); + } 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); + //assert(fr->safe_for_sender(thread), "Safety check"); + *fr = frame(fr->sender_sp(), frame::unpatchable, fr->sender_pc()); + if (!fr->is_java_frame()) { + assert(fr->safe_for_sender(thread), "Safety check"); + *fr = fr->java_sender(); + } + } + } + return true; +} + frame os::get_sender_for_C_frame(frame* fr) { return frame(fr->sender_sp(), frame::unpatchable, fr->sender_pc()); } @@ -369,17 +401,32 @@ if (sig == SIGSEGV && info->si_code == SEGV_ACCERR) { address addr = (address) info->si_addr; if (thread->in_stack_yellow_zone(addr)) { - thread->disable_stack_yellow_zone(); // Sometimes the register windows are not properly flushed. if(uc->uc_mcontext.gwins != NULL) { ::handle_unflushed_register_windows(uc->uc_mcontext.gwins); } if (thread->thread_state() == _thread_in_Java) { + if (thread->in_stack_reserved_zone(addr)) { + frame fr; + if (os::Solaris::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(); + RegisterMap map(thread); + int frame_size = activation.frame_size(&map); + thread->set_reserved_stack_activation((intptr_t*)(((address)activation.sp()) - STACK_BIAS)); + return true; + } + } + } // 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 true; } } else if (thread->in_stack_red_zone(addr)) {