< prev index next >
src/hotspot/share/runtime/vframe.hpp
Print this page
*** 28,38 ****
#include "code/debugInfo.hpp"
#include "code/debugInfoRec.hpp"
#include "code/location.hpp"
#include "oops/oop.hpp"
#include "runtime/frame.hpp"
- #include "runtime/frame.inline.hpp"
#include "runtime/stackValue.hpp"
#include "runtime/stackValueCollection.hpp"
#include "utilities/growableArray.hpp"
// vframes are virtual stack frames representing source level activations.
--- 28,37 ----
*** 305,344 ****
DEBUG_ONLY(void found_bad_method_frame() const;)
public:
// Constructor
! vframeStreamCommon(JavaThread* thread) : _reg_map(thread, false) {
! _thread = thread;
! }
// Accessors
Method* method() const { return _method; }
int bci() const { return _bci; }
! intptr_t* frame_id() const { return _frame.id(); }
address frame_pc() const { return _frame.pc(); }
CodeBlob* cb() const { return _frame.cb(); }
CompiledMethod* nm() const {
assert( cb() != NULL && cb()->is_compiled(), "usage");
return (CompiledMethod*) cb();
}
// Frame type
! bool is_interpreted_frame() const { return _frame.is_interpreted_frame(); }
! bool is_entry_frame() const { return _frame.is_entry_frame(); }
// Iteration
! void next() {
! // handle frames with inlining
! if (_mode == compiled_mode && fill_in_compiled_inlined_sender()) return;
!
! // handle general case
! do {
! _frame = _frame.sender(&_reg_map);
! } while (!fill_from_frame());
! }
void security_next();
bool at_end() const { return _mode == at_end_mode; }
// Implements security traversal. Skips depth no. of frame including
--- 304,333 ----
DEBUG_ONLY(void found_bad_method_frame() const;)
public:
// Constructor
! vframeStreamCommon(JavaThread* thread);
// Accessors
Method* method() const { return _method; }
int bci() const { return _bci; }
! intptr_t* frame_id() const;
address frame_pc() const { return _frame.pc(); }
CodeBlob* cb() const { return _frame.cb(); }
CompiledMethod* nm() const {
assert( cb() != NULL && cb()->is_compiled(), "usage");
return (CompiledMethod*) cb();
}
// Frame type
! bool is_interpreted_frame() const;
! bool is_entry_frame() const;
// Iteration
! void next();
void security_next();
bool at_end() const { return _mode == at_end_mode; }
// Implements security traversal. Skips depth no. of frame including
*** 351,534 ****
};
class vframeStream : public vframeStreamCommon {
public:
// Constructors
! vframeStream(JavaThread* thread, bool stop_at_java_call_stub = false)
! : vframeStreamCommon(thread) {
! _stop_at_java_call_stub = stop_at_java_call_stub;
!
! if (!thread->has_last_Java_frame()) {
! _mode = at_end_mode;
! return;
! }
!
! _frame = _thread->last_frame();
! while (!fill_from_frame()) {
! _frame = _frame.sender(&_reg_map);
! }
! }
// top_frame may not be at safepoint, start with sender
vframeStream(JavaThread* thread, frame top_frame, bool stop_at_java_call_stub = false);
};
-
- inline bool vframeStreamCommon::fill_in_compiled_inlined_sender() {
- if (_sender_decode_offset == DebugInformationRecorder::serialized_null) {
- return false;
- }
- fill_from_compiled_frame(_sender_decode_offset);
- return true;
- }
-
-
- inline void vframeStreamCommon::fill_from_compiled_frame(int decode_offset) {
- _mode = compiled_mode;
-
- // Range check to detect ridiculous offsets.
- if (decode_offset == DebugInformationRecorder::serialized_null ||
- decode_offset < 0 ||
- decode_offset >= nm()->scopes_data_size()) {
- // 6379830 AsyncGetCallTrace sometimes feeds us wild frames.
- // If we read nmethod::scopes_data at serialized_null (== 0)
- // or if read some at other invalid offset, invalid values will be decoded.
- // Based on these values, invalid heap locations could be referenced
- // that could lead to crashes in product mode.
- // Therefore, do not use the decode offset if invalid, but fill the frame
- // as it were a native compiled frame (no Java-level assumptions).
- #ifdef ASSERT
- if (WizardMode) {
- ttyLocker ttyl;
- tty->print_cr("Error in fill_from_frame: pc_desc for "
- INTPTR_FORMAT " not found or invalid at %d",
- p2i(_frame.pc()), decode_offset);
- nm()->print();
- nm()->method()->print_codes();
- nm()->print_code();
- nm()->print_pcs();
- }
- found_bad_method_frame();
- #endif
- // Provide a cheap fallback in product mode. (See comment above.)
- fill_from_compiled_native_frame();
- return;
- }
-
- // Decode first part of scopeDesc
- DebugInfoReadStream buffer(nm(), decode_offset);
- _sender_decode_offset = buffer.read_int();
- _method = buffer.read_method();
- _bci = buffer.read_bci();
-
- assert(_method->is_method(), "checking type of decoded method");
- }
-
- // The native frames are handled specially. We do not rely on ScopeDesc info
- // since the pc might not be exact due to the _last_native_pc trick.
- inline void vframeStreamCommon::fill_from_compiled_native_frame() {
- _mode = compiled_mode;
- _sender_decode_offset = DebugInformationRecorder::serialized_null;
- _method = nm()->method();
- _bci = 0;
- }
-
- inline bool vframeStreamCommon::fill_from_frame() {
- // Interpreted frame
- if (_frame.is_interpreted_frame()) {
- fill_from_interpreter_frame();
- return true;
- }
-
- // Compiled frame
-
- if (cb() != NULL && cb()->is_compiled()) {
- if (nm()->is_native_method()) {
- // Do not rely on scopeDesc since the pc might be unprecise due to the _last_native_pc trick.
- fill_from_compiled_native_frame();
- } else {
- PcDesc* pc_desc = nm()->pc_desc_at(_frame.pc());
- int decode_offset;
- if (pc_desc == NULL) {
- // Should not happen, but let fill_from_compiled_frame handle it.
-
- // If we are trying to walk the stack of a thread that is not
- // at a safepoint (like AsyncGetCallTrace would do) then this is an
- // acceptable result. [ This is assuming that safe_for_sender
- // is so bullet proof that we can trust the frames it produced. ]
- //
- // So if we see that the thread is not safepoint safe
- // then simply produce the method and a bci of zero
- // and skip the possibility of decoding any inlining that
- // may be present. That is far better than simply stopping (or
- // asserting. If however the thread is safepoint safe this
- // is the sign of a compiler bug and we'll let
- // fill_from_compiled_frame handle it.
-
-
- JavaThreadState state = _thread->thread_state();
-
- // in_Java should be good enough to test safepoint safety
- // if state were say in_Java_trans then we'd expect that
- // the pc would have already been slightly adjusted to
- // one that would produce a pcDesc since the trans state
- // would be one that might in fact anticipate a safepoint
-
- if (state == _thread_in_Java ) {
- // This will get a method a zero bci and no inlining.
- // Might be nice to have a unique bci to signify this
- // particular case but for now zero will do.
-
- fill_from_compiled_native_frame();
-
- // There is something to be said for setting the mode to
- // at_end_mode to prevent trying to walk further up the
- // stack. There is evidence that if we walk any further
- // that we could produce a bad stack chain. However until
- // we see evidence that allowing this causes us to find
- // frames bad enough to cause segv's or assertion failures
- // we don't do it as while we may get a bad call chain the
- // probability is much higher (several magnitudes) that we
- // get good data.
-
- return true;
- }
- decode_offset = DebugInformationRecorder::serialized_null;
- } else {
- decode_offset = pc_desc->scope_decode_offset();
- }
- fill_from_compiled_frame(decode_offset);
- }
- return true;
- }
-
- // End of stack?
- if (_frame.is_first_frame() || (_stop_at_java_call_stub && _frame.is_entry_frame())) {
- _mode = at_end_mode;
- return true;
- }
-
- return false;
- }
-
-
- inline void vframeStreamCommon::fill_from_interpreter_frame() {
- Method* method = _frame.interpreter_frame_method();
- address bcp = _frame.interpreter_frame_bcp();
- int bci = method->validate_bci_from_bcp(bcp);
- // 6379830 AsyncGetCallTrace sometimes feeds us wild frames.
- // AsyncGetCallTrace interrupts the VM asynchronously. As a result
- // it is possible to access an interpreter frame for which
- // no Java-level information is yet available (e.g., becasue
- // the frame was being created when the VM interrupted it).
- // In this scenario, pretend that the interpreter is at the point
- // of entering the method.
- if (bci < 0) {
- DEBUG_ONLY(found_bad_method_frame();)
- bci = 0;
- }
- _mode = interpreted_mode;
- _method = method;
- _bci = bci;
- }
-
#endif // SHARE_VM_RUNTIME_VFRAME_HPP
--- 340,351 ----
};
class vframeStream : public vframeStreamCommon {
public:
// Constructors
! vframeStream(JavaThread* thread, bool stop_at_java_call_stub = false);
// top_frame may not be at safepoint, start with sender
vframeStream(JavaThread* thread, frame top_frame, bool stop_at_java_call_stub = false);
};
#endif // SHARE_VM_RUNTIME_VFRAME_HPP
< prev index next >