view hotspot/src/share/vm/prims/forte.cpp @ 1:193df1943809 trunk

[svn] Load openjdk/jdk7/b13 into jdk/trunk.
author xiomara
date Fri, 25 May 2007 00:49:14 +0000
parents a4ed3fb96592
children e2018f79de77
line wrap: on
line source

#ifdef USE_PRAGMA_IDENT_SRC
#pragma ident "@(#)forte.cpp	1.69 07/05/17 16:02:39 JVM"
#endif
/*
 * 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());
}


// is_valid_method() exists in fprofiler.cpp and now here.
// We need one central version of this routine.

bool forte_is_valid_method(methodOop method) {

  if (method == NULL || 
      // The methodOop is extracted via an offset from the current
      // interpreter frame. With AsyncGetCallTrace() the interpreter
      // frame may still be under construction so we need to make
      // sure that we got an aligned oop before we try to use it.
      !Space::is_aligned(method) ||
      !Universe::heap()->is_in((void*)method) ||
      // See if GC became active after we entered AsyncGetCallTrace()
      // and before we try to use the methodOop. This routine is
      // used in validation of the top_frame so we don't have any
      // other data to flush if we bail due to GC here.
      // 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.
      Universe::heap()->is_gc_active() ||
      //
      // is_perm_and_alloced() needs to be checked before klass() because you can
      // get a method pointing into the unmapped part of the heap's
      // reserved area (e.g., a very high address just within bounds),
      // and the instruction which loads the class will SIGSEGV.
      !method->is_perm_and_alloced() || 
      method->klass() != Universe::methodKlassObj()) {
    return false;   // doesn't look good
  }
  return true;      // hopefully this is a method indeed
}


// 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 (forte_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;
  }

  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 (!forte_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 (!forte_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
}