1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/share/vm/prims/forte.cpp Wed Apr 27 01:25:04 2016 +0800 1.3 @@ -0,0 +1,651 @@ 1.4 +/* 1.5 + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. 1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.7 + * 1.8 + * This code is free software; you can redistribute it and/or modify it 1.9 + * under the terms of the GNU General Public License version 2 only, as 1.10 + * published by the Free Software Foundation. 1.11 + * 1.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 1.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.15 + * version 2 for more details (a copy is included in the LICENSE file that 1.16 + * accompanied this code). 1.17 + * 1.18 + * You should have received a copy of the GNU General Public License version 1.19 + * 2 along with this work; if not, write to the Free Software Foundation, 1.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.21 + * 1.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 1.23 + * or visit www.oracle.com if you need additional information or have any 1.24 + * questions. 1.25 + * 1.26 + */ 1.27 + 1.28 +#include "precompiled.hpp" 1.29 +#include "code/debugInfoRec.hpp" 1.30 +#include "code/pcDesc.hpp" 1.31 +#include "gc_interface/collectedHeap.inline.hpp" 1.32 +#include "memory/space.hpp" 1.33 +#include "memory/universe.inline.hpp" 1.34 +#include "oops/oop.inline.hpp" 1.35 +#include "oops/oop.inline2.hpp" 1.36 +#include "prims/forte.hpp" 1.37 +#include "runtime/javaCalls.hpp" 1.38 +#include "runtime/thread.hpp" 1.39 +#include "runtime/vframe.hpp" 1.40 +#include "runtime/vframeArray.hpp" 1.41 + 1.42 +// call frame copied from old .h file and renamed 1.43 +typedef struct { 1.44 + jint lineno; // line number in the source file 1.45 + jmethodID method_id; // method executed in this frame 1.46 +} ASGCT_CallFrame; 1.47 + 1.48 +// call trace copied from old .h file and renamed 1.49 +typedef struct { 1.50 + JNIEnv *env_id; // Env where trace was recorded 1.51 + jint num_frames; // number of frames in this trace 1.52 + ASGCT_CallFrame *frames; // frames 1.53 +} ASGCT_CallTrace; 1.54 + 1.55 +// These name match the names reported by the forte quality kit 1.56 +enum { 1.57 + ticks_no_Java_frame = 0, 1.58 + ticks_no_class_load = -1, 1.59 + ticks_GC_active = -2, 1.60 + ticks_unknown_not_Java = -3, 1.61 + ticks_not_walkable_not_Java = -4, 1.62 + ticks_unknown_Java = -5, 1.63 + ticks_not_walkable_Java = -6, 1.64 + ticks_unknown_state = -7, 1.65 + ticks_thread_exit = -8, 1.66 + ticks_deopt = -9, 1.67 + ticks_safepoint = -10 1.68 +}; 1.69 + 1.70 +#if INCLUDE_JVMTI 1.71 + 1.72 +//------------------------------------------------------- 1.73 + 1.74 +// Native interfaces for use by Forte tools. 1.75 + 1.76 + 1.77 +#if !defined(IA64) && !defined(PPC64) 1.78 + 1.79 +class vframeStreamForte : public vframeStreamCommon { 1.80 + public: 1.81 + // constructor that starts with sender of frame fr (top_frame) 1.82 + vframeStreamForte(JavaThread *jt, frame fr, bool stop_at_java_call_stub); 1.83 + void forte_next(); 1.84 +}; 1.85 + 1.86 + 1.87 +static bool is_decipherable_compiled_frame(JavaThread* thread, frame* fr, nmethod* nm); 1.88 +static bool is_decipherable_interpreted_frame(JavaThread* thread, 1.89 + frame* fr, 1.90 + Method** method_p, 1.91 + int* bci_p); 1.92 + 1.93 + 1.94 + 1.95 + 1.96 +vframeStreamForte::vframeStreamForte(JavaThread *jt, 1.97 + frame fr, 1.98 + bool stop_at_java_call_stub) : vframeStreamCommon(jt) { 1.99 + 1.100 + _stop_at_java_call_stub = stop_at_java_call_stub; 1.101 + _frame = fr; 1.102 + 1.103 + // We must always have a valid frame to start filling 1.104 + 1.105 + bool filled_in = fill_from_frame(); 1.106 + 1.107 + assert(filled_in, "invariant"); 1.108 + 1.109 +} 1.110 + 1.111 + 1.112 +// Solaris SPARC Compiler1 needs an additional check on the grandparent 1.113 +// of the top_frame when the parent of the top_frame is interpreted and 1.114 +// the grandparent is compiled. However, in this method we do not know 1.115 +// the relationship of the current _frame relative to the top_frame so 1.116 +// we implement a more broad sanity check. When the previous callee is 1.117 +// interpreted and the current sender is compiled, we verify that the 1.118 +// current sender is also walkable. If it is not walkable, then we mark 1.119 +// the current vframeStream as at the end. 1.120 +void vframeStreamForte::forte_next() { 1.121 + // handle frames with inlining 1.122 + if (_mode == compiled_mode && 1.123 + vframeStreamCommon::fill_in_compiled_inlined_sender()) { 1.124 + return; 1.125 + } 1.126 + 1.127 + // handle general case 1.128 + 1.129 + int loop_count = 0; 1.130 + int loop_max = MaxJavaStackTraceDepth * 2; 1.131 + 1.132 + 1.133 + do { 1.134 + 1.135 + loop_count++; 1.136 + 1.137 + // By the time we get here we should never see unsafe but better 1.138 + // safe then segv'd 1.139 + 1.140 + if (loop_count > loop_max || !_frame.safe_for_sender(_thread)) { 1.141 + _mode = at_end_mode; 1.142 + return; 1.143 + } 1.144 + 1.145 + _frame = _frame.sender(&_reg_map); 1.146 + 1.147 + } while (!fill_from_frame()); 1.148 +} 1.149 + 1.150 +// Determine if 'fr' is a decipherable compiled frame. We are already 1.151 +// assured that fr is for a java nmethod. 1.152 + 1.153 +static bool is_decipherable_compiled_frame(JavaThread* thread, frame* fr, nmethod* nm) { 1.154 + assert(nm->is_java_method(), "invariant"); 1.155 + 1.156 + if (thread->has_last_Java_frame() && thread->last_Java_pc() == fr->pc()) { 1.157 + // We're stopped at a call into the JVM so look for a PcDesc with 1.158 + // the actual pc reported by the frame. 1.159 + PcDesc* pc_desc = nm->pc_desc_at(fr->pc()); 1.160 + 1.161 + // Did we find a useful PcDesc? 1.162 + if (pc_desc != NULL && 1.163 + pc_desc->scope_decode_offset() != DebugInformationRecorder::serialized_null) { 1.164 + return true; 1.165 + } 1.166 + } 1.167 + 1.168 + // We're at some random pc in the nmethod so search for the PcDesc 1.169 + // whose pc is greater than the current PC. It's done this way 1.170 + // because the extra PcDescs that are recorded for improved debug 1.171 + // info record the end of the region covered by the ScopeDesc 1.172 + // instead of the beginning. 1.173 + PcDesc* pc_desc = nm->pc_desc_near(fr->pc() + 1); 1.174 + 1.175 + // Now do we have a useful PcDesc? 1.176 + if (pc_desc == NULL || 1.177 + pc_desc->scope_decode_offset() == DebugInformationRecorder::serialized_null) { 1.178 + // No debug information available for this pc 1.179 + // vframeStream would explode if we try and walk the frames. 1.180 + return false; 1.181 + } 1.182 + 1.183 + // This PcDesc is useful however we must adjust the frame's pc 1.184 + // so that the vframeStream lookups will use this same pc 1.185 + fr->set_pc(pc_desc->real_pc(nm)); 1.186 + return true; 1.187 +} 1.188 + 1.189 + 1.190 +// Determine if 'fr' is a walkable interpreted frame. Returns false 1.191 +// if it is not. *method_p, and *bci_p are not set when false is 1.192 +// returned. *method_p is non-NULL if frame was executing a Java 1.193 +// method. *bci_p is != -1 if a valid BCI in the Java method could 1.194 +// be found. 1.195 +// Note: this method returns true when a valid Java method is found 1.196 +// even if a valid BCI cannot be found. 1.197 + 1.198 +static bool is_decipherable_interpreted_frame(JavaThread* thread, 1.199 + frame* fr, 1.200 + Method** method_p, 1.201 + int* bci_p) { 1.202 + assert(fr->is_interpreted_frame(), "just checking"); 1.203 + 1.204 + // top frame is an interpreted frame 1.205 + // check if it is walkable (i.e. valid Method* and valid bci) 1.206 + 1.207 + // Because we may be racing a gc thread the method and/or bci 1.208 + // of a valid interpreter frame may look bad causing us to 1.209 + // fail the is_interpreted_frame_valid test. If the thread 1.210 + // is in any of the following states we are assured that the 1.211 + // frame is in fact valid and we must have hit the race. 1.212 + 1.213 + JavaThreadState state = thread->thread_state(); 1.214 + bool known_valid = (state == _thread_in_native || 1.215 + state == _thread_in_vm || 1.216 + state == _thread_blocked ); 1.217 + 1.218 + if (known_valid || fr->is_interpreted_frame_valid(thread)) { 1.219 + 1.220 + // The frame code should completely validate the frame so that 1.221 + // references to Method* and bci are completely safe to access 1.222 + // If they aren't the frame code should be fixed not this 1.223 + // code. However since gc isn't locked out the values could be 1.224 + // stale. This is a race we can never completely win since we can't 1.225 + // lock out gc so do one last check after retrieving their values 1.226 + // from the frame for additional safety 1.227 + 1.228 + Method* method = fr->interpreter_frame_method(); 1.229 + 1.230 + // We've at least found a method. 1.231 + // NOTE: there is something to be said for the approach that 1.232 + // if we don't find a valid bci then the method is not likely 1.233 + // a valid method. Then again we may have caught an interpreter 1.234 + // frame in the middle of construction and the bci field is 1.235 + // not yet valid. 1.236 + 1.237 + *method_p = method; 1.238 + if (!method->is_valid_method()) return false; 1.239 + 1.240 + intptr_t bcx = fr->interpreter_frame_bcx(); 1.241 + 1.242 + int bci = method->validate_bci_from_bcx(bcx); 1.243 + 1.244 + // note: bci is set to -1 if not a valid bci 1.245 + *bci_p = bci; 1.246 + return true; 1.247 + } 1.248 + 1.249 + return false; 1.250 +} 1.251 + 1.252 + 1.253 +// Determine if 'fr' can be used to find an initial Java frame. 1.254 +// Return false if it can not find a fully decipherable Java frame 1.255 +// (in other words a frame that isn't safe to use in a vframe stream). 1.256 +// Obviously if it can't even find a Java frame false will also be returned. 1.257 +// 1.258 +// If we find a Java frame decipherable or not then by definition we have 1.259 +// identified a method and that will be returned to the caller via method_p. 1.260 +// If we can determine a bci that is returned also. (Hmm is it possible 1.261 +// to return a method and bci and still return false? ) 1.262 +// 1.263 +// The initial Java frame we find (if any) is return via initial_frame_p. 1.264 +// 1.265 + 1.266 +static bool find_initial_Java_frame(JavaThread* thread, 1.267 + frame* fr, 1.268 + frame* initial_frame_p, 1.269 + Method** method_p, 1.270 + int* bci_p) { 1.271 + 1.272 + // It is possible that for a frame containing an nmethod 1.273 + // we can capture the method but no bci. If we get no 1.274 + // bci the frame isn't walkable but the method is usable. 1.275 + // Therefore we init the returned Method* to NULL so the 1.276 + // caller can make the distinction. 1.277 + 1.278 + *method_p = NULL; 1.279 + 1.280 + // On the initial call to this method the frame we get may not be 1.281 + // recognizable to us. This should only happen if we are in a JRT_LEAF 1.282 + // or something called by a JRT_LEAF method. 1.283 + 1.284 + 1.285 + 1.286 + frame candidate = *fr; 1.287 + 1.288 + // If the starting frame we were given has no codeBlob associated with 1.289 + // it see if we can find such a frame because only frames with codeBlobs 1.290 + // are possible Java frames. 1.291 + 1.292 + if (fr->cb() == NULL) { 1.293 + 1.294 + // See if we can find a useful frame 1.295 + int loop_count; 1.296 + int loop_max = MaxJavaStackTraceDepth * 2; 1.297 + RegisterMap map(thread, false); 1.298 + 1.299 + for (loop_count = 0; loop_count < loop_max; loop_count++) { 1.300 + if (!candidate.safe_for_sender(thread)) return false; 1.301 + candidate = candidate.sender(&map); 1.302 + if (candidate.cb() != NULL) break; 1.303 + } 1.304 + if (candidate.cb() == NULL) return false; 1.305 + } 1.306 + 1.307 + // We have a frame known to be in the codeCache 1.308 + // We will hopefully be able to figure out something to do with it. 1.309 + int loop_count; 1.310 + int loop_max = MaxJavaStackTraceDepth * 2; 1.311 + RegisterMap map(thread, false); 1.312 + 1.313 + for (loop_count = 0; loop_count < loop_max; loop_count++) { 1.314 + 1.315 + if (candidate.is_entry_frame()) { 1.316 + // jcw is NULL if the java call wrapper couldn't be found 1.317 + JavaCallWrapper *jcw = candidate.entry_frame_call_wrapper_if_safe(thread); 1.318 + // If initial frame is frame from StubGenerator and there is no 1.319 + // previous anchor, there are no java frames associated with a method 1.320 + if (jcw == NULL || jcw->is_first_frame()) { 1.321 + return false; 1.322 + } 1.323 + } 1.324 + 1.325 + if (candidate.is_interpreted_frame()) { 1.326 + if (is_decipherable_interpreted_frame(thread, &candidate, method_p, bci_p)) { 1.327 + *initial_frame_p = candidate; 1.328 + return true; 1.329 + } 1.330 + 1.331 + // Hopefully we got some data 1.332 + return false; 1.333 + } 1.334 + 1.335 + if (candidate.cb()->is_nmethod()) { 1.336 + 1.337 + nmethod* nm = (nmethod*) candidate.cb(); 1.338 + *method_p = nm->method(); 1.339 + 1.340 + // If the frame isn't fully decipherable then the default 1.341 + // value for the bci is a signal that we don't have a bci. 1.342 + // If we have a decipherable frame this bci value will 1.343 + // not be used. 1.344 + 1.345 + *bci_p = -1; 1.346 + 1.347 + *initial_frame_p = candidate; 1.348 + 1.349 + // Native wrapper code is trivial to decode by vframeStream 1.350 + 1.351 + if (nm->is_native_method()) return true; 1.352 + 1.353 + // If it isn't decipherable then we have found a pc that doesn't 1.354 + // have a PCDesc that can get us a bci however we did find 1.355 + // a method 1.356 + 1.357 + if (!is_decipherable_compiled_frame(thread, &candidate, nm)) { 1.358 + return false; 1.359 + } 1.360 + 1.361 + // is_decipherable_compiled_frame may modify candidate's pc 1.362 + *initial_frame_p = candidate; 1.363 + 1.364 + assert(nm->pc_desc_at(candidate.pc()) != NULL, "if it's decipherable then pc must be valid"); 1.365 + 1.366 + return true; 1.367 + } 1.368 + 1.369 + // Must be some stub frame that we don't care about 1.370 + 1.371 + if (!candidate.safe_for_sender(thread)) return false; 1.372 + candidate = candidate.sender(&map); 1.373 + 1.374 + // If it isn't in the code cache something is wrong 1.375 + // since once we find a frame in the code cache they 1.376 + // all should be there. 1.377 + 1.378 + if (candidate.cb() == NULL) return false; 1.379 + 1.380 + } 1.381 + 1.382 + return false; 1.383 + 1.384 +} 1.385 + 1.386 +static void forte_fill_call_trace_given_top(JavaThread* thd, 1.387 + ASGCT_CallTrace* trace, 1.388 + int depth, 1.389 + frame top_frame) { 1.390 + NoHandleMark nhm; 1.391 + 1.392 + frame initial_Java_frame; 1.393 + Method* method; 1.394 + int bci; 1.395 + int count; 1.396 + 1.397 + count = 0; 1.398 + assert(trace->frames != NULL, "trace->frames must be non-NULL"); 1.399 + 1.400 + bool fully_decipherable = find_initial_Java_frame(thd, &top_frame, &initial_Java_frame, &method, &bci); 1.401 + 1.402 + // The frame might not be walkable but still recovered a method 1.403 + // (e.g. an nmethod with no scope info for the pc) 1.404 + 1.405 + if (method == NULL) return; 1.406 + 1.407 + if (!method->is_valid_method()) { 1.408 + trace->num_frames = ticks_GC_active; // -2 1.409 + return; 1.410 + } 1.411 + 1.412 + // We got a Java frame however it isn't fully decipherable 1.413 + // so it won't necessarily be safe to use it for the 1.414 + // initial frame in the vframe stream. 1.415 + 1.416 + if (!fully_decipherable) { 1.417 + // Take whatever method the top-frame decoder managed to scrape up. 1.418 + // We look further at the top frame only if non-safepoint 1.419 + // debugging information is available. 1.420 + count++; 1.421 + trace->num_frames = count; 1.422 + trace->frames[0].method_id = method->find_jmethod_id_or_null(); 1.423 + if (!method->is_native()) { 1.424 + trace->frames[0].lineno = bci; 1.425 + } else { 1.426 + trace->frames[0].lineno = -3; 1.427 + } 1.428 + 1.429 + if (!initial_Java_frame.safe_for_sender(thd)) return; 1.430 + 1.431 + RegisterMap map(thd, false); 1.432 + initial_Java_frame = initial_Java_frame.sender(&map); 1.433 + } 1.434 + 1.435 + vframeStreamForte st(thd, initial_Java_frame, false); 1.436 + 1.437 + for (; !st.at_end() && count < depth; st.forte_next(), count++) { 1.438 + bci = st.bci(); 1.439 + method = st.method(); 1.440 + 1.441 + if (!method->is_valid_method()) { 1.442 + // we throw away everything we've gathered in this sample since 1.443 + // none of it is safe 1.444 + trace->num_frames = ticks_GC_active; // -2 1.445 + return; 1.446 + } 1.447 + 1.448 + trace->frames[count].method_id = method->find_jmethod_id_or_null(); 1.449 + if (!method->is_native()) { 1.450 + trace->frames[count].lineno = bci; 1.451 + } else { 1.452 + trace->frames[count].lineno = -3; 1.453 + } 1.454 + } 1.455 + trace->num_frames = count; 1.456 + return; 1.457 +} 1.458 + 1.459 + 1.460 +// Forte Analyzer AsyncGetCallTrace() entry point. Currently supported 1.461 +// on Linux X86, Solaris SPARC and Solaris X86. 1.462 +// 1.463 +// Async-safe version of GetCallTrace being called from a signal handler 1.464 +// when a LWP gets interrupted by SIGPROF but the stack traces are filled 1.465 +// with different content (see below). 1.466 +// 1.467 +// This function must only be called when JVM/TI 1.468 +// CLASS_LOAD events have been enabled since agent startup. The enabled 1.469 +// event will cause the jmethodIDs to be allocated at class load time. 1.470 +// The jmethodIDs cannot be allocated in a signal handler because locks 1.471 +// cannot be grabbed in a signal handler safely. 1.472 +// 1.473 +// void (*AsyncGetCallTrace)(ASGCT_CallTrace *trace, jint depth, void* ucontext) 1.474 +// 1.475 +// Called by the profiler to obtain the current method call stack trace for 1.476 +// a given thread. The thread is identified by the env_id field in the 1.477 +// ASGCT_CallTrace structure. The profiler agent should allocate a ASGCT_CallTrace 1.478 +// structure with enough memory for the requested stack depth. The VM fills in 1.479 +// the frames buffer and the num_frames field. 1.480 +// 1.481 +// Arguments: 1.482 +// 1.483 +// trace - trace data structure to be filled by the VM. 1.484 +// depth - depth of the call stack trace. 1.485 +// ucontext - ucontext_t of the LWP 1.486 +// 1.487 +// ASGCT_CallTrace: 1.488 +// typedef struct { 1.489 +// JNIEnv *env_id; 1.490 +// jint num_frames; 1.491 +// ASGCT_CallFrame *frames; 1.492 +// } ASGCT_CallTrace; 1.493 +// 1.494 +// Fields: 1.495 +// env_id - ID of thread which executed this trace. 1.496 +// num_frames - number of frames in the trace. 1.497 +// (< 0 indicates the frame is not walkable). 1.498 +// frames - the ASGCT_CallFrames that make up this trace. Callee followed by callers. 1.499 +// 1.500 +// ASGCT_CallFrame: 1.501 +// typedef struct { 1.502 +// jint lineno; 1.503 +// jmethodID method_id; 1.504 +// } ASGCT_CallFrame; 1.505 +// 1.506 +// Fields: 1.507 +// 1) For Java frame (interpreted and compiled), 1.508 +// lineno - bci of the method being executed or -1 if bci is not available 1.509 +// method_id - jmethodID of the method being executed 1.510 +// 2) For native method 1.511 +// lineno - (-3) 1.512 +// method_id - jmethodID of the method being executed 1.513 + 1.514 +extern "C" { 1.515 +JNIEXPORT 1.516 +void AsyncGetCallTrace(ASGCT_CallTrace *trace, jint depth, void* ucontext) { 1.517 + JavaThread* thread; 1.518 + 1.519 + if (trace->env_id == NULL || 1.520 + (thread = JavaThread::thread_from_jni_environment(trace->env_id)) == NULL || 1.521 + thread->is_exiting()) { 1.522 + 1.523 + // bad env_id, thread has exited or thread is exiting 1.524 + trace->num_frames = ticks_thread_exit; // -8 1.525 + return; 1.526 + } 1.527 + 1.528 + if (thread->in_deopt_handler()) { 1.529 + // thread is in the deoptimization handler so return no frames 1.530 + trace->num_frames = ticks_deopt; // -9 1.531 + return; 1.532 + } 1.533 + 1.534 + assert(JavaThread::current() == thread, 1.535 + "AsyncGetCallTrace must be called by the current interrupted thread"); 1.536 + 1.537 + if (!JvmtiExport::should_post_class_load()) { 1.538 + trace->num_frames = ticks_no_class_load; // -1 1.539 + return; 1.540 + } 1.541 + 1.542 + if (Universe::heap()->is_gc_active()) { 1.543 + trace->num_frames = ticks_GC_active; // -2 1.544 + return; 1.545 + } 1.546 + 1.547 + switch (thread->thread_state()) { 1.548 + case _thread_new: 1.549 + case _thread_uninitialized: 1.550 + case _thread_new_trans: 1.551 + // We found the thread on the threads list above, but it is too 1.552 + // young to be useful so return that there are no Java frames. 1.553 + trace->num_frames = 0; 1.554 + break; 1.555 + case _thread_in_native: 1.556 + case _thread_in_native_trans: 1.557 + case _thread_blocked: 1.558 + case _thread_blocked_trans: 1.559 + case _thread_in_vm: 1.560 + case _thread_in_vm_trans: 1.561 + { 1.562 + frame fr; 1.563 + 1.564 + // param isInJava == false - indicate we aren't in Java code 1.565 + if (!thread->pd_get_top_frame_for_signal_handler(&fr, ucontext, false)) { 1.566 + trace->num_frames = ticks_unknown_not_Java; // -3 unknown frame 1.567 + } else { 1.568 + if (!thread->has_last_Java_frame()) { 1.569 + trace->num_frames = 0; // No Java frames 1.570 + } else { 1.571 + trace->num_frames = ticks_not_walkable_not_Java; // -4 non walkable frame by default 1.572 + forte_fill_call_trace_given_top(thread, trace, depth, fr); 1.573 + 1.574 + // This assert would seem to be valid but it is not. 1.575 + // It would be valid if we weren't possibly racing a gc 1.576 + // thread. A gc thread can make a valid interpreted frame 1.577 + // look invalid. It's a small window but it does happen. 1.578 + // The assert is left here commented out as a reminder. 1.579 + // assert(trace->num_frames != ticks_not_walkable_not_Java, "should always be walkable"); 1.580 + 1.581 + } 1.582 + } 1.583 + } 1.584 + break; 1.585 + case _thread_in_Java: 1.586 + case _thread_in_Java_trans: 1.587 + { 1.588 + frame fr; 1.589 + 1.590 + // param isInJava == true - indicate we are in Java code 1.591 + if (!thread->pd_get_top_frame_for_signal_handler(&fr, ucontext, true)) { 1.592 + trace->num_frames = ticks_unknown_Java; // -5 unknown frame 1.593 + } else { 1.594 + trace->num_frames = ticks_not_walkable_Java; // -6, non walkable frame by default 1.595 + forte_fill_call_trace_given_top(thread, trace, depth, fr); 1.596 + } 1.597 + } 1.598 + break; 1.599 + default: 1.600 + // Unknown thread state 1.601 + trace->num_frames = ticks_unknown_state; // -7 1.602 + break; 1.603 + } 1.604 +} 1.605 + 1.606 + 1.607 +#ifndef _WINDOWS 1.608 +// Support for the Forte(TM) Peformance Tools collector. 1.609 +// 1.610 +// The method prototype is derived from libcollector.h. For more 1.611 +// information, please see the libcollect man page. 1.612 + 1.613 +// Method to let libcollector know about a dynamically loaded function. 1.614 +// Because it is weakly bound, the calls become NOP's when the library 1.615 +// isn't present. 1.616 +#ifdef __APPLE__ 1.617 +// XXXDARWIN: Link errors occur even when __attribute__((weak_import)) 1.618 +// is added 1.619 +#define collector_func_load(x0,x1,x2,x3,x4,x5,x6) (0) 1.620 +#else 1.621 +void collector_func_load(char* name, 1.622 + void* null_argument_1, 1.623 + void* null_argument_2, 1.624 + void *vaddr, 1.625 + int size, 1.626 + int zero_argument, 1.627 + void* null_argument_3); 1.628 +#pragma weak collector_func_load 1.629 +#define collector_func_load(x0,x1,x2,x3,x4,x5,x6) \ 1.630 + ( collector_func_load ? collector_func_load(x0,x1,x2,x3,x4,x5,x6),(void)0 : (void)0 ) 1.631 +#endif // __APPLE__ 1.632 +#endif // !_WINDOWS 1.633 + 1.634 +} // end extern "C" 1.635 +#endif // !IA64 && !PPC64 1.636 + 1.637 +void Forte::register_stub(const char* name, address start, address end) { 1.638 +#if !defined(_WINDOWS) && !defined(IA64) && !defined(PPC64) 1.639 + assert(pointer_delta(end, start, sizeof(jbyte)) < INT_MAX, 1.640 + "Code size exceeds maximum range"); 1.641 + 1.642 + collector_func_load((char*)name, NULL, NULL, start, 1.643 + pointer_delta(end, start, sizeof(jbyte)), 0, NULL); 1.644 +#endif // !_WINDOWS && !IA64 && !PPC64 1.645 +} 1.646 + 1.647 +#else // INCLUDE_JVMTI 1.648 +extern "C" { 1.649 + JNIEXPORT 1.650 + void AsyncGetCallTrace(ASGCT_CallTrace *trace, jint depth, void* ucontext) { 1.651 + trace->num_frames = ticks_no_class_load; // -1 1.652 + } 1.653 +} 1.654 +#endif // INCLUDE_JVMTI