forte.cpp revision 2721:f08d439fab8c
154359Sroberto/*
254359Sroberto * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
354359Sroberto * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
454359Sroberto *
554359Sroberto * This code is free software; you can redistribute it and/or modify it
654359Sroberto * under the terms of the GNU General Public License version 2 only, as
754359Sroberto * published by the Free Software Foundation.
854359Sroberto *
982498Sroberto * This code is distributed in the hope that it will be useful, but WITHOUT
1082498Sroberto * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1154359Sroberto * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1282498Sroberto * version 2 for more details (a copy is included in the LICENSE file that
13106163Sroberto * accompanied this code).
1482498Sroberto *
1582498Sroberto * You should have received a copy of the GNU General Public License version
1682498Sroberto * 2 along with this work; if not, write to the Free Software Foundation,
1782498Sroberto * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
1882498Sroberto *
1982498Sroberto * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2082498Sroberto * or visit www.oracle.com if you need additional information or have any
2182498Sroberto * questions.
2282498Sroberto *
2382498Sroberto */
24182007Sroberto
25182007Sroberto#include "precompiled.hpp"
26182007Sroberto#include "code/debugInfoRec.hpp"
27182007Sroberto#include "code/pcDesc.hpp"
28182007Sroberto#include "gc_interface/collectedHeap.inline.hpp"
29182007Sroberto#include "memory/space.hpp"
3054359Sroberto#include "memory/universe.inline.hpp"
3154359Sroberto#include "oops/oop.inline.hpp"
3254359Sroberto#include "oops/oop.inline2.hpp"
3354359Sroberto#include "prims/forte.hpp"
3454359Sroberto#include "runtime/thread.hpp"
3554359Sroberto#include "runtime/vframe.hpp"
3654359Sroberto#include "runtime/vframeArray.hpp"
3754359Sroberto
3882498Sroberto// These name match the names reported by the forte quality kit
3954359Srobertoenum {
4054359Sroberto  ticks_no_Java_frame         =  0,
41106163Sroberto  ticks_no_class_load         = -1,
42106163Sroberto  ticks_GC_active             = -2,
43106163Sroberto  ticks_unknown_not_Java      = -3,
44106163Sroberto  ticks_not_walkable_not_Java = -4,
45106163Sroberto  ticks_unknown_Java          = -5,
4682498Sroberto  ticks_not_walkable_Java     = -6,
4782498Sroberto  ticks_unknown_state         = -7,
4882498Sroberto  ticks_thread_exit           = -8,
4954359Sroberto  ticks_deopt                 = -9,
5054359Sroberto  ticks_safepoint             = -10
5154359Sroberto};
5254359Sroberto
5354359Sroberto//-------------------------------------------------------
54132451Sroberto
55132451Sroberto// Native interfaces for use by Forte tools.
5654359Sroberto
5754359Sroberto
5854359Sroberto#ifndef IA64
5954359Sroberto
6054359Srobertoclass vframeStreamForte : public vframeStreamCommon {
6154359Sroberto public:
6254359Sroberto  // constructor that starts with sender of frame fr (top_frame)
63182007Sroberto  vframeStreamForte(JavaThread *jt, frame fr, bool stop_at_java_call_stub);
64182007Sroberto  void forte_next();
65182007Sroberto};
66182007Sroberto
67182007Sroberto
68182007Srobertostatic bool is_decipherable_compiled_frame(JavaThread* thread, frame* fr, nmethod* nm);
6954359Srobertostatic bool is_decipherable_interpreted_frame(JavaThread* thread,
7054359Sroberto                                              frame* fr,
7154359Sroberto                                              methodOop* method_p,
7254359Sroberto                                              int* bci_p);
73132451Sroberto
74132451Sroberto
75132451Sroberto
76132451Sroberto
7754359SrobertovframeStreamForte::vframeStreamForte(JavaThread *jt,
7854359Sroberto                                     frame fr,
7954359Sroberto                                     bool stop_at_java_call_stub) : vframeStreamCommon(jt) {
80132451Sroberto
81182007Sroberto  _stop_at_java_call_stub = stop_at_java_call_stub;
82182007Sroberto  _frame = fr;
83132451Sroberto
8454359Sroberto  // We must always have a valid frame to start filling
8554359Sroberto
86182007Sroberto  bool filled_in = fill_from_frame();
87182007Sroberto
8854359Sroberto  assert(filled_in, "invariant");
8954359Sroberto
9054359Sroberto}
9154359Sroberto
9254359Sroberto
9354359Sroberto// Solaris SPARC Compiler1 needs an additional check on the grandparent
9454359Sroberto// of the top_frame when the parent of the top_frame is interpreted and
9554359Sroberto// the grandparent is compiled. However, in this method we do not know
9654359Sroberto// the relationship of the current _frame relative to the top_frame so
9754359Sroberto// we implement a more broad sanity check. When the previous callee is
9854359Sroberto// interpreted and the current sender is compiled, we verify that the
9954359Sroberto// current sender is also walkable. If it is not walkable, then we mark
10054359Sroberto// the current vframeStream as at the end.
10154359Srobertovoid vframeStreamForte::forte_next() {
10254359Sroberto  // handle frames with inlining
10354359Sroberto  if (_mode == compiled_mode &&
10454359Sroberto      vframeStreamCommon::fill_in_compiled_inlined_sender()) {
10554359Sroberto    return;
10654359Sroberto  }
10754359Sroberto
108182007Sroberto  // handle general case
10954359Sroberto
11054359Sroberto  int loop_count = 0;
11154359Sroberto  int loop_max = MaxJavaStackTraceDepth * 2;
112182007Sroberto
11354359Sroberto
11454359Sroberto  do {
11554359Sroberto
116182007Sroberto    loop_count++;
117182007Sroberto
118182007Sroberto    // By the time we get here we should never see unsafe but better
119182007Sroberto    // safe then segv'd
120182007Sroberto
12154359Sroberto    if (loop_count > loop_max || !_frame.safe_for_sender(_thread)) {
12254359Sroberto      _mode = at_end_mode;
12354359Sroberto      return;
12454359Sroberto    }
12554359Sroberto
12654359Sroberto    _frame = _frame.sender(&_reg_map);
12754359Sroberto
128132451Sroberto  } while (!fill_from_frame());
129132451Sroberto}
130182007Sroberto
131182007Sroberto// Determine if 'fr' is a decipherable compiled frame. We are already
132132451Sroberto// assured that fr is for a java nmethod.
13354359Sroberto
134132451Srobertostatic bool is_decipherable_compiled_frame(JavaThread* thread, frame* fr, nmethod* nm) {
13554359Sroberto  assert(nm->is_java_method(), "invariant");
13654359Sroberto
137182007Sroberto  if (thread->has_last_Java_frame() && thread->last_Java_pc() == fr->pc()) {
13854359Sroberto    // We're stopped at a call into the JVM so look for a PcDesc with
139132451Sroberto    // the actual pc reported by the frame.
14054359Sroberto    PcDesc* pc_desc = nm->pc_desc_at(fr->pc());
14154359Sroberto
14254359Sroberto    // Did we find a useful PcDesc?
14354359Sroberto    if (pc_desc != NULL &&
14454359Sroberto        pc_desc->scope_decode_offset() != DebugInformationRecorder::serialized_null) {
14554359Sroberto      return true;
14654359Sroberto    }
14754359Sroberto  }
14854359Sroberto
14954359Sroberto  // We're at some random pc in the nmethod so search for the PcDesc
15054359Sroberto  // whose pc is greater than the current PC.  It's done this way
15154359Sroberto  // because the extra PcDescs that are recorded for improved debug
15254359Sroberto  // info record the end of the region covered by the ScopeDesc
15354359Sroberto  // instead of the beginning.
15454359Sroberto  PcDesc* pc_desc = nm->pc_desc_near(fr->pc() + 1);
15554359Sroberto
15654359Sroberto  // Now do we have a useful PcDesc?
15754359Sroberto  if (pc_desc == NULL ||
158182007Sroberto      pc_desc->scope_decode_offset() == DebugInformationRecorder::serialized_null) {
15954359Sroberto    // No debug information available for this pc
16054359Sroberto    // vframeStream would explode if we try and walk the frames.
16154359Sroberto    return false;
16254359Sroberto  }
16354359Sroberto
16454359Sroberto  // This PcDesc is useful however we must adjust the frame's pc
16554359Sroberto  // so that the vframeStream lookups will use this same pc
16654359Sroberto  fr->set_pc(pc_desc->real_pc(nm));
16754359Sroberto  return true;
16854359Sroberto}
16954359Sroberto
17054359Sroberto
17154359Sroberto// Determine if 'fr' is a walkable interpreted frame. Returns false
17256746Sroberto// if it is not. *method_p, and *bci_p are not set when false is
17354359Sroberto// returned. *method_p is non-NULL if frame was executing a Java
17454359Sroberto// method. *bci_p is != -1 if a valid BCI in the Java method could
17554359Sroberto// be found.
17654359Sroberto// Note: this method returns true when a valid Java method is found
17754359Sroberto// even if a valid BCI cannot be found.
17854359Sroberto
17954359Srobertostatic bool is_decipherable_interpreted_frame(JavaThread* thread,
18054359Sroberto                                              frame* fr,
18154359Sroberto                                              methodOop* method_p,
18254359Sroberto                                              int* bci_p) {
18354359Sroberto  assert(fr->is_interpreted_frame(), "just checking");
18454359Sroberto
18554359Sroberto  // top frame is an interpreted frame
18654359Sroberto  // check if it is walkable (i.e. valid methodOop and valid bci)
18754359Sroberto
18854359Sroberto  // Because we may be racing a gc thread the method and/or bci
18954359Sroberto  // of a valid interpreter frame may look bad causing us to
19054359Sroberto  // fail the is_interpreted_frame_valid test. If the thread
19154359Sroberto  // is in any of the following states we are assured that the
19254359Sroberto  // frame is in fact valid and we must have hit the race.
19354359Sroberto
19454359Sroberto  JavaThreadState state = thread->thread_state();
19554359Sroberto  bool known_valid = (state == _thread_in_native ||
19654359Sroberto                      state == _thread_in_vm ||
19754359Sroberto                      state == _thread_blocked );
19854359Sroberto
19954359Sroberto  if (known_valid || fr->is_interpreted_frame_valid(thread)) {
20054359Sroberto
20154359Sroberto    // The frame code should completely validate the frame so that
20254359Sroberto    // references to methodOop and bci are completely safe to access
20354359Sroberto    // If they aren't the frame code should be fixed not this
20454359Sroberto    // code. However since gc isn't locked out the values could be
20554359Sroberto    // stale. This is a race we can never completely win since we can't
20654359Sroberto    // lock out gc so do one last check after retrieving their values
20754359Sroberto    // from the frame for additional safety
20854359Sroberto
20954359Sroberto    methodOop method = fr->interpreter_frame_method();
21054359Sroberto
21154359Sroberto    // We've at least found a method.
21254359Sroberto    // NOTE: there is something to be said for the approach that
21354359Sroberto    // if we don't find a valid bci then the method is not likely
214182007Sroberto    // a valid method. Then again we may have caught an interpreter
215132451Sroberto    // frame in the middle of construction and the bci field is
21654359Sroberto    // not yet valid.
21754359Sroberto
21854359Sroberto    *method_p = method;
21954359Sroberto
22054359Sroberto    // See if gc may have invalidated method since we validated frame
22154359Sroberto
22254359Sroberto    if (!Universe::heap()->is_valid_method(method)) return false;
223132451Sroberto
224182007Sroberto    intptr_t bcx = fr->interpreter_frame_bcx();
22554359Sroberto
22654359Sroberto    int      bci = method->validate_bci_from_bcx(bcx);
22754359Sroberto
22854359Sroberto    // note: bci is set to -1 if not a valid bci
22954359Sroberto    *bci_p = bci;
230132451Sroberto    return true;
23154359Sroberto  }
23254359Sroberto
23354359Sroberto  return false;
23454359Sroberto}
23554359Sroberto
23654359Sroberto
23754359Sroberto// Determine if 'fr' can be used to find an initial Java frame.
23854359Sroberto// Return false if it can not find a fully decipherable Java frame
23954359Sroberto// (in other words a frame that isn't safe to use in a vframe stream).
24054359Sroberto// Obviously if it can't even find a Java frame false will also be returned.
241182007Sroberto//
24254359Sroberto// If we find a Java frame decipherable or not then by definition we have
24354359Sroberto// identified a method and that will be returned to the caller via method_p.
24454359Sroberto// If we can determine a bci that is returned also. (Hmm is it possible
24554359Sroberto// to return a method and bci and still return false? )
24654359Sroberto//
24754359Sroberto// The initial Java frame we find (if any) is return via initial_frame_p.
24854359Sroberto//
24954359Sroberto
25054359Srobertostatic bool find_initial_Java_frame(JavaThread* thread,
25154359Sroberto                                    frame* fr,
25254359Sroberto                                    frame* initial_frame_p,
25354359Sroberto                                    methodOop* method_p,
25454359Sroberto                                    int* bci_p) {
25554359Sroberto
25654359Sroberto  // It is possible that for a frame containing an nmethod
25754359Sroberto  // we can capture the method but no bci. If we get no
25854359Sroberto  // bci the frame isn't walkable but the method is usable.
25954359Sroberto  // Therefore we init the returned methodOop to NULL so the
26054359Sroberto  // caller can make the distinction.
26154359Sroberto
26254359Sroberto  *method_p = NULL;
26354359Sroberto
26454359Sroberto  // On the initial call to this method the frame we get may not be
26554359Sroberto  // recognizable to us. This should only happen if we are in a JRT_LEAF
26654359Sroberto  // or something called by a JRT_LEAF method.
26754359Sroberto
26854359Sroberto
26954359Sroberto
27054359Sroberto  frame candidate = *fr;
27154359Sroberto
27254359Sroberto  // If the starting frame we were given has no codeBlob associated with
273182007Sroberto  // it see if we can find such a frame because only frames with codeBlobs
27454359Sroberto  // are possible Java frames.
27554359Sroberto
27654359Sroberto  if (fr->cb() == NULL) {
27754359Sroberto
27854359Sroberto    // See if we can find a useful frame
27954359Sroberto    int loop_count;
28054359Sroberto    int loop_max = MaxJavaStackTraceDepth * 2;
28154359Sroberto    RegisterMap map(thread, false);
28254359Sroberto
28354359Sroberto    for (loop_count = 0; loop_count < loop_max; loop_count++) {
28454359Sroberto      if (!candidate.safe_for_sender(thread)) return false;
28554359Sroberto      candidate = candidate.sender(&map);
28654359Sroberto      if (candidate.cb() != NULL) break;
28754359Sroberto    }
28854359Sroberto    if (candidate.cb() == NULL) return false;
28954359Sroberto  }
29054359Sroberto
29154359Sroberto  // We have a frame known to be in the codeCache
29254359Sroberto  // We will hopefully be able to figure out something to do with it.
29354359Sroberto  int loop_count;
29454359Sroberto  int loop_max = MaxJavaStackTraceDepth * 2;
29554359Sroberto  RegisterMap map(thread, false);
29654359Sroberto
29754359Sroberto  for (loop_count = 0; loop_count < loop_max; loop_count++) {
29854359Sroberto
29954359Sroberto    if (candidate.is_first_frame()) {
30054359Sroberto      // If initial frame is frame from StubGenerator and there is no
30154359Sroberto      // previous anchor, there are no java frames associated with a method
30254359Sroberto      return false;
30354359Sroberto    }
30454359Sroberto
30554359Sroberto    if (candidate.is_interpreted_frame()) {
30654359Sroberto      if (is_decipherable_interpreted_frame(thread, &candidate, method_p, bci_p)) {
30754359Sroberto        *initial_frame_p = candidate;
30854359Sroberto        return true;
30954359Sroberto      }
31054359Sroberto
31154359Sroberto      // Hopefully we got some data
31254359Sroberto      return false;
31354359Sroberto    }
31454359Sroberto
31554359Sroberto    if (candidate.cb()->is_nmethod()) {
31654359Sroberto
31754359Sroberto      nmethod* nm = (nmethod*) candidate.cb();
31854359Sroberto      *method_p = nm->method();
31954359Sroberto
32054359Sroberto      // If the frame isn't fully decipherable then the default
32154359Sroberto      // value for the bci is a signal that we don't have a bci.
32254359Sroberto      // If we have a decipherable frame this bci value will
32354359Sroberto      // not be used.
32454359Sroberto
32554359Sroberto      *bci_p = -1;
32654359Sroberto
327182007Sroberto      *initial_frame_p = candidate;
32854359Sroberto
32954359Sroberto      // Native wrapper code is trivial to decode by vframeStream
33054359Sroberto
33154359Sroberto      if (nm->is_native_method()) return true;
332182007Sroberto
333132451Sroberto      // If it isn't decipherable then we have found a pc that doesn't
33454359Sroberto      // have a PCDesc that can get us a bci however we did find
33554359Sroberto      // a method
33654359Sroberto
33754359Sroberto      if (!is_decipherable_compiled_frame(thread, &candidate, nm)) {
33854359Sroberto        return false;
33954359Sroberto      }
34054359Sroberto
34154359Sroberto      // is_decipherable_compiled_frame may modify candidate's pc
342132451Sroberto      *initial_frame_p = candidate;
34354359Sroberto
34454359Sroberto      assert(nm->pc_desc_at(candidate.pc()) != NULL, "if it's decipherable then pc must be valid");
34554359Sroberto
34654359Sroberto      return true;
34754359Sroberto    }
34854359Sroberto
34954359Sroberto    // Must be some stub frame that we don't care about
35054359Sroberto
35154359Sroberto    if (!candidate.safe_for_sender(thread)) return false;
35254359Sroberto    candidate = candidate.sender(&map);
35354359Sroberto
35454359Sroberto    // If it isn't in the code cache something is wrong
35554359Sroberto    // since once we find a frame in the code cache they
35654359Sroberto    // all should be there.
35754359Sroberto
358182007Sroberto    if (candidate.cb() == NULL) return false;
359182007Sroberto
360182007Sroberto  }
361182007Sroberto
362182007Sroberto  return false;
363182007Sroberto
36454359Sroberto}
36554359Sroberto
36654359Sroberto
36754359Sroberto// call frame copied from old .h file and renamed
36854359Srobertotypedef struct {
36954359Sroberto    jint lineno;                      // line number in the source file
37054359Sroberto    jmethodID method_id;              // method executed in this frame
371182007Sroberto} ASGCT_CallFrame;
37254359Sroberto
37354359Sroberto// call trace copied from old .h file and renamed
374132451Srobertotypedef struct {
375132451Sroberto    JNIEnv *env_id;                   // Env where trace was recorded
376132451Sroberto    jint num_frames;                  // number of frames in this trace
377132451Sroberto    ASGCT_CallFrame *frames;          // frames
378132451Sroberto} ASGCT_CallTrace;
379132451Sroberto
38054359Srobertostatic void forte_fill_call_trace_given_top(JavaThread* thd,
38154359Sroberto                                            ASGCT_CallTrace* trace,
38254359Sroberto                                            int depth,
38354359Sroberto                                            frame top_frame) {
38454359Sroberto  NoHandleMark nhm;
38554359Sroberto
38654359Sroberto  frame initial_Java_frame;
38754359Sroberto  methodOop method;
38854359Sroberto  int bci;
38954359Sroberto  int count;
39054359Sroberto
39154359Sroberto  count = 0;
39254359Sroberto  assert(trace->frames != NULL, "trace->frames must be non-NULL");
39354359Sroberto
39454359Sroberto  bool fully_decipherable = find_initial_Java_frame(thd, &top_frame, &initial_Java_frame, &method, &bci);
39554359Sroberto
39654359Sroberto  // The frame might not be walkable but still recovered a method
39754359Sroberto  // (e.g. an nmethod with no scope info for the pc
39854359Sroberto
39954359Sroberto  if (method == NULL) return;
40054359Sroberto
40154359Sroberto  CollectedHeap* ch = Universe::heap();
40254359Sroberto
40354359Sroberto  // The method is not stored GC safe so see if GC became active
40454359Sroberto  // after we entered AsyncGetCallTrace() and before we try to
40554359Sroberto  // use the methodOop.
40654359Sroberto  // Yes, there is still a window after this check and before
40754359Sroberto  // we use methodOop below, but we can't lock out GC so that
40854359Sroberto  // has to be an acceptable risk.
40954359Sroberto  if (!ch->is_valid_method(method)) {
41054359Sroberto    trace->num_frames = ticks_GC_active; // -2
41154359Sroberto    return;
41254359Sroberto  }
41354359Sroberto
41454359Sroberto  // We got a Java frame however it isn't fully decipherable
41554359Sroberto  // so it won't necessarily be safe to use it for the
41654359Sroberto  // initial frame in the vframe stream.
41754359Sroberto
41854359Sroberto  if (!fully_decipherable) {
41954359Sroberto    // Take whatever method the top-frame decoder managed to scrape up.
42054359Sroberto    // We look further at the top frame only if non-safepoint
42154359Sroberto    // debugging information is available.
42254359Sroberto    count++;
42354359Sroberto    trace->num_frames = count;
42454359Sroberto    trace->frames[0].method_id = method->find_jmethod_id_or_null();
42554359Sroberto    if (!method->is_native()) {
42654359Sroberto      trace->frames[0].lineno = bci;
42754359Sroberto    } else {
42854359Sroberto      trace->frames[0].lineno = -3;
42954359Sroberto    }
43054359Sroberto
43154359Sroberto    if (!initial_Java_frame.safe_for_sender(thd)) return;
43254359Sroberto
43354359Sroberto    RegisterMap map(thd, false);
43454359Sroberto    initial_Java_frame = initial_Java_frame.sender(&map);
43554359Sroberto  }
43654359Sroberto
43754359Sroberto  vframeStreamForte st(thd, initial_Java_frame, false);
43854359Sroberto
43954359Sroberto  for (; !st.at_end() && count < depth; st.forte_next(), count++) {
44054359Sroberto    bci = st.bci();
44154359Sroberto    method = st.method();
44254359Sroberto
44354359Sroberto    // The method is not stored GC safe so see if GC became active
44454359Sroberto    // after we entered AsyncGetCallTrace() and before we try to
44554359Sroberto    // use the methodOop.
44654359Sroberto    // Yes, there is still a window after this check and before
44754359Sroberto    // we use methodOop below, but we can't lock out GC so that
44854359Sroberto    // has to be an acceptable risk.
44954359Sroberto    if (!ch->is_valid_method(method)) {
45054359Sroberto      // we throw away everything we've gathered in this sample since
45154359Sroberto      // none of it is safe
45254359Sroberto      trace->num_frames = ticks_GC_active; // -2
45354359Sroberto      return;
45454359Sroberto    }
45554359Sroberto
45654359Sroberto    trace->frames[count].method_id = method->find_jmethod_id_or_null();
45754359Sroberto    if (!method->is_native()) {
458182007Sroberto      trace->frames[count].lineno = bci;
459132451Sroberto    } else {
46054359Sroberto      trace->frames[count].lineno = -3;
46154359Sroberto    }
46254359Sroberto  }
46354359Sroberto  trace->num_frames = count;
46454359Sroberto  return;
46554359Sroberto}
466182007Sroberto
467182007Sroberto
468182007Sroberto// Forte Analyzer AsyncGetCallTrace() entry point. Currently supported
469182007Sroberto// on Linux X86, Solaris SPARC and Solaris X86.
47054359Sroberto//
471182007Sroberto// Async-safe version of GetCallTrace being called from a signal handler
47254359Sroberto// when a LWP gets interrupted by SIGPROF but the stack traces are filled
47354359Sroberto// with different content (see below).
47454359Sroberto//
47554359Sroberto// This function must only be called when JVM/TI
47654359Sroberto// CLASS_LOAD events have been enabled since agent startup. The enabled
47754359Sroberto// event will cause the jmethodIDs to be allocated at class load time.
47854359Sroberto// The jmethodIDs cannot be allocated in a signal handler because locks
47954359Sroberto// cannot be grabbed in a signal handler safely.
48054359Sroberto//
48154359Sroberto// void (*AsyncGetCallTrace)(ASGCT_CallTrace *trace, jint depth, void* ucontext)
48254359Sroberto//
48354359Sroberto// Called by the profiler to obtain the current method call stack trace for
48454359Sroberto// a given thread. The thread is identified by the env_id field in the
48554359Sroberto// ASGCT_CallTrace structure. The profiler agent should allocate a ASGCT_CallTrace
48654359Sroberto// structure with enough memory for the requested stack depth. The VM fills in
48754359Sroberto// the frames buffer and the num_frames field.
48854359Sroberto//
48954359Sroberto// Arguments:
49054359Sroberto//
49154359Sroberto//   trace    - trace data structure to be filled by the VM.
49254359Sroberto//   depth    - depth of the call stack trace.
49354359Sroberto//   ucontext - ucontext_t of the LWP
49454359Sroberto//
49554359Sroberto// ASGCT_CallTrace:
49654359Sroberto//   typedef struct {
49754359Sroberto//       JNIEnv *env_id;
49854359Sroberto//       jint num_frames;
49954359Sroberto//       ASGCT_CallFrame *frames;
50054359Sroberto//   } ASGCT_CallTrace;
50154359Sroberto//
50254359Sroberto// Fields:
50354359Sroberto//   env_id     - ID of thread which executed this trace.
50454359Sroberto//   num_frames - number of frames in the trace.
50582498Sroberto//                (< 0 indicates the frame is not walkable).
50654359Sroberto//   frames     - the ASGCT_CallFrames that make up this trace. Callee followed by callers.
50754359Sroberto//
50854359Sroberto//  ASGCT_CallFrame:
50954359Sroberto//    typedef struct {
51054359Sroberto//        jint lineno;
51154359Sroberto//        jmethodID method_id;
51254359Sroberto//    } ASGCT_CallFrame;
51354359Sroberto//
51454359Sroberto//  Fields:
51554359Sroberto//    1) For Java frame (interpreted and compiled),
51654359Sroberto//       lineno    - bci of the method being executed or -1 if bci is not available
51754359Sroberto//       method_id - jmethodID of the method being executed
51854359Sroberto//    2) For native method
51954359Sroberto//       lineno    - (-3)
52054359Sroberto//       method_id - jmethodID of the method being executed
52154359Sroberto
52254359Srobertoextern "C" {
52354359SrobertoJNIEXPORT
52454359Srobertovoid AsyncGetCallTrace(ASGCT_CallTrace *trace, jint depth, void* ucontext) {
52554359Sroberto  JavaThread* thread;
52654359Sroberto
52754359Sroberto  if (trace->env_id == NULL ||
52854359Sroberto    (thread = JavaThread::thread_from_jni_environment(trace->env_id)) == NULL ||
52954359Sroberto    thread->is_exiting()) {
53054359Sroberto
53154359Sroberto    // bad env_id, thread has exited or thread is exiting
53254359Sroberto    trace->num_frames = ticks_thread_exit; // -8
53354359Sroberto    return;
53454359Sroberto  }
53554359Sroberto
53654359Sroberto  if (thread->in_deopt_handler()) {
53754359Sroberto    // thread is in the deoptimization handler so return no frames
53854359Sroberto    trace->num_frames = ticks_deopt; // -9
53982498Sroberto    return;
54054359Sroberto  }
54154359Sroberto
54282498Sroberto  assert(JavaThread::current() == thread,
54354359Sroberto         "AsyncGetCallTrace must be called by the current interrupted thread");
544182007Sroberto
545182007Sroberto  if (!JvmtiExport::should_post_class_load()) {
54654359Sroberto    trace->num_frames = ticks_no_class_load; // -1
54754359Sroberto    return;
54854359Sroberto  }
54954359Sroberto
55054359Sroberto  if (Universe::heap()->is_gc_active()) {
55154359Sroberto    trace->num_frames = ticks_GC_active; // -2
55254359Sroberto    return;
55354359Sroberto  }
55454359Sroberto
55554359Sroberto  switch (thread->thread_state()) {
55654359Sroberto  case _thread_new:
55754359Sroberto  case _thread_uninitialized:
55854359Sroberto  case _thread_new_trans:
55954359Sroberto    // We found the thread on the threads list above, but it is too
56054359Sroberto    // young to be useful so return that there are no Java frames.
56154359Sroberto    trace->num_frames = 0;
56254359Sroberto    break;
56354359Sroberto  case _thread_in_native:
56454359Sroberto  case _thread_in_native_trans:
56554359Sroberto  case _thread_blocked:
56654359Sroberto  case _thread_blocked_trans:
56754359Sroberto  case _thread_in_vm:
56854359Sroberto  case _thread_in_vm_trans:
56954359Sroberto    {
57054359Sroberto      frame fr;
571132451Sroberto
572132451Sroberto      // param isInJava == false - indicate we aren't in Java code
57354359Sroberto      if (!thread->pd_get_top_frame_for_signal_handler(&fr, ucontext, false)) {
57454359Sroberto        trace->num_frames = ticks_unknown_not_Java;  // -3 unknown frame
575132451Sroberto      } else {
57654359Sroberto        if (!thread->has_last_Java_frame()) {
57754359Sroberto          trace->num_frames = 0; // No Java frames
578182007Sroberto        } else {
579182007Sroberto          trace->num_frames = ticks_not_walkable_not_Java;    // -4 non walkable frame by default
58054359Sroberto          forte_fill_call_trace_given_top(thread, trace, depth, fr);
58154359Sroberto
582182007Sroberto          // This assert would seem to be valid but it is not.
58354359Sroberto          // It would be valid if we weren't possibly racing a gc
58454359Sroberto          // thread. A gc thread can make a valid interpreted frame
58554359Sroberto          // look invalid. It's a small window but it does happen.
58654359Sroberto          // The assert is left here commented out as a reminder.
58754359Sroberto          // assert(trace->num_frames != ticks_not_walkable_not_Java, "should always be walkable");
58854359Sroberto
589182007Sroberto        }
59054359Sroberto      }
591182007Sroberto    }
59254359Sroberto    break;
59354359Sroberto  case _thread_in_Java:
59454359Sroberto  case _thread_in_Java_trans:
59554359Sroberto    {
596182007Sroberto      frame fr;
597132451Sroberto
59854359Sroberto      // param isInJava == true - indicate we are in Java code
599182007Sroberto      if (!thread->pd_get_top_frame_for_signal_handler(&fr, ucontext, true)) {
60054359Sroberto        trace->num_frames = ticks_unknown_Java;  // -5 unknown frame
60154359Sroberto      } else {
60254359Sroberto        trace->num_frames = ticks_not_walkable_Java;  // -6, non walkable frame by default
60354359Sroberto        forte_fill_call_trace_given_top(thread, trace, depth, fr);
604182007Sroberto      }
605182007Sroberto    }
60654359Sroberto    break;
607182007Sroberto  default:
60854359Sroberto    // Unknown thread state
609182007Sroberto    trace->num_frames = ticks_unknown_state; // -7
61054359Sroberto    break;
611132451Sroberto  }
61254359Sroberto}
61354359Sroberto
61454359Sroberto
61554359Sroberto#ifndef _WINDOWS
61654359Sroberto// Support for the Forte(TM) Peformance Tools collector.
61754359Sroberto//
618182007Sroberto// The method prototype is derived from libcollector.h. For more
61954359Sroberto// information, please see the libcollect man page.
620132451Sroberto
62154359Sroberto// Method to let libcollector know about a dynamically loaded function.
62254359Sroberto// Because it is weakly bound, the calls become NOP's when the library
62354359Sroberto// isn't present.
62454359Sroberto#ifdef __APPLE__
62554359Sroberto// XXXDARWIN: Link errors occur even when __attribute__((weak_import))
62654359Sroberto// is added
62754359Sroberto#define collector_func_load(x0,x1,x2,x3,x4,x5,x6) (0)
62854359Sroberto#else
62954359Srobertovoid    collector_func_load(char* name,
63054359Sroberto                            void* null_argument_1,
63154359Sroberto                            void* null_argument_2,
63254359Sroberto                            void *vaddr,
633182007Sroberto                            int size,
63454359Sroberto                            int zero_argument,
63554359Sroberto                            void* null_argument_3);
63654359Sroberto#pragma weak collector_func_load
63754359Sroberto#define collector_func_load(x0,x1,x2,x3,x4,x5,x6) \
63854359Sroberto        ( collector_func_load ? collector_func_load(x0,x1,x2,x3,x4,x5,x6),0 : 0 )
63954359Sroberto#endif // __APPLE__
640182007Sroberto#endif // !_WINDOWS
641182007Sroberto
642182007Sroberto} // end extern "C"
64354359Sroberto#endif // !IA64
64454359Sroberto
645182007Srobertovoid Forte::register_stub(const char* name, address start, address end) {
64654359Sroberto#if !defined(_WINDOWS) && !defined(IA64)
64754359Sroberto  assert(pointer_delta(end, start, sizeof(jbyte)) < INT_MAX,
64854359Sroberto         "Code size exceeds maximum range");
64954359Sroberto
65054359Sroberto  collector_func_load((char*)name, NULL, NULL, start,
65154359Sroberto    pointer_delta(end, start, sizeof(jbyte)), 0, NULL);
65254359Sroberto#endif // !_WINDOWS && !IA64
65354359Sroberto}
65454359Sroberto