--- old/src/share/vm/runtime/sharedRuntime.cpp 2015-11-04 14:32:55.135948366 +0100 +++ new/src/share/vm/runtime/sharedRuntime.cpp 2015-11-04 14:32:54.960930927 +0100 @@ -56,6 +56,7 @@ #include "runtime/stubRoutines.hpp" #include "runtime/vframe.hpp" #include "runtime/vframeArray.hpp" +#include "trace/tracing.hpp" #include "utilities/copy.hpp" #include "utilities/dtrace.hpp" #include "utilities/events.hpp" @@ -482,8 +483,11 @@ // unguarded. Reguard the stack otherwise if we return to the // deopt blob and the stack bang causes a stack overflow we // crash. - bool guard_pages_enabled = thread->stack_yellow_zone_enabled(); + bool guard_pages_enabled = thread->stack_guards_enabled(); if (!guard_pages_enabled) guard_pages_enabled = thread->reguard_stack(); + if (thread->reserved_stack_activation() != (intptr_t*) thread->stack_base()) { + thread->set_reserved_stack_activation((intptr_t*) thread->stack_base()); + } assert(guard_pages_enabled, "stack banging in deopt blob may cause crash"); return SharedRuntime::deopt_blob()->unpack_with_exception(); } else { @@ -763,10 +767,23 @@ JRT_END JRT_ENTRY(void, SharedRuntime::throw_StackOverflowError(JavaThread* thread)) + throw_StackOverflowError_common(thread, false); +JRT_END + +JRT_ENTRY(void, SharedRuntime::throw_delayed_StackOverflowError(JavaThread* thread)) + throw_StackOverflowError_common(thread, true); +JRT_END + +void SharedRuntime::throw_StackOverflowError_common(JavaThread* thread, bool delayed) { // We avoid using the normal exception construction in this case because // it performs an upcall to Java, and we're already out of stack space. + Thread* THREAD = thread; Klass* k = SystemDictionary::StackOverflowError_klass(); oop exception_oop = InstanceKlass::cast(k)->allocate_instance(CHECK); + if (delayed) { + java_lang_Throwable::set_message(exception_oop, + Universe::delayed_stack_overflow_error_message()); + } Handle exception (thread, exception_oop); if (StackTraceInThrowable) { java_lang_Throwable::fill_in_stack_trace(exception); @@ -774,7 +791,7 @@ // Increment counter for hs_err file reporting Atomic::inc(&Exceptions::_stack_overflow_errors); throw_and_post_jvmti_exception(thread, exception); -JRT_END +} #if INCLUDE_JVMCI address SharedRuntime::deoptimize_for_implicit_exception(JavaThread* thread, address pc, nmethod* nm, int deopt_reason) { @@ -2930,3 +2947,69 @@ } #endif /* PRODUCT */ + +JRT_LEAF(void, SharedRuntime::enable_stack_reserved_zone(JavaThread* thread)) + assert(thread->is_Java_thread(), "Only Java threads have a stack reserved zone"); + thread->enable_stack_reserved_zone(); + thread->set_reserved_stack_activation((intptr_t*)thread->stack_base()); +JRT_END + +frame SharedRuntime::look_for_reserved_stack_annotated_method(JavaThread* thread, frame fr) { + frame activation; + int decode_offset = 0; + nmethod* nm = NULL; + frame prv_fr = fr; + int count = 1; + + assert(fr.is_java_frame(), "Must start on Java frame"); + + while (!fr.is_first_frame()) { + Method* method = NULL; + // Compiled java method case. + if (decode_offset != 0) { + DebugInfoReadStream stream(nm, decode_offset); + decode_offset = stream.read_int(); + method = (Method*)nm->metadata_at(stream.read_int()); + } else { + if (fr.is_first_java_frame()) break; + address pc = fr.pc(); + if (fr.is_interpreted_frame()) { + method = fr.interpreter_frame_method(); + prv_fr = fr; + fr = fr.java_sender(); + } else { + CodeBlob* cb = fr.cb(); + prv_fr = fr; + fr = fr.java_sender(); + if (cb == NULL || !cb->is_nmethod()) { + continue; + } + nm = (nmethod*)cb; + if (nm->method()->is_native()) { + method = nm->method(); + } else { + PcDesc* pd = nm->pc_desc_at(pc); + assert(pd != NULL, "PcDesc must not be NULL"); + decode_offset = pd->scope_decode_offset(); + // if decode_offset is not equal to 0, it will execute the + // "compiled java method case" at the beginning of the loop. + continue; + } + } + } + if (method->has_reserved_stack_access()) { + ResourceMark rm(thread); + activation = prv_fr; + warning("Potentially dangerous stack overflow in " + "ReservedStackAccess annotated method %s [%d]", + method->name_and_sig_as_C_string(), count++); + EventReservedStackActivation event; + if (event.should_commit()) { + event.set_method(method); + event.commit(); + } + } + } + return activation; +} +