/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef SHARE_VM_RUNTIME_VFRAME_HPP
#define SHARE_VM_RUNTIME_VFRAME_HPP
#include "code/debugInfo.hpp"
#include "code/debugInfoRec.hpp"
#include "code/location.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.
// A single frame may hold several source level activations in the case of
// optimized code. The debugging stored with the optimized code enables
// us to unfold a frame as a stack of vframes.
// A cVFrame represents an activation of a non-java method.
// The vframe inheritance hierarchy:
// - vframe
// - javaVFrame
// - interpretedVFrame
// - compiledVFrame ; (used for both compiled Java methods and native stubs)
// - externalVFrame
// - entryVFrame ; special frame created when calling Java from C
// - BasicLock
protected:
public:
// Factory method for creating vframes
// Accessors
}
// ???? Does this need to be a copy?
// Returns the sender vframe
// Returns the next javaVFrame on the stack (skipping all other kinds of frame)
javaVFrame *java_sender() const;
// Answers if the this is the top vframe in the frame, i.e., if the sender vframe
// is in the caller frame
virtual bool is_top() const { return true; }
// Returns top vframe within same frame (see is_top())
// Type testing operations
virtual bool is_entry_frame() const { return false; }
virtual bool is_java_frame() const { return false; }
virtual bool is_interpreted_frame() const { return false; }
virtual bool is_compiled_frame() const { return false; }
#ifndef PRODUCT
// printing operations
virtual void print_value() const;
virtual void print();
#endif
};
public:
// JVM state
virtual int bci() const = 0;
virtual StackValueCollection* locals() const = 0;
virtual StackValueCollection* expressions() const = 0;
// the order returned by monitors() is from oldest -> youngest#4418568
// Debugging support via JVMTI.
// NOTE that this is not guaranteed to give correct results for compiled vframes.
// Deoptimize first if necessary.
// Test operation
bool is_java_frame() const { return true; }
protected:
javaVFrame(const frame* fr, const RegisterMap* reg_map, JavaThread* thread) : vframe(fr, reg_map, thread) {}
public:
// casting
return (javaVFrame*) vf;
}
// Return an array of monitors locked by this frame in the youngest to oldest order
// printing used during stack dumps
#ifndef PRODUCT
public:
// printing operations
void print();
void print_value() const;
void print_activation(int index) const;
// verify operations
virtual void verify() const;
// Structural compare
#endif
friend class vframe;
};
public:
// JVM state
int bci() const;
StackValueCollection* locals() const;
StackValueCollection* expressions() const;
// Test operation
bool is_interpreted_frame() const { return true; }
protected:
interpretedVFrame(const frame* fr, const RegisterMap* reg_map, JavaThread* thread) : javaVFrame(fr, reg_map, thread) {};
public:
// Accessors for Byte Code Pointer
// casting
return (interpretedVFrame*) vf;
}
private:
static const int bcp_offset;
// returns where the parameters starts relative to the frame pointer
int start_of_parameters() const;
#ifndef PRODUCT
public:
// verify operations
void verify() const;
#endif
friend class vframe;
};
protected:
externalVFrame(const frame* fr, const RegisterMap* reg_map, JavaThread* thread) : vframe(fr, reg_map, thread) {}
#ifndef PRODUCT
public:
// printing operations
void print_value() const;
void print();
#endif
friend class vframe;
};
public:
bool is_entry_frame() const { return true; }
protected:
public:
// casting
return (entryVFrame*) vf;
}
#ifndef PRODUCT
public:
// printing
void print_value() const;
void print();
#endif
friend class vframe;
};
// A MonitorInfo is a ResourceObject that describes a the pair:
// 1) the owner of the monitor
// 2) the monitor lock
private:
bool _eliminated;
public:
// Constructor
if (!owner_is_scalar_replaced) {
_owner_klass = NULL;
} else {
}
}
// Accessors
return _owner;
}
return (klassOop)_owner_klass;
}
};
protected:
// common
// Cached information
int _bci;
// Should VM activations be ignored or not
bool _stop_at_java_call_stub;
bool fill_in_compiled_inlined_sender();
void fill_from_compiled_frame(int decode_offset);
void fill_from_compiled_native_frame();
void found_bad_method_frame();
void fill_from_interpreter_frame();
bool fill_from_frame();
// Helper routine for security_get_caller_frame
public:
// Constructor
}
// Accessors
}
// Frame type
// Iteration
void next() {
// handle frames with inlining
// handle general case
do {
} while (!fill_from_frame());
}
// Implements security traversal. Skips depth no. of frame including
// special security frames and prefixed native methods
void security_get_caller_frame(int depth);
// Helper routine for JVM_LatestUserDefinedLoader -- needed for 1.4
// reflection implementation
void skip_reflection_related_frames();
};
public:
// Constructors
: vframeStreamCommon(thread) {
if (!thread->has_last_Java_frame()) {
_mode = at_end_mode;
return;
}
while (!fill_from_frame()) {
}
}
// top_frame may not be at safepoint, start with sender
};
return false;
}
return true;
}
// Range check to detect ridiculous offsets.
decode_offset < 0 ||
// 6379830 AsyncGetCallTrace sometimes feeds us wild frames.
// If we attempt to read nmethod::scopes_data at serialized_null (== 0),
// or if we read some at other crazy offset,
// we will decode garbage and make wild references into the heap,
// leading to crashes in product mode.
// (This isn't airtight, of course, since there are internal
// offsets which are also crazy.)
#ifdef ASSERT
if (WizardMode) {
INTPTR_FORMAT " not found or invalid at %d",
nm()->print_code();
}
#endif
// Provide a cheap fallback in product mode. (See comment above.)
return;
}
// Decode first part of scopeDesc
}
// 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.
_bci = 0;
}
// Interpreted frame
if (_frame.is_interpreted_frame()) {
return true;
}
// Compiled frame
if (nm()->is_native_method()) {
// Do not rely on scopeDesc since the pc might be unprecise due to the _last_native_pc trick.
} else {
int decode_offset;
// 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.
// 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.
// 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;
}
} else {
}
}
return true;
}
// End of stack?
_mode = at_end_mode;
return true;
}
return false;
}
// 6379830 AsyncGetCallTrace sometimes feeds us wild frames.
if (bci < 0) {
bci = 0; // pretend it's on the point of entering
}
}
#endif // SHARE_VM_RUNTIME_VFRAME_HPP