--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/prims/forte.cpp Sat Dec 01 00:00:00 2007 +0000
@@ -0,0 +1,895 @@
+/*
+ * 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
+}