896 lines
31 KiB
C++
896 lines
31 KiB
C++
|
/*
|
||
|
* 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
|
||
|
}
|