Top


定義場所(file name)

hotspot/src/share/vm/prims/forte.cpp

説明(description)

// 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" {
JNIEXPORT

名前(function name)

void AsyncGetCallTrace(ASGCT_CallTrace *trace, jint depth, void* ucontext) {

本体部(body)

  {- -------------------------------------------
  (1) 
      ---------------------------------------- -}

    // This is if'd out because we no longer use thread suspension.
    // However if someone wanted to backport this to a 5.0 jvm then this
    // code would be important.
    #if 0
      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 = ticks_safepoint; // -10
        return;
      }
    #endif

  {- -------------------------------------------
  (1) 
      ---------------------------------------- -}

      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 = ticks_thread_exit; // -8
        return;
      }

      if (thread->in_deopt_handler()) {
        // thread is in the deoptimization handler so return no frames
        trace->num_frames = ticks_deopt; // -9
        return;
      }

      assert(JavaThread::current() == thread,
             "AsyncGetCallTrace must be called by the current interrupted thread");

      if (!JvmtiExport::should_post_class_load()) {
        trace->num_frames = ticks_no_class_load; // -1
        return;
      }

      if (Universe::heap()->is_gc_active()) {
        trace->num_frames = ticks_GC_active; // -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)) {
            trace->num_frames = ticks_unknown_not_Java;  // -3 unknown frame
          } else {
            if (!thread->has_last_Java_frame()) {
              trace->num_frames = 0; // No Java frames
            } else {
              trace->num_frames = ticks_not_walkable_not_Java;    // -4 non walkable frame by default
              forte_fill_call_trace_given_top(thread, trace, depth, fr);

              // This assert would seem to be valid but it is not.
              // It would be valid if we weren't possibly racing a gc
              // thread. A gc thread can make a valid interpreted frame
              // look invalid. It's a small window but it does happen.
              // The assert is left here commented out as a reminder.
              // assert(trace->num_frames != ticks_not_walkable_not_Java, "should always be walkable");

            }
          }
        }
        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 = ticks_unknown_Java;  // -5 unknown frame
          } else {
            trace->num_frames = ticks_not_walkable_Java;  // -6, non walkable frame by default
            forte_fill_call_trace_given_top(thread, trace, depth, fr);
          }
        }
        break;
      default:
        // Unknown thread state
        trace->num_frames = ticks_unknown_state; // -7
        break;
      }
    }

This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.