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