Thu, 09 Dec 2010 15:04:26 -0500
7004582: Add GetThisObject() function to JVMTI 1.2
Summary: Add 'GetThisObject' function
Reviewed-by: never, coleenp
duke@435 | 1 | /* |
stefank@2314 | 2 | * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. |
duke@435 | 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
duke@435 | 4 | * |
duke@435 | 5 | * This code is free software; you can redistribute it and/or modify it |
duke@435 | 6 | * under the terms of the GNU General Public License version 2 only, as |
duke@435 | 7 | * published by the Free Software Foundation. |
duke@435 | 8 | * |
duke@435 | 9 | * This code is distributed in the hope that it will be useful, but WITHOUT |
duke@435 | 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
duke@435 | 11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
duke@435 | 12 | * version 2 for more details (a copy is included in the LICENSE file that |
duke@435 | 13 | * accompanied this code). |
duke@435 | 14 | * |
duke@435 | 15 | * You should have received a copy of the GNU General Public License version |
duke@435 | 16 | * 2 along with this work; if not, write to the Free Software Foundation, |
duke@435 | 17 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
duke@435 | 18 | * |
trims@1907 | 19 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
trims@1907 | 20 | * or visit www.oracle.com if you need additional information or have any |
trims@1907 | 21 | * questions. |
duke@435 | 22 | * |
duke@435 | 23 | */ |
duke@435 | 24 | |
stefank@2314 | 25 | #include "precompiled.hpp" |
stefank@2314 | 26 | #include "code/debugInfoRec.hpp" |
stefank@2314 | 27 | #include "code/pcDesc.hpp" |
stefank@2314 | 28 | #include "gc_interface/collectedHeap.inline.hpp" |
stefank@2314 | 29 | #include "memory/space.hpp" |
stefank@2314 | 30 | #include "memory/universe.inline.hpp" |
stefank@2314 | 31 | #include "oops/oop.inline.hpp" |
stefank@2314 | 32 | #include "oops/oop.inline2.hpp" |
stefank@2314 | 33 | #include "prims/forte.hpp" |
stefank@2314 | 34 | #include "runtime/thread.hpp" |
stefank@2314 | 35 | #include "runtime/vframe.hpp" |
stefank@2314 | 36 | #include "runtime/vframeArray.hpp" |
duke@435 | 37 | |
sgoldman@542 | 38 | // These name match the names reported by the forte quality kit |
sgoldman@542 | 39 | enum { |
sgoldman@542 | 40 | ticks_no_Java_frame = 0, |
sgoldman@542 | 41 | ticks_no_class_load = -1, |
sgoldman@542 | 42 | ticks_GC_active = -2, |
sgoldman@542 | 43 | ticks_unknown_not_Java = -3, |
sgoldman@542 | 44 | ticks_not_walkable_not_Java = -4, |
sgoldman@542 | 45 | ticks_unknown_Java = -5, |
sgoldman@542 | 46 | ticks_not_walkable_Java = -6, |
sgoldman@542 | 47 | ticks_unknown_state = -7, |
sgoldman@542 | 48 | ticks_thread_exit = -8, |
sgoldman@542 | 49 | ticks_deopt = -9, |
sgoldman@542 | 50 | ticks_safepoint = -10 |
sgoldman@542 | 51 | }; |
duke@435 | 52 | |
duke@435 | 53 | //------------------------------------------------------- |
duke@435 | 54 | |
duke@435 | 55 | // Native interfaces for use by Forte tools. |
duke@435 | 56 | |
duke@435 | 57 | |
duke@435 | 58 | #ifndef IA64 |
duke@435 | 59 | |
duke@435 | 60 | class vframeStreamForte : public vframeStreamCommon { |
duke@435 | 61 | public: |
duke@435 | 62 | // constructor that starts with sender of frame fr (top_frame) |
duke@435 | 63 | vframeStreamForte(JavaThread *jt, frame fr, bool stop_at_java_call_stub); |
duke@435 | 64 | void forte_next(); |
duke@435 | 65 | }; |
duke@435 | 66 | |
duke@435 | 67 | |
never@1784 | 68 | static bool is_decipherable_compiled_frame(JavaThread* thread, frame* fr, nmethod* nm); |
sgoldman@542 | 69 | static bool is_decipherable_interpreted_frame(JavaThread* thread, |
never@1784 | 70 | frame* fr, |
never@1784 | 71 | methodOop* method_p, |
never@1784 | 72 | int* bci_p); |
duke@435 | 73 | |
duke@435 | 74 | |
duke@435 | 75 | |
duke@435 | 76 | |
sgoldman@542 | 77 | vframeStreamForte::vframeStreamForte(JavaThread *jt, |
sgoldman@542 | 78 | frame fr, |
sgoldman@542 | 79 | bool stop_at_java_call_stub) : vframeStreamCommon(jt) { |
duke@435 | 80 | |
sgoldman@542 | 81 | _stop_at_java_call_stub = stop_at_java_call_stub; |
sgoldman@542 | 82 | _frame = fr; |
duke@435 | 83 | |
sgoldman@542 | 84 | // We must always have a valid frame to start filling |
duke@435 | 85 | |
sgoldman@542 | 86 | bool filled_in = fill_from_frame(); |
duke@435 | 87 | |
sgoldman@542 | 88 | assert(filled_in, "invariant"); |
duke@435 | 89 | |
duke@435 | 90 | } |
duke@435 | 91 | |
duke@435 | 92 | |
duke@435 | 93 | // Solaris SPARC Compiler1 needs an additional check on the grandparent |
duke@435 | 94 | // of the top_frame when the parent of the top_frame is interpreted and |
duke@435 | 95 | // the grandparent is compiled. However, in this method we do not know |
duke@435 | 96 | // the relationship of the current _frame relative to the top_frame so |
duke@435 | 97 | // we implement a more broad sanity check. When the previous callee is |
duke@435 | 98 | // interpreted and the current sender is compiled, we verify that the |
duke@435 | 99 | // current sender is also walkable. If it is not walkable, then we mark |
duke@435 | 100 | // the current vframeStream as at the end. |
duke@435 | 101 | void vframeStreamForte::forte_next() { |
duke@435 | 102 | // handle frames with inlining |
duke@435 | 103 | if (_mode == compiled_mode && |
duke@435 | 104 | vframeStreamCommon::fill_in_compiled_inlined_sender()) { |
duke@435 | 105 | return; |
duke@435 | 106 | } |
duke@435 | 107 | |
duke@435 | 108 | // handle general case |
duke@435 | 109 | |
duke@435 | 110 | int loop_count = 0; |
duke@435 | 111 | int loop_max = MaxJavaStackTraceDepth * 2; |
duke@435 | 112 | |
duke@435 | 113 | |
duke@435 | 114 | do { |
duke@435 | 115 | |
sgoldman@542 | 116 | loop_count++; |
duke@435 | 117 | |
sgoldman@542 | 118 | // By the time we get here we should never see unsafe but better |
sgoldman@542 | 119 | // safe then segv'd |
duke@435 | 120 | |
sgoldman@542 | 121 | if (loop_count > loop_max || !_frame.safe_for_sender(_thread)) { |
duke@435 | 122 | _mode = at_end_mode; |
duke@435 | 123 | return; |
duke@435 | 124 | } |
duke@435 | 125 | |
sgoldman@542 | 126 | _frame = _frame.sender(&_reg_map); |
duke@435 | 127 | |
duke@435 | 128 | } while (!fill_from_frame()); |
duke@435 | 129 | } |
duke@435 | 130 | |
sgoldman@542 | 131 | // Determine if 'fr' is a decipherable compiled frame. We are already |
sgoldman@542 | 132 | // assured that fr is for a java nmethod. |
duke@435 | 133 | |
never@1784 | 134 | static bool is_decipherable_compiled_frame(JavaThread* thread, frame* fr, nmethod* nm) { |
sgoldman@542 | 135 | assert(nm->is_java_method(), "invariant"); |
duke@435 | 136 | |
never@1784 | 137 | if (thread->has_last_Java_frame() && thread->last_Java_pc() == fr->pc()) { |
never@1784 | 138 | // We're stopped at a call into the JVM so look for a PcDesc with |
never@1784 | 139 | // the actual pc reported by the frame. |
never@1784 | 140 | PcDesc* pc_desc = nm->pc_desc_at(fr->pc()); |
sgoldman@542 | 141 | |
never@1784 | 142 | // Did we find a useful PcDesc? |
sgoldman@542 | 143 | if (pc_desc != NULL && |
never@1784 | 144 | pc_desc->scope_decode_offset() != DebugInformationRecorder::serialized_null) { |
never@1784 | 145 | return true; |
duke@435 | 146 | } |
duke@435 | 147 | } |
sgoldman@542 | 148 | |
never@1784 | 149 | // We're at some random pc in the nmethod so search for the PcDesc |
never@1784 | 150 | // whose pc is greater than the current PC. It's done this way |
never@1784 | 151 | // because the extra PcDescs that are recorded for improved debug |
never@1784 | 152 | // info record the end of the region covered by the ScopeDesc |
never@1784 | 153 | // instead of the beginning. |
never@1784 | 154 | PcDesc* pc_desc = nm->pc_desc_near(fr->pc() + 1); |
never@1784 | 155 | |
never@1784 | 156 | // Now do we have a useful PcDesc? |
never@1784 | 157 | if (pc_desc == NULL || |
never@1784 | 158 | pc_desc->scope_decode_offset() == DebugInformationRecorder::serialized_null) { |
never@1784 | 159 | // No debug information available for this pc |
never@1784 | 160 | // vframeStream would explode if we try and walk the frames. |
never@1784 | 161 | return false; |
never@1784 | 162 | } |
never@1784 | 163 | |
never@1784 | 164 | // This PcDesc is useful however we must adjust the frame's pc |
never@1784 | 165 | // so that the vframeStream lookups will use this same pc |
never@1784 | 166 | fr->set_pc(pc_desc->real_pc(nm)); |
sgoldman@542 | 167 | return true; |
duke@435 | 168 | } |
duke@435 | 169 | |
never@1784 | 170 | |
duke@435 | 171 | // Determine if 'fr' is a walkable interpreted frame. Returns false |
duke@435 | 172 | // if it is not. *method_p, and *bci_p are not set when false is |
duke@435 | 173 | // returned. *method_p is non-NULL if frame was executing a Java |
duke@435 | 174 | // method. *bci_p is != -1 if a valid BCI in the Java method could |
duke@435 | 175 | // be found. |
duke@435 | 176 | // Note: this method returns true when a valid Java method is found |
duke@435 | 177 | // even if a valid BCI cannot be found. |
duke@435 | 178 | |
sgoldman@542 | 179 | static bool is_decipherable_interpreted_frame(JavaThread* thread, |
never@1784 | 180 | frame* fr, |
never@1784 | 181 | methodOop* method_p, |
never@1784 | 182 | int* bci_p) { |
duke@435 | 183 | assert(fr->is_interpreted_frame(), "just checking"); |
duke@435 | 184 | |
duke@435 | 185 | // top frame is an interpreted frame |
duke@435 | 186 | // check if it is walkable (i.e. valid methodOop and valid bci) |
sgoldman@542 | 187 | |
sgoldman@542 | 188 | // Because we may be racing a gc thread the method and/or bci |
sgoldman@542 | 189 | // of a valid interpreter frame may look bad causing us to |
sgoldman@542 | 190 | // fail the is_interpreted_frame_valid test. If the thread |
sgoldman@542 | 191 | // is in any of the following states we are assured that the |
sgoldman@542 | 192 | // frame is in fact valid and we must have hit the race. |
sgoldman@542 | 193 | |
sgoldman@542 | 194 | JavaThreadState state = thread->thread_state(); |
sgoldman@542 | 195 | bool known_valid = (state == _thread_in_native || |
sgoldman@542 | 196 | state == _thread_in_vm || |
sgoldman@542 | 197 | state == _thread_blocked ); |
sgoldman@542 | 198 | |
sgoldman@542 | 199 | if (known_valid || fr->is_interpreted_frame_valid(thread)) { |
sgoldman@542 | 200 | |
sgoldman@542 | 201 | // The frame code should completely validate the frame so that |
sgoldman@542 | 202 | // references to methodOop and bci are completely safe to access |
sgoldman@542 | 203 | // If they aren't the frame code should be fixed not this |
sgoldman@542 | 204 | // code. However since gc isn't locked out the values could be |
sgoldman@542 | 205 | // stale. This is a race we can never completely win since we can't |
sgoldman@542 | 206 | // lock out gc so do one last check after retrieving their values |
sgoldman@542 | 207 | // from the frame for additional safety |
sgoldman@542 | 208 | |
sgoldman@542 | 209 | methodOop method = fr->interpreter_frame_method(); |
sgoldman@542 | 210 | |
sgoldman@542 | 211 | // We've at least found a method. |
sgoldman@542 | 212 | // NOTE: there is something to be said for the approach that |
sgoldman@542 | 213 | // if we don't find a valid bci then the method is not likely |
sgoldman@542 | 214 | // a valid method. Then again we may have caught an interpreter |
sgoldman@542 | 215 | // frame in the middle of construction and the bci field is |
sgoldman@542 | 216 | // not yet valid. |
sgoldman@542 | 217 | |
sgoldman@542 | 218 | *method_p = method; |
sgoldman@542 | 219 | |
sgoldman@542 | 220 | // See if gc may have invalidated method since we validated frame |
sgoldman@542 | 221 | |
sgoldman@542 | 222 | if (!Universe::heap()->is_valid_method(method)) return false; |
sgoldman@542 | 223 | |
sgoldman@542 | 224 | intptr_t bcx = fr->interpreter_frame_bcx(); |
sgoldman@542 | 225 | |
sgoldman@542 | 226 | int bci = method->validate_bci_from_bcx(bcx); |
sgoldman@542 | 227 | |
sgoldman@542 | 228 | // note: bci is set to -1 if not a valid bci |
sgoldman@542 | 229 | *bci_p = bci; |
sgoldman@542 | 230 | return true; |
duke@435 | 231 | } |
sgoldman@542 | 232 | |
duke@435 | 233 | return false; |
duke@435 | 234 | } |
duke@435 | 235 | |
duke@435 | 236 | |
sgoldman@542 | 237 | // Determine if 'fr' can be used to find an initial Java frame. |
sgoldman@542 | 238 | // Return false if it can not find a fully decipherable Java frame |
sgoldman@542 | 239 | // (in other words a frame that isn't safe to use in a vframe stream). |
sgoldman@542 | 240 | // Obviously if it can't even find a Java frame false will also be returned. |
duke@435 | 241 | // |
sgoldman@542 | 242 | // If we find a Java frame decipherable or not then by definition we have |
sgoldman@542 | 243 | // identified a method and that will be returned to the caller via method_p. |
sgoldman@542 | 244 | // If we can determine a bci that is returned also. (Hmm is it possible |
sgoldman@542 | 245 | // to return a method and bci and still return false? ) |
sgoldman@542 | 246 | // |
sgoldman@542 | 247 | // The initial Java frame we find (if any) is return via initial_frame_p. |
sgoldman@542 | 248 | // |
duke@435 | 249 | |
sgoldman@542 | 250 | static bool find_initial_Java_frame(JavaThread* thread, |
sgoldman@542 | 251 | frame* fr, |
sgoldman@542 | 252 | frame* initial_frame_p, |
sgoldman@542 | 253 | methodOop* method_p, |
sgoldman@542 | 254 | int* bci_p) { |
sgoldman@542 | 255 | |
sgoldman@542 | 256 | // It is possible that for a frame containing an nmethod |
sgoldman@542 | 257 | // we can capture the method but no bci. If we get no |
sgoldman@542 | 258 | // bci the frame isn't walkable but the method is usable. |
sgoldman@542 | 259 | // Therefore we init the returned methodOop to NULL so the |
sgoldman@542 | 260 | // caller can make the distinction. |
sgoldman@542 | 261 | |
sgoldman@542 | 262 | *method_p = NULL; |
sgoldman@542 | 263 | |
sgoldman@542 | 264 | // On the initial call to this method the frame we get may not be |
sgoldman@542 | 265 | // recognizable to us. This should only happen if we are in a JRT_LEAF |
sgoldman@542 | 266 | // or something called by a JRT_LEAF method. |
sgoldman@542 | 267 | |
sgoldman@542 | 268 | |
sgoldman@542 | 269 | |
sgoldman@542 | 270 | frame candidate = *fr; |
sgoldman@542 | 271 | |
sgoldman@542 | 272 | // If the starting frame we were given has no codeBlob associated with |
sgoldman@542 | 273 | // it see if we can find such a frame because only frames with codeBlobs |
sgoldman@542 | 274 | // are possible Java frames. |
sgoldman@542 | 275 | |
sgoldman@542 | 276 | if (fr->cb() == NULL) { |
sgoldman@542 | 277 | |
sgoldman@542 | 278 | // See if we can find a useful frame |
sgoldman@542 | 279 | int loop_count; |
sgoldman@542 | 280 | int loop_max = MaxJavaStackTraceDepth * 2; |
sgoldman@542 | 281 | RegisterMap map(thread, false); |
sgoldman@542 | 282 | |
sgoldman@542 | 283 | for (loop_count = 0; loop_count < loop_max; loop_count++) { |
sgoldman@542 | 284 | if (!candidate.safe_for_sender(thread)) return false; |
sgoldman@542 | 285 | candidate = candidate.sender(&map); |
sgoldman@542 | 286 | if (candidate.cb() != NULL) break; |
sgoldman@542 | 287 | } |
sgoldman@542 | 288 | if (candidate.cb() == NULL) return false; |
duke@435 | 289 | } |
duke@435 | 290 | |
sgoldman@542 | 291 | // We have a frame known to be in the codeCache |
sgoldman@542 | 292 | // We will hopefully be able to figure out something to do with it. |
sgoldman@542 | 293 | int loop_count; |
sgoldman@542 | 294 | int loop_max = MaxJavaStackTraceDepth * 2; |
sgoldman@542 | 295 | RegisterMap map(thread, false); |
sgoldman@542 | 296 | |
sgoldman@542 | 297 | for (loop_count = 0; loop_count < loop_max; loop_count++) { |
sgoldman@542 | 298 | |
sgoldman@542 | 299 | if (candidate.is_first_frame()) { |
sgoldman@542 | 300 | // If initial frame is frame from StubGenerator and there is no |
sgoldman@542 | 301 | // previous anchor, there are no java frames associated with a method |
sgoldman@542 | 302 | return false; |
sgoldman@542 | 303 | } |
sgoldman@542 | 304 | |
sgoldman@542 | 305 | if (candidate.is_interpreted_frame()) { |
sgoldman@542 | 306 | if (is_decipherable_interpreted_frame(thread, &candidate, method_p, bci_p)) { |
sgoldman@542 | 307 | *initial_frame_p = candidate; |
sgoldman@542 | 308 | return true; |
sgoldman@542 | 309 | } |
sgoldman@542 | 310 | |
sgoldman@542 | 311 | // Hopefully we got some data |
sgoldman@542 | 312 | return false; |
sgoldman@542 | 313 | } |
sgoldman@542 | 314 | |
sgoldman@542 | 315 | if (candidate.cb()->is_nmethod()) { |
sgoldman@542 | 316 | |
sgoldman@542 | 317 | nmethod* nm = (nmethod*) candidate.cb(); |
sgoldman@542 | 318 | *method_p = nm->method(); |
sgoldman@542 | 319 | |
sgoldman@542 | 320 | // If the frame isn't fully decipherable then the default |
sgoldman@542 | 321 | // value for the bci is a signal that we don't have a bci. |
sgoldman@542 | 322 | // If we have a decipherable frame this bci value will |
sgoldman@542 | 323 | // not be used. |
sgoldman@542 | 324 | |
sgoldman@542 | 325 | *bci_p = -1; |
sgoldman@542 | 326 | |
sgoldman@542 | 327 | *initial_frame_p = candidate; |
sgoldman@542 | 328 | |
sgoldman@542 | 329 | // Native wrapper code is trivial to decode by vframeStream |
sgoldman@542 | 330 | |
sgoldman@542 | 331 | if (nm->is_native_method()) return true; |
sgoldman@542 | 332 | |
sgoldman@542 | 333 | // If it isn't decipherable then we have found a pc that doesn't |
sgoldman@542 | 334 | // have a PCDesc that can get us a bci however we did find |
sgoldman@542 | 335 | // a method |
sgoldman@542 | 336 | |
never@1784 | 337 | if (!is_decipherable_compiled_frame(thread, &candidate, nm)) { |
sgoldman@542 | 338 | return false; |
sgoldman@542 | 339 | } |
sgoldman@542 | 340 | |
sgoldman@542 | 341 | // is_decipherable_compiled_frame may modify candidate's pc |
sgoldman@542 | 342 | *initial_frame_p = candidate; |
sgoldman@542 | 343 | |
never@1784 | 344 | assert(nm->pc_desc_at(candidate.pc()) != NULL, "if it's decipherable then pc must be valid"); |
never@1784 | 345 | |
sgoldman@542 | 346 | return true; |
sgoldman@542 | 347 | } |
sgoldman@542 | 348 | |
sgoldman@542 | 349 | // Must be some stub frame that we don't care about |
sgoldman@542 | 350 | |
sgoldman@542 | 351 | if (!candidate.safe_for_sender(thread)) return false; |
sgoldman@542 | 352 | candidate = candidate.sender(&map); |
sgoldman@542 | 353 | |
sgoldman@542 | 354 | // If it isn't in the code cache something is wrong |
sgoldman@542 | 355 | // since once we find a frame in the code cache they |
sgoldman@542 | 356 | // all should be there. |
sgoldman@542 | 357 | |
sgoldman@542 | 358 | if (candidate.cb() == NULL) return false; |
sgoldman@542 | 359 | |
duke@435 | 360 | } |
duke@435 | 361 | |
sgoldman@542 | 362 | return false; |
duke@435 | 363 | |
duke@435 | 364 | } |
duke@435 | 365 | |
duke@435 | 366 | |
duke@435 | 367 | // call frame copied from old .h file and renamed |
duke@435 | 368 | typedef struct { |
duke@435 | 369 | jint lineno; // line number in the source file |
duke@435 | 370 | jmethodID method_id; // method executed in this frame |
duke@435 | 371 | } ASGCT_CallFrame; |
duke@435 | 372 | |
duke@435 | 373 | // call trace copied from old .h file and renamed |
duke@435 | 374 | typedef struct { |
duke@435 | 375 | JNIEnv *env_id; // Env where trace was recorded |
duke@435 | 376 | jint num_frames; // number of frames in this trace |
duke@435 | 377 | ASGCT_CallFrame *frames; // frames |
duke@435 | 378 | } ASGCT_CallTrace; |
duke@435 | 379 | |
duke@435 | 380 | static void forte_fill_call_trace_given_top(JavaThread* thd, |
sgoldman@542 | 381 | ASGCT_CallTrace* trace, |
sgoldman@542 | 382 | int depth, |
sgoldman@542 | 383 | frame top_frame) { |
duke@435 | 384 | NoHandleMark nhm; |
duke@435 | 385 | |
sgoldman@542 | 386 | frame initial_Java_frame; |
duke@435 | 387 | methodOop method; |
duke@435 | 388 | int bci; |
duke@435 | 389 | int count; |
duke@435 | 390 | |
duke@435 | 391 | count = 0; |
duke@435 | 392 | assert(trace->frames != NULL, "trace->frames must be non-NULL"); |
duke@435 | 393 | |
sgoldman@542 | 394 | bool fully_decipherable = find_initial_Java_frame(thd, &top_frame, &initial_Java_frame, &method, &bci); |
sgoldman@542 | 395 | |
sgoldman@542 | 396 | // The frame might not be walkable but still recovered a method |
sgoldman@542 | 397 | // (e.g. an nmethod with no scope info for the pc |
sgoldman@542 | 398 | |
sgoldman@542 | 399 | if (method == NULL) return; |
sgoldman@542 | 400 | |
sgoldman@542 | 401 | CollectedHeap* ch = Universe::heap(); |
sgoldman@542 | 402 | |
sgoldman@542 | 403 | // The method is not stored GC safe so see if GC became active |
sgoldman@542 | 404 | // after we entered AsyncGetCallTrace() and before we try to |
sgoldman@542 | 405 | // use the methodOop. |
sgoldman@542 | 406 | // Yes, there is still a window after this check and before |
sgoldman@542 | 407 | // we use methodOop below, but we can't lock out GC so that |
sgoldman@542 | 408 | // has to be an acceptable risk. |
sgoldman@542 | 409 | if (!ch->is_valid_method(method)) { |
sgoldman@542 | 410 | trace->num_frames = ticks_GC_active; // -2 |
duke@435 | 411 | return; |
duke@435 | 412 | } |
duke@435 | 413 | |
sgoldman@542 | 414 | // We got a Java frame however it isn't fully decipherable |
sgoldman@542 | 415 | // so it won't necessarily be safe to use it for the |
sgoldman@542 | 416 | // initial frame in the vframe stream. |
duke@435 | 417 | |
sgoldman@542 | 418 | if (!fully_decipherable) { |
sgoldman@542 | 419 | // Take whatever method the top-frame decoder managed to scrape up. |
sgoldman@542 | 420 | // We look further at the top frame only if non-safepoint |
sgoldman@542 | 421 | // debugging information is available. |
sgoldman@542 | 422 | count++; |
sgoldman@542 | 423 | trace->num_frames = count; |
sgoldman@542 | 424 | trace->frames[0].method_id = method->find_jmethod_id_or_null(); |
sgoldman@542 | 425 | if (!method->is_native()) { |
sgoldman@542 | 426 | trace->frames[0].lineno = bci; |
sgoldman@542 | 427 | } else { |
sgoldman@542 | 428 | trace->frames[0].lineno = -3; |
duke@435 | 429 | } |
duke@435 | 430 | |
sgoldman@542 | 431 | if (!initial_Java_frame.safe_for_sender(thd)) return; |
sgoldman@542 | 432 | |
sgoldman@542 | 433 | RegisterMap map(thd, false); |
sgoldman@542 | 434 | initial_Java_frame = initial_Java_frame.sender(&map); |
duke@435 | 435 | } |
duke@435 | 436 | |
sgoldman@542 | 437 | vframeStreamForte st(thd, initial_Java_frame, false); |
duke@435 | 438 | |
duke@435 | 439 | for (; !st.at_end() && count < depth; st.forte_next(), count++) { |
duke@435 | 440 | bci = st.bci(); |
duke@435 | 441 | method = st.method(); |
duke@435 | 442 | |
duke@435 | 443 | // The method is not stored GC safe so see if GC became active |
duke@435 | 444 | // after we entered AsyncGetCallTrace() and before we try to |
duke@435 | 445 | // use the methodOop. |
duke@435 | 446 | // Yes, there is still a window after this check and before |
duke@435 | 447 | // we use methodOop below, but we can't lock out GC so that |
duke@435 | 448 | // has to be an acceptable risk. |
duke@435 | 449 | if (!ch->is_valid_method(method)) { |
duke@435 | 450 | // we throw away everything we've gathered in this sample since |
duke@435 | 451 | // none of it is safe |
sgoldman@542 | 452 | trace->num_frames = ticks_GC_active; // -2 |
duke@435 | 453 | return; |
duke@435 | 454 | } |
duke@435 | 455 | |
duke@435 | 456 | trace->frames[count].method_id = method->find_jmethod_id_or_null(); |
duke@435 | 457 | if (!method->is_native()) { |
duke@435 | 458 | trace->frames[count].lineno = bci; |
duke@435 | 459 | } else { |
duke@435 | 460 | trace->frames[count].lineno = -3; |
duke@435 | 461 | } |
duke@435 | 462 | } |
duke@435 | 463 | trace->num_frames = count; |
duke@435 | 464 | return; |
duke@435 | 465 | } |
duke@435 | 466 | |
duke@435 | 467 | |
duke@435 | 468 | // Forte Analyzer AsyncGetCallTrace() entry point. Currently supported |
duke@435 | 469 | // on Linux X86, Solaris SPARC and Solaris X86. |
duke@435 | 470 | // |
duke@435 | 471 | // Async-safe version of GetCallTrace being called from a signal handler |
duke@435 | 472 | // when a LWP gets interrupted by SIGPROF but the stack traces are filled |
duke@435 | 473 | // with different content (see below). |
duke@435 | 474 | // |
duke@435 | 475 | // This function must only be called when JVM/TI |
duke@435 | 476 | // CLASS_LOAD events have been enabled since agent startup. The enabled |
duke@435 | 477 | // event will cause the jmethodIDs to be allocated at class load time. |
duke@435 | 478 | // The jmethodIDs cannot be allocated in a signal handler because locks |
duke@435 | 479 | // cannot be grabbed in a signal handler safely. |
duke@435 | 480 | // |
duke@435 | 481 | // void (*AsyncGetCallTrace)(ASGCT_CallTrace *trace, jint depth, void* ucontext) |
duke@435 | 482 | // |
duke@435 | 483 | // Called by the profiler to obtain the current method call stack trace for |
duke@435 | 484 | // a given thread. The thread is identified by the env_id field in the |
duke@435 | 485 | // ASGCT_CallTrace structure. The profiler agent should allocate a ASGCT_CallTrace |
duke@435 | 486 | // structure with enough memory for the requested stack depth. The VM fills in |
duke@435 | 487 | // the frames buffer and the num_frames field. |
duke@435 | 488 | // |
duke@435 | 489 | // Arguments: |
duke@435 | 490 | // |
duke@435 | 491 | // trace - trace data structure to be filled by the VM. |
duke@435 | 492 | // depth - depth of the call stack trace. |
duke@435 | 493 | // ucontext - ucontext_t of the LWP |
duke@435 | 494 | // |
duke@435 | 495 | // ASGCT_CallTrace: |
duke@435 | 496 | // typedef struct { |
duke@435 | 497 | // JNIEnv *env_id; |
duke@435 | 498 | // jint num_frames; |
duke@435 | 499 | // ASGCT_CallFrame *frames; |
duke@435 | 500 | // } ASGCT_CallTrace; |
duke@435 | 501 | // |
duke@435 | 502 | // Fields: |
duke@435 | 503 | // env_id - ID of thread which executed this trace. |
duke@435 | 504 | // num_frames - number of frames in the trace. |
duke@435 | 505 | // (< 0 indicates the frame is not walkable). |
duke@435 | 506 | // frames - the ASGCT_CallFrames that make up this trace. Callee followed by callers. |
duke@435 | 507 | // |
duke@435 | 508 | // ASGCT_CallFrame: |
duke@435 | 509 | // typedef struct { |
duke@435 | 510 | // jint lineno; |
duke@435 | 511 | // jmethodID method_id; |
duke@435 | 512 | // } ASGCT_CallFrame; |
duke@435 | 513 | // |
duke@435 | 514 | // Fields: |
duke@435 | 515 | // 1) For Java frame (interpreted and compiled), |
duke@435 | 516 | // lineno - bci of the method being executed or -1 if bci is not available |
duke@435 | 517 | // method_id - jmethodID of the method being executed |
duke@435 | 518 | // 2) For native method |
duke@435 | 519 | // lineno - (-3) |
duke@435 | 520 | // method_id - jmethodID of the method being executed |
duke@435 | 521 | |
duke@435 | 522 | extern "C" { |
duke@435 | 523 | void AsyncGetCallTrace(ASGCT_CallTrace *trace, jint depth, void* ucontext) { |
sgoldman@542 | 524 | |
sgoldman@542 | 525 | // This is if'd out because we no longer use thread suspension. |
sgoldman@542 | 526 | // However if someone wanted to backport this to a 5.0 jvm then this |
sgoldman@542 | 527 | // code would be important. |
sgoldman@542 | 528 | #if 0 |
duke@435 | 529 | if (SafepointSynchronize::is_synchronizing()) { |
duke@435 | 530 | // The safepoint mechanism is trying to synchronize all the threads. |
duke@435 | 531 | // Since this can involve thread suspension, it is not safe for us |
duke@435 | 532 | // to be here. We can reduce the deadlock risk window by quickly |
duke@435 | 533 | // returning to the SIGPROF handler. However, it is still possible |
duke@435 | 534 | // for VMThread to catch us here or in the SIGPROF handler. If we |
duke@435 | 535 | // are suspended while holding a resource and another thread blocks |
duke@435 | 536 | // on that resource in the SIGPROF handler, then we will have a |
duke@435 | 537 | // three-thread deadlock (VMThread, this thread, the other thread). |
sgoldman@542 | 538 | trace->num_frames = ticks_safepoint; // -10 |
duke@435 | 539 | return; |
duke@435 | 540 | } |
sgoldman@542 | 541 | #endif |
duke@435 | 542 | |
duke@435 | 543 | JavaThread* thread; |
duke@435 | 544 | |
duke@435 | 545 | if (trace->env_id == NULL || |
duke@435 | 546 | (thread = JavaThread::thread_from_jni_environment(trace->env_id)) == NULL || |
duke@435 | 547 | thread->is_exiting()) { |
duke@435 | 548 | |
duke@435 | 549 | // bad env_id, thread has exited or thread is exiting |
sgoldman@542 | 550 | trace->num_frames = ticks_thread_exit; // -8 |
duke@435 | 551 | return; |
duke@435 | 552 | } |
duke@435 | 553 | |
duke@435 | 554 | if (thread->in_deopt_handler()) { |
duke@435 | 555 | // thread is in the deoptimization handler so return no frames |
sgoldman@542 | 556 | trace->num_frames = ticks_deopt; // -9 |
duke@435 | 557 | return; |
duke@435 | 558 | } |
duke@435 | 559 | |
duke@435 | 560 | assert(JavaThread::current() == thread, |
duke@435 | 561 | "AsyncGetCallTrace must be called by the current interrupted thread"); |
duke@435 | 562 | |
duke@435 | 563 | if (!JvmtiExport::should_post_class_load()) { |
sgoldman@542 | 564 | trace->num_frames = ticks_no_class_load; // -1 |
duke@435 | 565 | return; |
duke@435 | 566 | } |
duke@435 | 567 | |
duke@435 | 568 | if (Universe::heap()->is_gc_active()) { |
sgoldman@542 | 569 | trace->num_frames = ticks_GC_active; // -2 |
duke@435 | 570 | return; |
duke@435 | 571 | } |
duke@435 | 572 | |
duke@435 | 573 | switch (thread->thread_state()) { |
duke@435 | 574 | case _thread_new: |
duke@435 | 575 | case _thread_uninitialized: |
duke@435 | 576 | case _thread_new_trans: |
duke@435 | 577 | // We found the thread on the threads list above, but it is too |
duke@435 | 578 | // young to be useful so return that there are no Java frames. |
duke@435 | 579 | trace->num_frames = 0; |
duke@435 | 580 | break; |
duke@435 | 581 | case _thread_in_native: |
duke@435 | 582 | case _thread_in_native_trans: |
duke@435 | 583 | case _thread_blocked: |
duke@435 | 584 | case _thread_blocked_trans: |
duke@435 | 585 | case _thread_in_vm: |
duke@435 | 586 | case _thread_in_vm_trans: |
duke@435 | 587 | { |
duke@435 | 588 | frame fr; |
duke@435 | 589 | |
duke@435 | 590 | // param isInJava == false - indicate we aren't in Java code |
duke@435 | 591 | if (!thread->pd_get_top_frame_for_signal_handler(&fr, ucontext, false)) { |
sgoldman@542 | 592 | trace->num_frames = ticks_unknown_not_Java; // -3 unknown frame |
sgoldman@542 | 593 | } else { |
duke@435 | 594 | if (!thread->has_last_Java_frame()) { |
sgoldman@542 | 595 | trace->num_frames = 0; // No Java frames |
duke@435 | 596 | } else { |
sgoldman@542 | 597 | trace->num_frames = ticks_not_walkable_not_Java; // -4 non walkable frame by default |
sgoldman@542 | 598 | forte_fill_call_trace_given_top(thread, trace, depth, fr); |
sgoldman@542 | 599 | |
sgoldman@542 | 600 | // This assert would seem to be valid but it is not. |
sgoldman@542 | 601 | // It would be valid if we weren't possibly racing a gc |
sgoldman@542 | 602 | // thread. A gc thread can make a valid interpreted frame |
sgoldman@542 | 603 | // look invalid. It's a small window but it does happen. |
sgoldman@542 | 604 | // The assert is left here commented out as a reminder. |
sgoldman@542 | 605 | // assert(trace->num_frames != ticks_not_walkable_not_Java, "should always be walkable"); |
sgoldman@542 | 606 | |
duke@435 | 607 | } |
duke@435 | 608 | } |
duke@435 | 609 | } |
duke@435 | 610 | break; |
duke@435 | 611 | case _thread_in_Java: |
duke@435 | 612 | case _thread_in_Java_trans: |
duke@435 | 613 | { |
duke@435 | 614 | frame fr; |
duke@435 | 615 | |
duke@435 | 616 | // param isInJava == true - indicate we are in Java code |
duke@435 | 617 | if (!thread->pd_get_top_frame_for_signal_handler(&fr, ucontext, true)) { |
sgoldman@542 | 618 | trace->num_frames = ticks_unknown_Java; // -5 unknown frame |
duke@435 | 619 | } else { |
sgoldman@542 | 620 | trace->num_frames = ticks_not_walkable_Java; // -6, non walkable frame by default |
duke@435 | 621 | forte_fill_call_trace_given_top(thread, trace, depth, fr); |
duke@435 | 622 | } |
duke@435 | 623 | } |
duke@435 | 624 | break; |
duke@435 | 625 | default: |
duke@435 | 626 | // Unknown thread state |
sgoldman@542 | 627 | trace->num_frames = ticks_unknown_state; // -7 |
duke@435 | 628 | break; |
duke@435 | 629 | } |
duke@435 | 630 | } |
duke@435 | 631 | |
duke@435 | 632 | |
duke@435 | 633 | #ifndef _WINDOWS |
duke@435 | 634 | // Support for the Forte(TM) Peformance Tools collector. |
duke@435 | 635 | // |
duke@435 | 636 | // The method prototype is derived from libcollector.h. For more |
duke@435 | 637 | // information, please see the libcollect man page. |
duke@435 | 638 | |
duke@435 | 639 | // Method to let libcollector know about a dynamically loaded function. |
duke@435 | 640 | // Because it is weakly bound, the calls become NOP's when the library |
duke@435 | 641 | // isn't present. |
duke@435 | 642 | void collector_func_load(char* name, |
duke@435 | 643 | void* null_argument_1, |
duke@435 | 644 | void* null_argument_2, |
duke@435 | 645 | void *vaddr, |
duke@435 | 646 | int size, |
duke@435 | 647 | int zero_argument, |
duke@435 | 648 | void* null_argument_3); |
duke@435 | 649 | #pragma weak collector_func_load |
duke@435 | 650 | #define collector_func_load(x0,x1,x2,x3,x4,x5,x6) \ |
duke@435 | 651 | ( collector_func_load ? collector_func_load(x0,x1,x2,x3,x4,x5,x6),0 : 0 ) |
duke@435 | 652 | #endif // !_WINDOWS |
duke@435 | 653 | |
duke@435 | 654 | } // end extern "C" |
duke@435 | 655 | #endif // !IA64 |
duke@435 | 656 | |
duke@435 | 657 | void Forte::register_stub(const char* name, address start, address end) { |
duke@435 | 658 | #if !defined(_WINDOWS) && !defined(IA64) |
duke@435 | 659 | assert(pointer_delta(end, start, sizeof(jbyte)) < INT_MAX, |
jcoomes@1844 | 660 | "Code size exceeds maximum range"); |
duke@435 | 661 | |
duke@435 | 662 | collector_func_load((char*)name, NULL, NULL, start, |
duke@435 | 663 | pointer_delta(end, start, sizeof(jbyte)), 0, NULL); |
duke@435 | 664 | #endif // !_WINDOWS && !IA64 |
duke@435 | 665 | } |