blob: efda11f6a7aa1d1484760dd1984c86c6bd3a3dac [file] [log] [blame]
/*
* Copyright 2003-2007 Sun Microsystems, Inc. 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*
*/
# include "incls/_precompiled.incl"
# include "incls/_forte.cpp.incl"
//-------------------------------------------------------
// Native interfaces for use by Forte tools.
#ifndef IA64
class vframeStreamForte : public vframeStreamCommon {
public:
// constructor that starts with sender of frame fr (top_frame)
vframeStreamForte(JavaThread *jt, frame fr, bool stop_at_java_call_stub);
void forte_next();
};
static void forte_is_walkable_compiled_frame(frame* fr, RegisterMap* map,
bool* is_compiled_p, bool* is_walkable_p);
static bool forte_is_walkable_interpreted_frame(frame* fr,
methodOop* method_p, int* bci_p);
// A Forte specific version of frame:safe_for_sender().
static bool forte_safe_for_sender(frame* fr, JavaThread *thread) {
bool ret_value = false; // be pessimistic
#ifdef COMPILER2
#if defined(IA32) || defined(AMD64)
{
// This check is the same as the standard safe_for_sender()
// on IA32 or AMD64 except that NULL FP values are tolerated
// for C2.
address sp = (address)fr->sp();
address fp = (address)fr->fp();
ret_value = sp != NULL && sp <= thread->stack_base() &&
sp >= thread->stack_base() - thread->stack_size() &&
(fp == NULL || (fp <= thread->stack_base() &&
fp >= thread->stack_base() - thread->stack_size()));
// We used to use standard safe_for_sender() when we are supposed
// to be executing Java code. However, that prevents us from
// walking some intrinsic stacks so now we have to be more refined.
// If we passed the above check and we have a NULL frame pointer
// and we are supposed to be executing Java code, then we have a
// couple of more checks to make.
if (ret_value && fp == NULL && (thread->thread_state() == _thread_in_Java
|| thread->thread_state() == _thread_in_Java_trans)) {
if (fr->is_interpreted_frame()) {
// interpreted frames don't really have a NULL frame pointer
return false;
} else if (CodeCache::find_blob(fr->pc()) == NULL) {
// the NULL frame pointer should be associated with generated code
return false;
}
}
}
#else // !(IA32 || AMD64)
ret_value = fr->safe_for_sender(thread);
#endif // IA32 || AMD64
#else // !COMPILER2
ret_value = fr->safe_for_sender(thread);
#endif // COMPILER2
if (!ret_value) {
return ret_value; // not safe, nothing more to do
}
address sp1;
#ifdef SPARC
// On Solaris SPARC, when a compiler frame has an interpreted callee
// the _interpreter_sp_adjustment field contains the adjustment to
// this frame's SP made by that interpreted callee.
// For AsyncGetCallTrace(), we need to verify that the resulting SP
// is valid for the specified thread's stack.
sp1 = (address)fr->sp();
address sp2 = (address)fr->unextended_sp();
// If the second SP is NULL, then the _interpreter_sp_adjustment
// field simply adjusts this frame's SP to NULL and the frame is
// not safe. This strange value can be set in the frame constructor
// when our peek into the interpreted callee's adjusted value for
// this frame's SP finds a NULL. This can happen when SIGPROF
// catches us while we are creating the interpreter frame.
//
if (sp2 == NULL ||
// If the two SPs are different, then _interpreter_sp_adjustment
// is non-zero and we need to validate the second SP. We invert
// the range check from frame::safe_for_sender() and bail out
// if the second SP is not safe.
(sp1 != sp2 && !(sp2 <= thread->stack_base()
&& sp2 >= (thread->stack_base() - thread->stack_size())))) {
return false;
}
#endif // SPARC
if (fr->is_entry_frame()) {
// This frame thinks it is an entry frame; we need to validate
// the JavaCallWrapper pointer.
// Note: frame::entry_frame_is_first() assumes that the
// JavaCallWrapper has a non-NULL _anchor field. We don't
// check that here (yet) since we've never seen a failure
// due to a NULL _anchor field.
// Update: Originally this check was done only for SPARC. However,
// this failure has now been seen on C2 C86. I have no reason to
// believe that this is not a general issue so I'm enabling the
// check for all compilers on all supported platforms.
#ifdef COMPILER2
#if defined(IA32) || defined(AMD64)
if (fr->fp() == NULL) {
// C2 X86 allows NULL frame pointers, but if we have one then
// we cannot call entry_frame_call_wrapper().
return false;
}
#endif // IA32 || AMD64
#endif // COMPILER2
sp1 = (address)fr->entry_frame_call_wrapper();
// We invert the range check from frame::safe_for_sender() and
// bail out if the JavaCallWrapper * is not safe.
if (!(sp1 <= thread->stack_base()
&& sp1 >= (thread->stack_base() - thread->stack_size()))) {
return false;
}
}
return ret_value;
}
// Unknown compiled frames have caused assertion failures on Solaris
// X86. This code also detects unknown compiled frames on Solaris
// SPARC, but no assertion failures have been observed. However, I'm
// paranoid so I'm enabling this code whenever we have a compiler.
//
// Returns true if the specified frame is an unknown compiled frame
// and false otherwise.
static bool is_unknown_compiled_frame(frame* fr, JavaThread *thread) {
bool ret_value = false; // be optimistic
// This failure mode only occurs when the thread is in state
// _thread_in_Java so we are okay for this check for any other
// thread state.
//
// Note: _thread_in_Java does not always mean that the thread
// is executing Java code. AsyncGetCallTrace() has caught
// threads executing in JRT_LEAF() routines when the state
// will also be _thread_in_Java.
if (thread->thread_state() != _thread_in_Java) {
return ret_value;
}
// This failure mode only occurs with compiled frames so we are
// okay for this check for both entry and interpreted frames.
if (fr->is_entry_frame() || fr->is_interpreted_frame()) {
return ret_value;
}
// This failure mode only occurs when the compiled frame's PC
// is in the code cache so we are okay for this check if the
// PC is not in the code cache.
CodeBlob* cb = CodeCache::find_blob(fr->pc());
if (cb == NULL) {
return ret_value;
}
// We have compiled code in the code cache so it is time for
// the final check: let's see if any frame type is set
ret_value = !(
// is_entry_frame() is checked above
// testers that are a subset of is_entry_frame():
// is_first_frame()
fr->is_java_frame()
// testers that are a subset of is_java_frame():
// is_interpreted_frame()
// is_compiled_frame()
|| fr->is_native_frame()
|| fr->is_runtime_frame()
|| fr->is_safepoint_blob_frame()
);
// If there is no frame type set, then we have an unknown compiled
// frame and sender() should not be called on it.
return ret_value;
}
#define DebugNonSafepoints_IS_CLEARED \
(!FLAG_IS_DEFAULT(DebugNonSafepoints) && !DebugNonSafepoints)
// if -XX:-DebugNonSafepoints, then top-frame will be skipped
vframeStreamForte::vframeStreamForte(JavaThread *jt, frame fr,
bool stop_at_java_call_stub) : vframeStreamCommon(jt) {
_stop_at_java_call_stub = stop_at_java_call_stub;
if (!DebugNonSafepoints_IS_CLEARED) {
// decode the top frame fully
// (usual case, if JVMTI is enabled)
_frame = fr;
} else {
// skip top frame, as it may not be at safepoint
// For AsyncGetCallTrace(), we extracted as much info from the top
// frame as we could in forte_is_walkable_frame(). We also verified
// forte_safe_for_sender() so this sender() call is safe.
_frame = fr.sender(&_reg_map);
}
if (jt->thread_state() == _thread_in_Java && !fr.is_first_frame()) {
bool sender_check = false; // assume sender is not safe
if (forte_safe_for_sender(&_frame, jt)) {
// If the initial sender frame is safe, then continue on with other
// checks. The unsafe sender frame has been seen on Solaris X86
// with both Compiler1 and Compiler2. It has not been seen on
// Solaris SPARC, but seems like a good sanity check to have
// anyway.
// SIGPROF caught us in Java code and the current frame is not the
// first frame so we should sanity check the sender frame. It is
// possible for SIGPROF to catch us in the middle of making a call.
// When that happens the current frame is actually a combination of
// the real sender and some of the new call's info. We can't find
// the real sender with such a current frame and things can get
// confused.
//
// This sanity check has caught problems with the sender frame on
// Solaris SPARC. So far Solaris X86 has not had a failure here.
sender_check = _frame.is_entry_frame()
// testers that are a subset of is_entry_frame():
// is_first_frame()
|| _frame.is_java_frame()
// testers that are a subset of is_java_frame():
// is_interpreted_frame()
// is_compiled_frame()
|| _frame.is_native_frame()
|| _frame.is_runtime_frame()
|| _frame.is_safepoint_blob_frame()
;
// We need an additional sanity check on an initial interpreted
// sender frame. This interpreted frame needs to be both walkable
// and have a valid BCI. This is yet another variant of SIGPROF
// catching us in the middle of making a call.
if (sender_check && _frame.is_interpreted_frame()) {
methodOop method = NULL;
int bci = -1;
if (!forte_is_walkable_interpreted_frame(&_frame, &method, &bci)
|| bci == -1) {
sender_check = false;
}
}
// We need an additional sanity check on an initial compiled
// sender frame. This compiled frame also needs to be walkable.
// This is yet another variant of SIGPROF catching us in the
// middle of making a call.
if (sender_check && !_frame.is_interpreted_frame()) {
bool is_compiled, is_walkable;
forte_is_walkable_compiled_frame(&_frame, &_reg_map,
&is_compiled, &is_walkable);
if (is_compiled && !is_walkable) {
sender_check = false;
}
}
}
if (!sender_check) {
// nothing else to try if we can't recognize the sender
_mode = at_end_mode;
return;
}
}
int loop_count = 0;
int loop_max = MaxJavaStackTraceDepth * 2;
while (!fill_from_frame()) {
_frame = _frame.sender(&_reg_map);
#ifdef COMPILER2
#if defined(IA32) || defined(AMD64)
// Stress testing on C2 X86 has shown a periodic problem with
// the sender() call below. The initial _frame that we have on
// entry to the loop has already passed forte_safe_for_sender()
// so we only check frames after it.
if (!forte_safe_for_sender(&_frame, _thread)) {
_mode = at_end_mode;
return;
}
#endif // IA32 || AMD64
#endif // COMPILER2
if (++loop_count >= loop_max) {
// We have looped more than twice the number of possible
// Java frames. This indicates that we are trying to walk
// a stack that is in the middle of being constructed and
// it is self referential.
_mode = at_end_mode;
return;
}
}
}
// Solaris SPARC Compiler1 needs an additional check on the grandparent
// of the top_frame when the parent of the top_frame is interpreted and
// the grandparent is compiled. However, in this method we do not know
// the relationship of the current _frame relative to the top_frame so
// we implement a more broad sanity check. When the previous callee is
// interpreted and the current sender is compiled, we verify that the
// current sender is also walkable. If it is not walkable, then we mark
// the current vframeStream as at the end.
void vframeStreamForte::forte_next() {
// handle frames with inlining
if (_mode == compiled_mode &&
vframeStreamCommon::fill_in_compiled_inlined_sender()) {
return;
}
// handle general case
int loop_count = 0;
int loop_max = MaxJavaStackTraceDepth * 2;
do {
#if defined(COMPILER1) && defined(SPARC)
bool prevIsInterpreted = _frame.is_interpreted_frame();
#endif // COMPILER1 && SPARC
_frame = _frame.sender(&_reg_map);
if (!forte_safe_for_sender(&_frame, _thread)) {
_mode = at_end_mode;
return;
}
#if defined(COMPILER1) && defined(SPARC)
if (prevIsInterpreted) {
// previous callee was interpreted and may require a special check
if (_frame.is_compiled_frame() && _frame.cb()->is_compiled_by_c1()) {
// compiled sender called interpreted callee so need one more check
bool is_compiled, is_walkable;
// sanity check the compiled sender frame
forte_is_walkable_compiled_frame(&_frame, &_reg_map,
&is_compiled, &is_walkable);
assert(is_compiled, "sanity check");
if (!is_walkable) {
// compiled sender frame is not walkable so bail out
_mode = at_end_mode;
return;
}
}
}
#endif // COMPILER1 && SPARC
if (++loop_count >= loop_max) {
// We have looped more than twice the number of possible
// Java frames. This indicates that we are trying to walk
// a stack that is in the middle of being constructed and
// it is self referential.
_mode = at_end_mode;
return;
}
} while (!fill_from_frame());
}
// Determine if 'fr' is a walkable, compiled frame.
// *is_compiled_p is set to true if the frame is compiled and if it
// is, then *is_walkable_p is set to true if it is also walkable.
static void forte_is_walkable_compiled_frame(frame* fr, RegisterMap* map,
bool* is_compiled_p, bool* is_walkable_p) {
*is_compiled_p = false;
*is_walkable_p = false;
CodeBlob* cb = CodeCache::find_blob(fr->pc());
if (cb != NULL &&
cb->is_nmethod() &&
((nmethod*)cb)->is_java_method()) {
// frame is compiled and executing a Java method
*is_compiled_p = true;
// Increment PC because the PcDesc we want is associated with
// the *end* of the instruction, and pc_desc_near searches
// forward to the first matching PC after the probe PC.
PcDesc* pc_desc = NULL;
if (!DebugNonSafepoints_IS_CLEARED) {
// usual case: look for any safepoint near the sampled PC
address probe_pc = fr->pc() + 1;
pc_desc = ((nmethod*) cb)->pc_desc_near(probe_pc);
} else {
// reduced functionality: only recognize PCs immediately after calls
pc_desc = ((nmethod*) cb)->pc_desc_at(fr->pc());
}
if (pc_desc != NULL && (pc_desc->scope_decode_offset()
== DebugInformationRecorder::serialized_null)) {
pc_desc = NULL;
}
if (pc_desc != NULL) {
// it has a PcDesc so the frame is also walkable
*is_walkable_p = true;
if (!DebugNonSafepoints_IS_CLEARED) {
// Normalize the PC to the one associated exactly with
// this PcDesc, so that subsequent stack-walking queries
// need not be approximate:
fr->set_pc(pc_desc->real_pc((nmethod*) cb));
}
}
// Implied else: this compiled frame has no PcDesc, i.e., contains
// a frameless stub such as C1 method exit, so it is not walkable.
}
// Implied else: this isn't a compiled frame so it isn't a
// walkable, compiled frame.
}
// Determine if 'fr' is a walkable interpreted frame. Returns false
// if it is not. *method_p, and *bci_p are not set when false is
// returned. *method_p is non-NULL if frame was executing a Java
// method. *bci_p is != -1 if a valid BCI in the Java method could
// be found.
// Note: this method returns true when a valid Java method is found
// even if a valid BCI cannot be found.
static bool forte_is_walkable_interpreted_frame(frame* fr,
methodOop* method_p, int* bci_p) {
assert(fr->is_interpreted_frame(), "just checking");
// top frame is an interpreted frame
// check if it is walkable (i.e. valid methodOop and valid bci)
if (fr->is_interpreted_frame_valid()) {
if (fr->fp() != NULL) {
// access address in order not to trigger asserts that
// are built in interpreter_frame_method function
methodOop method = *fr->interpreter_frame_method_addr();
if (Universe::heap()->is_valid_method(method)) {
intptr_t bcx = fr->interpreter_frame_bcx();
int bci = method->validate_bci_from_bcx(bcx);
// note: bci is set to -1 if not a valid bci
*method_p = method;
*bci_p = bci;
return true;
}
}
}
return false;
}
// Determine if 'fr' can be used to find a walkable frame. Returns
// false if a walkable frame cannot be found. *walkframe_p, *method_p,
// and *bci_p are not set when false is returned. Returns true if a
// walkable frame is returned via *walkframe_p. *method_p is non-NULL
// if the returned frame was executing a Java method. *bci_p is != -1
// if a valid BCI in the Java method could be found.
//
// *walkframe_p will be used by vframeStreamForte as the initial
// frame for walking the stack. Currently the initial frame is
// skipped by vframeStreamForte because we inherited the logic from
// the vframeStream class. This needs to be revisited in the future.
static bool forte_is_walkable_frame(JavaThread* thread, frame* fr,
frame* walkframe_p, methodOop* method_p, int* bci_p) {
if (!forte_safe_for_sender(fr, thread)
|| is_unknown_compiled_frame(fr, thread)
) {
// If the initial frame is not safe, then bail out. So far this
// has only been seen on Solaris X86 with Compiler2, but it seems
// like a great initial sanity check.
return false;
}
if (fr->is_first_frame()) {
// If initial frame is frame from StubGenerator and there is no
// previous anchor, there are no java frames yet
return false;
}
if (fr->is_interpreted_frame()) {
if (forte_is_walkable_interpreted_frame(fr, method_p, bci_p)) {
*walkframe_p = *fr;
return true;
}
return false;
}
// At this point we have something other than a first frame or an
// interpreted frame.
methodOop method = NULL;
frame candidate = *fr;
// If we loop more than twice the number of possible Java
// frames, then this indicates that we are trying to walk
// a stack that is in the middle of being constructed and
// it is self referential. So far this problem has only
// been seen on Solaris X86 Compiler2, but it seems like
// a good robustness fix for all platforms.
int loop_count;
int loop_max = MaxJavaStackTraceDepth * 2;
for (loop_count = 0; loop_count < loop_max; loop_count++) {
// determine if the candidate frame is executing a Java method
if (CodeCache::contains(candidate.pc())) {
// candidate is a compiled frame or stub routine
CodeBlob* cb = CodeCache::find_blob(candidate.pc());
if (cb->is_nmethod()) {
method = ((nmethod *)cb)->method();
}
} // end if CodeCache has our PC
RegisterMap map(thread, false);
// we have a Java frame that seems reasonable
if (method != NULL && candidate.is_java_frame()
&& candidate.sp() != NULL && candidate.pc() != NULL) {
// we need to sanity check the candidate further
bool is_compiled, is_walkable;
forte_is_walkable_compiled_frame(&candidate, &map, &is_compiled,
&is_walkable);
if (is_compiled) {
// At this point, we know we have a compiled Java frame with
// method information that we want to return. We don't check
// the is_walkable flag here because that flag pertains to
// vframeStreamForte work that is done after we are done here.
break;
}
}
// At this point, the candidate doesn't work so try the sender.
// For AsyncGetCallTrace() we cannot assume there is a sender
// for the initial frame. The initial forte_safe_for_sender() call
// and check for is_first_frame() is done on entry to this method.
candidate = candidate.sender(&map);
if (!forte_safe_for_sender(&candidate, thread)) {
#ifdef COMPILER2
#if defined(IA32) || defined(AMD64)
// C2 on X86 can use the ebp register as a general purpose register
// which can cause the candidate to fail theforte_safe_for_sender()
// above. We try one more time using a NULL frame pointer (fp).
candidate = frame(candidate.sp(), NULL, candidate.pc());
if (!forte_safe_for_sender(&candidate, thread)) {
#endif // IA32 || AMD64
#endif // COMPILER2
return false;
#ifdef COMPILER2
#if defined(IA32) || defined(AMD64)
} // end forte_safe_for_sender retry with NULL fp
#endif // IA32 || AMD64
#endif // COMPILER2
} // end first forte_safe_for_sender check
if (candidate.is_first_frame()
|| is_unknown_compiled_frame(&candidate, thread)) {
return false;
}
} // end for loop_count
if (method == NULL) {
// If we didn't get any method info from the candidate, then
// we have nothing to return so bail out.
return false;
}
*walkframe_p = candidate;
*method_p = method;
*bci_p = -1;
return true;
}
// call frame copied from old .h file and renamed
typedef struct {
jint lineno; // line number in the source file
jmethodID method_id; // method executed in this frame
} ASGCT_CallFrame;
// call trace copied from old .h file and renamed
typedef struct {
JNIEnv *env_id; // Env where trace was recorded
jint num_frames; // number of frames in this trace
ASGCT_CallFrame *frames; // frames
} ASGCT_CallTrace;
static void forte_fill_call_trace_given_top(JavaThread* thd,
ASGCT_CallTrace* trace, int depth, frame top_frame) {
NoHandleMark nhm;
frame walkframe;
methodOop method;
int bci;
int count;
count = 0;
assert(trace->frames != NULL, "trace->frames must be non-NULL");
if (!forte_is_walkable_frame(thd, &top_frame, &walkframe, &method, &bci)) {
// return if no walkable frame is found
return;
}
CollectedHeap* ch = Universe::heap();
if (method != NULL) {
// The method is not stored GC safe so see if GC became active
// after we entered AsyncGetCallTrace() and before we try to
// use the methodOop.
// Yes, there is still a window after this check and before
// we use methodOop below, but we can't lock out GC so that
// has to be an acceptable risk.
if (!ch->is_valid_method(method)) {
trace->num_frames = -2;
return;
}
if (DebugNonSafepoints_IS_CLEARED) {
// Take whatever method the top-frame decoder managed to scrape up.
// We look further at the top frame only if non-safepoint
// debugging information is available.
count++;
trace->num_frames = count;
trace->frames[0].method_id = method->find_jmethod_id_or_null();
if (!method->is_native()) {
trace->frames[0].lineno = bci;
} else {
trace->frames[0].lineno = -3;
}
}
}
// check has_last_Java_frame() after looking at the top frame
// which may be an interpreted Java frame.
if (!thd->has_last_Java_frame() && method == NULL) {
trace->num_frames = 0;
return;
}
vframeStreamForte st(thd, walkframe, false);
for (; !st.at_end() && count < depth; st.forte_next(), count++) {
bci = st.bci();
method = st.method();
// The method is not stored GC safe so see if GC became active
// after we entered AsyncGetCallTrace() and before we try to
// use the methodOop.
// Yes, there is still a window after this check and before
// we use methodOop below, but we can't lock out GC so that
// has to be an acceptable risk.
if (!ch->is_valid_method(method)) {
// we throw away everything we've gathered in this sample since
// none of it is safe
trace->num_frames = -2;
return;
}
trace->frames[count].method_id = method->find_jmethod_id_or_null();
if (!method->is_native()) {
trace->frames[count].lineno = bci;
} else {
trace->frames[count].lineno = -3;
}
}
trace->num_frames = count;
return;
}
// Forte Analyzer AsyncGetCallTrace() entry point. Currently supported
// on Linux X86, Solaris SPARC and Solaris X86.
//
// Async-safe version of GetCallTrace being called from a signal handler
// when a LWP gets interrupted by SIGPROF but the stack traces are filled
// with different content (see below).
//
// This function must only be called when JVM/TI
// CLASS_LOAD events have been enabled since agent startup. The enabled
// event will cause the jmethodIDs to be allocated at class load time.
// The jmethodIDs cannot be allocated in a signal handler because locks
// cannot be grabbed in a signal handler safely.
//
// void (*AsyncGetCallTrace)(ASGCT_CallTrace *trace, jint depth, void* ucontext)
//
// Called by the profiler to obtain the current method call stack trace for
// a given thread. The thread is identified by the env_id field in the
// ASGCT_CallTrace structure. The profiler agent should allocate a ASGCT_CallTrace
// structure with enough memory for the requested stack depth. The VM fills in
// the frames buffer and the num_frames field.
//
// Arguments:
//
// trace - trace data structure to be filled by the VM.
// depth - depth of the call stack trace.
// ucontext - ucontext_t of the LWP
//
// ASGCT_CallTrace:
// typedef struct {
// JNIEnv *env_id;
// jint num_frames;
// ASGCT_CallFrame *frames;
// } ASGCT_CallTrace;
//
// Fields:
// env_id - ID of thread which executed this trace.
// num_frames - number of frames in the trace.
// (< 0 indicates the frame is not walkable).
// frames - the ASGCT_CallFrames that make up this trace. Callee followed by callers.
//
// ASGCT_CallFrame:
// typedef struct {
// jint lineno;
// jmethodID method_id;
// } ASGCT_CallFrame;
//
// Fields:
// 1) For Java frame (interpreted and compiled),
// lineno - bci of the method being executed or -1 if bci is not available
// method_id - jmethodID of the method being executed
// 2) For native method
// lineno - (-3)
// method_id - jmethodID of the method being executed
extern "C" {
void AsyncGetCallTrace(ASGCT_CallTrace *trace, jint depth, void* ucontext) {
if (SafepointSynchronize::is_synchronizing()) {
// The safepoint mechanism is trying to synchronize all the threads.
// Since this can involve thread suspension, it is not safe for us
// to be here. We can reduce the deadlock risk window by quickly
// returning to the SIGPROF handler. However, it is still possible
// for VMThread to catch us here or in the SIGPROF handler. If we
// are suspended while holding a resource and another thread blocks
// on that resource in the SIGPROF handler, then we will have a
// three-thread deadlock (VMThread, this thread, the other thread).
trace->num_frames = -10;
return;
}
JavaThread* thread;
if (trace->env_id == NULL ||
(thread = JavaThread::thread_from_jni_environment(trace->env_id)) == NULL ||
thread->is_exiting()) {
// bad env_id, thread has exited or thread is exiting
trace->num_frames = -8;
return;
}
if (thread->in_deopt_handler()) {
// thread is in the deoptimization handler so return no frames
trace->num_frames = -9;
return;
}
assert(JavaThread::current() == thread,
"AsyncGetCallTrace must be called by the current interrupted thread");
if (!JvmtiExport::should_post_class_load()) {
trace->num_frames = -1;
return;
}
if (Universe::heap()->is_gc_active()) {
trace->num_frames = -2;
return;
}
switch (thread->thread_state()) {
case _thread_new:
case _thread_uninitialized:
case _thread_new_trans:
// We found the thread on the threads list above, but it is too
// young to be useful so return that there are no Java frames.
trace->num_frames = 0;
break;
case _thread_in_native:
case _thread_in_native_trans:
case _thread_blocked:
case _thread_blocked_trans:
case _thread_in_vm:
case _thread_in_vm_trans:
{
frame fr;
// param isInJava == false - indicate we aren't in Java code
if (!thread->pd_get_top_frame_for_signal_handler(&fr, ucontext, false)) {
if (!thread->has_last_Java_frame()) {
trace->num_frames = 0; // no Java frames
} else {
trace->num_frames = -3; // unknown frame
}
} else {
trace->num_frames = -4; // non walkable frame by default
forte_fill_call_trace_given_top(thread, trace, depth, fr);
}
}
break;
case _thread_in_Java:
case _thread_in_Java_trans:
{
frame fr;
// param isInJava == true - indicate we are in Java code
if (!thread->pd_get_top_frame_for_signal_handler(&fr, ucontext, true)) {
trace->num_frames = -5; // unknown frame
} else {
trace->num_frames = -6; // non walkable frame by default
forte_fill_call_trace_given_top(thread, trace, depth, fr);
}
}
break;
default:
// Unknown thread state
trace->num_frames = -7;
break;
}
}
#ifndef _WINDOWS
// Support for the Forte(TM) Peformance Tools collector.
//
// The method prototype is derived from libcollector.h. For more
// information, please see the libcollect man page.
// Method to let libcollector know about a dynamically loaded function.
// Because it is weakly bound, the calls become NOP's when the library
// isn't present.
void collector_func_load(char* name,
void* null_argument_1,
void* null_argument_2,
void *vaddr,
int size,
int zero_argument,
void* null_argument_3);
#pragma weak collector_func_load
#define collector_func_load(x0,x1,x2,x3,x4,x5,x6) \
( collector_func_load ? collector_func_load(x0,x1,x2,x3,x4,x5,x6),0 : 0 )
#endif // !_WINDOWS
} // end extern "C"
#endif // !IA64
void Forte::register_stub(const char* name, address start, address end) {
#if !defined(_WINDOWS) && !defined(IA64)
assert(pointer_delta(end, start, sizeof(jbyte)) < INT_MAX,
"Code size exceeds maximum range")
collector_func_load((char*)name, NULL, NULL, start,
pointer_delta(end, start, sizeof(jbyte)), 0, NULL);
#endif // !_WINDOWS && !IA64
}