src/share/vm/runtime/vframe.hpp

Wed, 03 Jul 2019 20:42:37 +0800

author
aoqi
date
Wed, 03 Jul 2019 20:42:37 +0800
changeset 9637
eef07cd490d4
parent 7994
04ff2f6cd0eb
permissions
-rw-r--r--

Merge

aoqi@0 1 /*
aoqi@0 2 * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
aoqi@0 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
aoqi@0 4 *
aoqi@0 5 * This code is free software; you can redistribute it and/or modify it
aoqi@0 6 * under the terms of the GNU General Public License version 2 only, as
aoqi@0 7 * published by the Free Software Foundation.
aoqi@0 8 *
aoqi@0 9 * This code is distributed in the hope that it will be useful, but WITHOUT
aoqi@0 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
aoqi@0 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
aoqi@0 12 * version 2 for more details (a copy is included in the LICENSE file that
aoqi@0 13 * accompanied this code).
aoqi@0 14 *
aoqi@0 15 * You should have received a copy of the GNU General Public License version
aoqi@0 16 * 2 along with this work; if not, write to the Free Software Foundation,
aoqi@0 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
aoqi@0 18 *
aoqi@0 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
aoqi@0 20 * or visit www.oracle.com if you need additional information or have any
aoqi@0 21 * questions.
aoqi@0 22 *
aoqi@0 23 */
aoqi@0 24
aoqi@0 25 #ifndef SHARE_VM_RUNTIME_VFRAME_HPP
aoqi@0 26 #define SHARE_VM_RUNTIME_VFRAME_HPP
aoqi@0 27
aoqi@0 28 #include "code/debugInfo.hpp"
aoqi@0 29 #include "code/debugInfoRec.hpp"
aoqi@0 30 #include "code/location.hpp"
aoqi@0 31 #include "oops/oop.hpp"
aoqi@0 32 #include "runtime/frame.hpp"
aoqi@0 33 #include "runtime/frame.inline.hpp"
aoqi@0 34 #include "runtime/stackValue.hpp"
aoqi@0 35 #include "runtime/stackValueCollection.hpp"
aoqi@0 36 #include "utilities/growableArray.hpp"
aoqi@0 37
aoqi@0 38 // vframes are virtual stack frames representing source level activations.
aoqi@0 39 // A single frame may hold several source level activations in the case of
aoqi@0 40 // optimized code. The debugging stored with the optimized code enables
aoqi@0 41 // us to unfold a frame as a stack of vframes.
aoqi@0 42 // A cVFrame represents an activation of a non-java method.
aoqi@0 43
aoqi@0 44 // The vframe inheritance hierarchy:
aoqi@0 45 // - vframe
aoqi@0 46 // - javaVFrame
aoqi@0 47 // - interpretedVFrame
aoqi@0 48 // - compiledVFrame ; (used for both compiled Java methods and native stubs)
aoqi@0 49 // - externalVFrame
aoqi@0 50 // - entryVFrame ; special frame created when calling Java from C
aoqi@0 51
aoqi@0 52 // - BasicLock
aoqi@0 53
aoqi@0 54 class vframe: public ResourceObj {
aoqi@0 55 protected:
aoqi@0 56 frame _fr; // Raw frame behind the virtual frame.
aoqi@0 57 RegisterMap _reg_map; // Register map for the raw frame (used to handle callee-saved registers).
aoqi@0 58 JavaThread* _thread; // The thread owning the raw frame.
aoqi@0 59
aoqi@0 60 vframe(const frame* fr, const RegisterMap* reg_map, JavaThread* thread);
aoqi@0 61 vframe(const frame* fr, JavaThread* thread);
aoqi@0 62 public:
aoqi@0 63 // Factory method for creating vframes
aoqi@0 64 static vframe* new_vframe(const frame* f, const RegisterMap *reg_map, JavaThread* thread);
aoqi@0 65
aoqi@0 66 // Accessors
aoqi@0 67 frame fr() const { return _fr; }
aoqi@0 68 CodeBlob* cb() const { return _fr.cb(); }
aoqi@0 69 nmethod* nm() const {
aoqi@0 70 assert( cb() != NULL && cb()->is_nmethod(), "usage");
aoqi@0 71 return (nmethod*) cb();
aoqi@0 72 }
aoqi@0 73
aoqi@0 74 // ???? Does this need to be a copy?
aoqi@0 75 frame* frame_pointer() { return &_fr; }
aoqi@0 76 const RegisterMap* register_map() const { return &_reg_map; }
aoqi@0 77 JavaThread* thread() const { return _thread; }
aoqi@0 78
aoqi@0 79 // Returns the sender vframe
aoqi@0 80 virtual vframe* sender() const;
aoqi@0 81
aoqi@0 82 // Returns the next javaVFrame on the stack (skipping all other kinds of frame)
aoqi@0 83 javaVFrame *java_sender() const;
aoqi@0 84
aoqi@0 85 // Answers if the this is the top vframe in the frame, i.e., if the sender vframe
aoqi@0 86 // is in the caller frame
aoqi@0 87 virtual bool is_top() const { return true; }
aoqi@0 88
aoqi@0 89 // Returns top vframe within same frame (see is_top())
aoqi@0 90 virtual vframe* top() const;
aoqi@0 91
aoqi@0 92 // Type testing operations
aoqi@0 93 virtual bool is_entry_frame() const { return false; }
aoqi@0 94 virtual bool is_java_frame() const { return false; }
aoqi@0 95 virtual bool is_interpreted_frame() const { return false; }
aoqi@0 96 virtual bool is_compiled_frame() const { return false; }
aoqi@0 97
aoqi@0 98 #ifndef PRODUCT
aoqi@0 99 // printing operations
aoqi@0 100 virtual void print_value() const;
aoqi@0 101 virtual void print();
aoqi@0 102 #endif
aoqi@0 103 };
aoqi@0 104
aoqi@0 105
aoqi@0 106 class javaVFrame: public vframe {
aoqi@0 107 public:
aoqi@0 108 // JVM state
aoqi@0 109 virtual Method* method() const = 0;
aoqi@0 110 virtual int bci() const = 0;
aoqi@0 111 virtual StackValueCollection* locals() const = 0;
aoqi@0 112 virtual StackValueCollection* expressions() const = 0;
aoqi@0 113 // the order returned by monitors() is from oldest -> youngest#4418568
aoqi@0 114 virtual GrowableArray<MonitorInfo*>* monitors() const = 0;
aoqi@0 115
aoqi@0 116 // Debugging support via JVMTI.
aoqi@0 117 // NOTE that this is not guaranteed to give correct results for compiled vframes.
aoqi@0 118 // Deoptimize first if necessary.
aoqi@0 119 virtual void set_locals(StackValueCollection* values) const = 0;
aoqi@0 120
aoqi@0 121 // Test operation
aoqi@0 122 bool is_java_frame() const { return true; }
aoqi@0 123
aoqi@0 124 protected:
aoqi@0 125 javaVFrame(const frame* fr, const RegisterMap* reg_map, JavaThread* thread) : vframe(fr, reg_map, thread) {}
aoqi@0 126 javaVFrame(const frame* fr, JavaThread* thread) : vframe(fr, thread) {}
aoqi@0 127
aoqi@0 128 public:
aoqi@0 129 // casting
aoqi@0 130 static javaVFrame* cast(vframe* vf) {
aoqi@0 131 assert(vf == NULL || vf->is_java_frame(), "must be java frame");
aoqi@0 132 return (javaVFrame*) vf;
aoqi@0 133 }
aoqi@0 134
aoqi@0 135 // Return an array of monitors locked by this frame in the youngest to oldest order
aoqi@0 136 GrowableArray<MonitorInfo*>* locked_monitors();
aoqi@0 137
aoqi@0 138 // printing used during stack dumps
aoqi@0 139 void print_lock_info_on(outputStream* st, int frame_count);
aoqi@0 140 void print_lock_info(int frame_count) { print_lock_info_on(tty, frame_count); }
aoqi@0 141
aoqi@0 142 #ifndef PRODUCT
aoqi@0 143 public:
aoqi@0 144 // printing operations
aoqi@0 145 void print();
aoqi@0 146 void print_value() const;
aoqi@0 147 void print_activation(int index) const;
aoqi@0 148
aoqi@0 149 // verify operations
aoqi@0 150 virtual void verify() const;
aoqi@0 151
aoqi@0 152 // Structural compare
aoqi@0 153 bool structural_compare(javaVFrame* other);
aoqi@0 154 #endif
aoqi@0 155 friend class vframe;
aoqi@0 156 };
aoqi@0 157
aoqi@0 158 class interpretedVFrame: public javaVFrame {
aoqi@0 159 public:
aoqi@0 160 // JVM state
aoqi@0 161 Method* method() const;
aoqi@0 162 int bci() const;
aoqi@0 163 StackValueCollection* locals() const;
aoqi@0 164 StackValueCollection* expressions() const;
aoqi@0 165 GrowableArray<MonitorInfo*>* monitors() const;
aoqi@0 166
aoqi@0 167 void set_locals(StackValueCollection* values) const;
aoqi@0 168
aoqi@0 169 // Test operation
aoqi@0 170 bool is_interpreted_frame() const { return true; }
aoqi@0 171
aoqi@0 172 protected:
aoqi@0 173 interpretedVFrame(const frame* fr, const RegisterMap* reg_map, JavaThread* thread) : javaVFrame(fr, reg_map, thread) {};
aoqi@0 174
aoqi@0 175 public:
aoqi@0 176 // Accessors for Byte Code Pointer
aoqi@0 177 u_char* bcp() const;
aoqi@0 178 void set_bcp(u_char* bcp);
aoqi@0 179
aoqi@0 180 // casting
aoqi@0 181 static interpretedVFrame* cast(vframe* vf) {
aoqi@0 182 assert(vf == NULL || vf->is_interpreted_frame(), "must be interpreted frame");
aoqi@0 183 return (interpretedVFrame*) vf;
aoqi@0 184 }
aoqi@0 185
aoqi@0 186 private:
aoqi@0 187 static const int bcp_offset;
aoqi@0 188 intptr_t* locals_addr_at(int offset) const;
mgronlun@7215 189 StackValueCollection* stack_data(bool expressions) const;
aoqi@0 190 // returns where the parameters starts relative to the frame pointer
aoqi@0 191 int start_of_parameters() const;
aoqi@0 192
aoqi@0 193 #ifndef PRODUCT
aoqi@0 194 public:
aoqi@0 195 // verify operations
aoqi@0 196 void verify() const;
aoqi@0 197 #endif
aoqi@0 198 friend class vframe;
aoqi@0 199 };
aoqi@0 200
aoqi@0 201
aoqi@0 202 class externalVFrame: public vframe {
aoqi@0 203 protected:
aoqi@0 204 externalVFrame(const frame* fr, const RegisterMap* reg_map, JavaThread* thread) : vframe(fr, reg_map, thread) {}
aoqi@0 205
aoqi@0 206 #ifndef PRODUCT
aoqi@0 207 public:
aoqi@0 208 // printing operations
aoqi@0 209 void print_value() const;
aoqi@0 210 void print();
aoqi@0 211 #endif
aoqi@0 212 friend class vframe;
aoqi@0 213 };
aoqi@0 214
aoqi@0 215 class entryVFrame: public externalVFrame {
aoqi@0 216 public:
aoqi@0 217 bool is_entry_frame() const { return true; }
aoqi@0 218
aoqi@0 219 protected:
aoqi@0 220 entryVFrame(const frame* fr, const RegisterMap* reg_map, JavaThread* thread);
aoqi@0 221
aoqi@0 222 public:
aoqi@0 223 // casting
aoqi@0 224 static entryVFrame* cast(vframe* vf) {
aoqi@0 225 assert(vf == NULL || vf->is_entry_frame(), "must be entry frame");
aoqi@0 226 return (entryVFrame*) vf;
aoqi@0 227 }
aoqi@0 228
aoqi@0 229 #ifndef PRODUCT
aoqi@0 230 public:
aoqi@0 231 // printing
aoqi@0 232 void print_value() const;
aoqi@0 233 void print();
aoqi@0 234 #endif
aoqi@0 235 friend class vframe;
aoqi@0 236 };
aoqi@0 237
aoqi@0 238
aoqi@0 239 // A MonitorInfo is a ResourceObject that describes a the pair:
aoqi@0 240 // 1) the owner of the monitor
aoqi@0 241 // 2) the monitor lock
aoqi@0 242 class MonitorInfo : public ResourceObj {
aoqi@0 243 private:
aoqi@0 244 oop _owner; // the object owning the monitor
aoqi@0 245 BasicLock* _lock;
aoqi@0 246 oop _owner_klass; // klass (mirror) if owner was scalar replaced
aoqi@0 247 bool _eliminated;
aoqi@0 248 bool _owner_is_scalar_replaced;
aoqi@0 249 public:
aoqi@0 250 // Constructor
aoqi@0 251 MonitorInfo(oop owner, BasicLock* lock, bool eliminated, bool owner_is_scalar_replaced) {
aoqi@0 252 if (!owner_is_scalar_replaced) {
aoqi@0 253 _owner = owner;
aoqi@0 254 _owner_klass = NULL;
aoqi@0 255 } else {
aoqi@0 256 assert(eliminated, "monitor should be eliminated for scalar replaced object");
aoqi@0 257 _owner = NULL;
aoqi@0 258 _owner_klass = owner;
aoqi@0 259 }
aoqi@0 260 _lock = lock;
aoqi@0 261 _eliminated = eliminated;
aoqi@0 262 _owner_is_scalar_replaced = owner_is_scalar_replaced;
aoqi@0 263 }
aoqi@0 264 // Accessors
aoqi@0 265 oop owner() const {
aoqi@0 266 assert(!_owner_is_scalar_replaced, "should not be called for scalar replaced object");
aoqi@0 267 return _owner;
aoqi@0 268 }
aoqi@0 269 oop owner_klass() const {
aoqi@0 270 assert(_owner_is_scalar_replaced, "should not be called for not scalar replaced object");
aoqi@0 271 return _owner_klass;
aoqi@0 272 }
aoqi@0 273 BasicLock* lock() const { return _lock; }
aoqi@0 274 bool eliminated() const { return _eliminated; }
aoqi@0 275 bool owner_is_scalar_replaced() const { return _owner_is_scalar_replaced; }
aoqi@0 276 };
aoqi@0 277
aoqi@0 278 class vframeStreamCommon : StackObj {
aoqi@0 279 protected:
aoqi@0 280 // common
aoqi@0 281 frame _frame;
aoqi@0 282 JavaThread* _thread;
aoqi@0 283 RegisterMap _reg_map;
aoqi@0 284 enum { interpreted_mode, compiled_mode, at_end_mode } _mode;
aoqi@0 285
aoqi@0 286 int _sender_decode_offset;
aoqi@0 287
aoqi@0 288 // Cached information
aoqi@0 289 Method* _method;
aoqi@0 290 int _bci;
aoqi@0 291
aoqi@0 292 // Should VM activations be ignored or not
aoqi@0 293 bool _stop_at_java_call_stub;
aoqi@0 294
aoqi@0 295 bool fill_in_compiled_inlined_sender();
aoqi@0 296 void fill_from_compiled_frame(int decode_offset);
aoqi@0 297 void fill_from_compiled_native_frame();
aoqi@0 298
aoqi@0 299 void found_bad_method_frame();
aoqi@0 300
aoqi@0 301 void fill_from_interpreter_frame();
aoqi@0 302 bool fill_from_frame();
aoqi@0 303
aoqi@0 304 // Helper routine for security_get_caller_frame
aoqi@0 305 void skip_prefixed_method_and_wrappers();
aoqi@0 306
aoqi@0 307 public:
aoqi@0 308 // Constructor
aoqi@0 309 vframeStreamCommon(JavaThread* thread) : _reg_map(thread, false) {
aoqi@0 310 _thread = thread;
aoqi@0 311 }
aoqi@0 312
aoqi@0 313 // Accessors
aoqi@0 314 Method* method() const { return _method; }
aoqi@0 315 int bci() const { return _bci; }
aoqi@0 316 intptr_t* frame_id() const { return _frame.id(); }
aoqi@0 317 address frame_pc() const { return _frame.pc(); }
aoqi@0 318
aoqi@0 319 CodeBlob* cb() const { return _frame.cb(); }
aoqi@0 320 nmethod* nm() const {
aoqi@0 321 assert( cb() != NULL && cb()->is_nmethod(), "usage");
aoqi@0 322 return (nmethod*) cb();
aoqi@0 323 }
aoqi@0 324
aoqi@0 325 // Frame type
aoqi@0 326 bool is_interpreted_frame() const { return _frame.is_interpreted_frame(); }
aoqi@0 327 bool is_entry_frame() const { return _frame.is_entry_frame(); }
aoqi@0 328
aoqi@0 329 // Iteration
aoqi@0 330 void next() {
aoqi@0 331 // handle frames with inlining
aoqi@0 332 if (_mode == compiled_mode && fill_in_compiled_inlined_sender()) return;
aoqi@0 333
aoqi@0 334 // handle general case
aoqi@0 335 do {
aoqi@0 336 _frame = _frame.sender(&_reg_map);
aoqi@0 337 } while (!fill_from_frame());
aoqi@0 338 }
aoqi@0 339 void security_next();
aoqi@0 340
aoqi@0 341 bool at_end() const { return _mode == at_end_mode; }
aoqi@0 342
aoqi@0 343 // Implements security traversal. Skips depth no. of frame including
aoqi@0 344 // special security frames and prefixed native methods
aoqi@0 345 void security_get_caller_frame(int depth);
aoqi@0 346
aoqi@0 347 // Helper routine for JVM_LatestUserDefinedLoader -- needed for 1.4
aoqi@0 348 // reflection implementation
aoqi@0 349 void skip_reflection_related_frames();
aoqi@0 350 };
aoqi@0 351
aoqi@0 352 class vframeStream : public vframeStreamCommon {
aoqi@0 353 public:
aoqi@0 354 // Constructors
aoqi@0 355 vframeStream(JavaThread* thread, bool stop_at_java_call_stub = false)
aoqi@0 356 : vframeStreamCommon(thread) {
aoqi@0 357 _stop_at_java_call_stub = stop_at_java_call_stub;
aoqi@0 358
aoqi@0 359 if (!thread->has_last_Java_frame()) {
aoqi@0 360 _mode = at_end_mode;
aoqi@0 361 return;
aoqi@0 362 }
aoqi@0 363
aoqi@0 364 _frame = _thread->last_frame();
aoqi@0 365 while (!fill_from_frame()) {
aoqi@0 366 _frame = _frame.sender(&_reg_map);
aoqi@0 367 }
aoqi@0 368 }
aoqi@0 369
aoqi@0 370 // top_frame may not be at safepoint, start with sender
aoqi@0 371 vframeStream(JavaThread* thread, frame top_frame, bool stop_at_java_call_stub = false);
aoqi@0 372 };
aoqi@0 373
aoqi@0 374
aoqi@0 375 inline bool vframeStreamCommon::fill_in_compiled_inlined_sender() {
aoqi@0 376 if (_sender_decode_offset == DebugInformationRecorder::serialized_null) {
aoqi@0 377 return false;
aoqi@0 378 }
aoqi@0 379 fill_from_compiled_frame(_sender_decode_offset);
aoqi@0 380 return true;
aoqi@0 381 }
aoqi@0 382
aoqi@0 383
aoqi@0 384 inline void vframeStreamCommon::fill_from_compiled_frame(int decode_offset) {
aoqi@0 385 _mode = compiled_mode;
aoqi@0 386
aoqi@0 387 // Range check to detect ridiculous offsets.
aoqi@0 388 if (decode_offset == DebugInformationRecorder::serialized_null ||
aoqi@0 389 decode_offset < 0 ||
aoqi@0 390 decode_offset >= nm()->scopes_data_size()) {
aoqi@0 391 // 6379830 AsyncGetCallTrace sometimes feeds us wild frames.
zmajo@7854 392 // If we read nmethod::scopes_data at serialized_null (== 0)
zmajo@7854 393 // or if read some at other invalid offset, invalid values will be decoded.
zmajo@7854 394 // Based on these values, invalid heap locations could be referenced
zmajo@7854 395 // that could lead to crashes in product mode.
zmajo@7854 396 // Therefore, do not use the decode offset if invalid, but fill the frame
zmajo@7854 397 // as it were a native compiled frame (no Java-level assumptions).
aoqi@0 398 #ifdef ASSERT
aoqi@0 399 if (WizardMode) {
aoqi@0 400 tty->print_cr("Error in fill_from_frame: pc_desc for "
aoqi@0 401 INTPTR_FORMAT " not found or invalid at %d",
aoqi@0 402 p2i(_frame.pc()), decode_offset);
aoqi@0 403 nm()->print();
aoqi@0 404 nm()->method()->print_codes();
aoqi@0 405 nm()->print_code();
aoqi@0 406 nm()->print_pcs();
aoqi@0 407 }
aoqi@0 408 #endif
aoqi@0 409 // Provide a cheap fallback in product mode. (See comment above.)
aoqi@0 410 found_bad_method_frame();
aoqi@0 411 fill_from_compiled_native_frame();
aoqi@0 412 return;
aoqi@0 413 }
aoqi@0 414
aoqi@0 415 // Decode first part of scopeDesc
aoqi@0 416 DebugInfoReadStream buffer(nm(), decode_offset);
aoqi@0 417 _sender_decode_offset = buffer.read_int();
aoqi@0 418 _method = buffer.read_method();
aoqi@0 419 _bci = buffer.read_bci();
aoqi@0 420
aoqi@0 421 assert(_method->is_method(), "checking type of decoded method");
aoqi@0 422 }
aoqi@0 423
aoqi@0 424 // The native frames are handled specially. We do not rely on ScopeDesc info
aoqi@0 425 // since the pc might not be exact due to the _last_native_pc trick.
aoqi@0 426 inline void vframeStreamCommon::fill_from_compiled_native_frame() {
aoqi@0 427 _mode = compiled_mode;
aoqi@0 428 _sender_decode_offset = DebugInformationRecorder::serialized_null;
aoqi@0 429 _method = nm()->method();
aoqi@0 430 _bci = 0;
aoqi@0 431 }
aoqi@0 432
aoqi@0 433 inline bool vframeStreamCommon::fill_from_frame() {
aoqi@0 434 // Interpreted frame
aoqi@0 435 if (_frame.is_interpreted_frame()) {
aoqi@0 436 fill_from_interpreter_frame();
aoqi@0 437 return true;
aoqi@0 438 }
aoqi@0 439
aoqi@0 440 // Compiled frame
aoqi@0 441
aoqi@0 442 if (cb() != NULL && cb()->is_nmethod()) {
aoqi@0 443 if (nm()->is_native_method()) {
aoqi@0 444 // Do not rely on scopeDesc since the pc might be unprecise due to the _last_native_pc trick.
aoqi@0 445 fill_from_compiled_native_frame();
aoqi@0 446 } else {
aoqi@0 447 PcDesc* pc_desc = nm()->pc_desc_at(_frame.pc());
aoqi@0 448 int decode_offset;
aoqi@0 449 if (pc_desc == NULL) {
aoqi@0 450 // Should not happen, but let fill_from_compiled_frame handle it.
aoqi@0 451
aoqi@0 452 // If we are trying to walk the stack of a thread that is not
aoqi@0 453 // at a safepoint (like AsyncGetCallTrace would do) then this is an
aoqi@0 454 // acceptable result. [ This is assuming that safe_for_sender
aoqi@0 455 // is so bullet proof that we can trust the frames it produced. ]
aoqi@0 456 //
aoqi@0 457 // So if we see that the thread is not safepoint safe
aoqi@0 458 // then simply produce the method and a bci of zero
aoqi@0 459 // and skip the possibility of decoding any inlining that
aoqi@0 460 // may be present. That is far better than simply stopping (or
aoqi@0 461 // asserting. If however the thread is safepoint safe this
aoqi@0 462 // is the sign of a compiler bug and we'll let
aoqi@0 463 // fill_from_compiled_frame handle it.
aoqi@0 464
aoqi@0 465
aoqi@0 466 JavaThreadState state = _thread->thread_state();
aoqi@0 467
aoqi@0 468 // in_Java should be good enough to test safepoint safety
aoqi@0 469 // if state were say in_Java_trans then we'd expect that
aoqi@0 470 // the pc would have already been slightly adjusted to
aoqi@0 471 // one that would produce a pcDesc since the trans state
aoqi@0 472 // would be one that might in fact anticipate a safepoint
aoqi@0 473
aoqi@0 474 if (state == _thread_in_Java ) {
aoqi@0 475 // This will get a method a zero bci and no inlining.
aoqi@0 476 // Might be nice to have a unique bci to signify this
aoqi@0 477 // particular case but for now zero will do.
aoqi@0 478
aoqi@0 479 fill_from_compiled_native_frame();
aoqi@0 480
aoqi@0 481 // There is something to be said for setting the mode to
aoqi@0 482 // at_end_mode to prevent trying to walk further up the
aoqi@0 483 // stack. There is evidence that if we walk any further
aoqi@0 484 // that we could produce a bad stack chain. However until
aoqi@0 485 // we see evidence that allowing this causes us to find
aoqi@0 486 // frames bad enough to cause segv's or assertion failures
aoqi@0 487 // we don't do it as while we may get a bad call chain the
aoqi@0 488 // probability is much higher (several magnitudes) that we
aoqi@0 489 // get good data.
aoqi@0 490
aoqi@0 491 return true;
aoqi@0 492 }
aoqi@0 493 decode_offset = DebugInformationRecorder::serialized_null;
aoqi@0 494 } else {
aoqi@0 495 decode_offset = pc_desc->scope_decode_offset();
aoqi@0 496 }
aoqi@0 497 fill_from_compiled_frame(decode_offset);
aoqi@0 498 }
aoqi@0 499 return true;
aoqi@0 500 }
aoqi@0 501
aoqi@0 502 // End of stack?
aoqi@0 503 if (_frame.is_first_frame() || (_stop_at_java_call_stub && _frame.is_entry_frame())) {
aoqi@0 504 _mode = at_end_mode;
aoqi@0 505 return true;
aoqi@0 506 }
aoqi@0 507
aoqi@0 508 return false;
aoqi@0 509 }
aoqi@0 510
aoqi@0 511
aoqi@0 512 inline void vframeStreamCommon::fill_from_interpreter_frame() {
aoqi@0 513 Method* method = _frame.interpreter_frame_method();
aoqi@0 514 intptr_t bcx = _frame.interpreter_frame_bcx();
aoqi@0 515 int bci = method->validate_bci_from_bcx(bcx);
aoqi@0 516 // 6379830 AsyncGetCallTrace sometimes feeds us wild frames.
zmajo@7854 517 // AsyncGetCallTrace interrupts the VM asynchronously. As a result
zmajo@7854 518 // it is possible to access an interpreter frame for which
zmajo@7854 519 // no Java-level information is yet available (e.g., becasue
zmajo@7854 520 // the frame was being created when the VM interrupted it).
zmajo@7854 521 // In this scenario, pretend that the interpreter is at the point
zmajo@7854 522 // of entering the method.
aoqi@0 523 if (bci < 0) {
aoqi@0 524 found_bad_method_frame();
zmajo@7854 525 bci = 0;
aoqi@0 526 }
aoqi@0 527 _mode = interpreted_mode;
aoqi@0 528 _method = method;
aoqi@0 529 _bci = bci;
aoqi@0 530 }
aoqi@0 531
aoqi@0 532 #endif // SHARE_VM_RUNTIME_VFRAME_HPP

mercurial