8153123: Streamline StackWalker code
Reviewed-by: coleenp, dfuchs, mchung, redestad
This commit is contained in:
parent
87d68625af
commit
2d2abce433
@ -41,7 +41,6 @@
|
||||
JVM_DumpAllStacks;
|
||||
JVM_DumpThreads;
|
||||
JVM_FillInStackTrace;
|
||||
JVM_FillStackFrames;
|
||||
JVM_FindClassFromCaller;
|
||||
JVM_FindClassFromClass;
|
||||
JVM_FindClassFromBootLoader;
|
||||
@ -157,13 +156,13 @@
|
||||
JVM_SetClassSigners;
|
||||
JVM_SetNativeThreadName;
|
||||
JVM_SetPrimitiveArrayElement;
|
||||
JVM_SetMethodInfo;
|
||||
JVM_SetThreadPriority;
|
||||
JVM_Sleep;
|
||||
JVM_StartThread;
|
||||
JVM_StopThread;
|
||||
JVM_SuspendThread;
|
||||
JVM_SupportsCX8;
|
||||
JVM_ToStackTraceElement;
|
||||
JVM_TotalMemory;
|
||||
JVM_UnloadLibrary;
|
||||
JVM_Yield;
|
||||
|
@ -58,7 +58,6 @@ JVM_DoPrivileged
|
||||
JVM_DumpAllStacks
|
||||
JVM_DumpThreads
|
||||
JVM_FillInStackTrace
|
||||
JVM_FillStackFrames
|
||||
JVM_FindClassFromCaller
|
||||
JVM_FindClassFromClass
|
||||
JVM_FindLibraryEntry
|
||||
@ -169,7 +168,6 @@ JVM_ReleaseUTF
|
||||
JVM_ResumeThread
|
||||
JVM_SetArrayElement
|
||||
JVM_SetClassSigners
|
||||
JVM_SetMethodInfo
|
||||
JVM_SetNativeThreadName
|
||||
JVM_SetPrimitiveArrayElement
|
||||
JVM_SetThreadPriority
|
||||
@ -178,6 +176,7 @@ JVM_StartThread
|
||||
JVM_StopThread
|
||||
JVM_SupportsCX8
|
||||
JVM_SuspendThread
|
||||
JVM_ToStackTraceElement
|
||||
JVM_TotalMemory
|
||||
JVM_UnloadLibrary
|
||||
JVM_Yield
|
||||
|
@ -2187,43 +2187,19 @@ void java_lang_StackTraceElement::fill_in(Handle element,
|
||||
}
|
||||
|
||||
Method* java_lang_StackFrameInfo::get_method(Handle stackFrame, InstanceKlass* holder, TRAPS) {
|
||||
if (MemberNameInStackFrame) {
|
||||
Handle mname(THREAD, stackFrame->obj_field(_memberName_offset));
|
||||
Method* method = (Method*)java_lang_invoke_MemberName::vmtarget(mname());
|
||||
// we should expand MemberName::name when Throwable uses StackTrace
|
||||
// MethodHandles::expand_MemberName(mname, MethodHandles::_suppress_defc|MethodHandles::_suppress_type, CHECK_NULL);
|
||||
return method;
|
||||
} else {
|
||||
short mid = stackFrame->short_field(_mid_offset);
|
||||
short version = stackFrame->short_field(_version_offset);
|
||||
return holder->method_with_orig_idnum(mid, version);
|
||||
}
|
||||
}
|
||||
|
||||
Symbol* java_lang_StackFrameInfo::get_file_name(Handle stackFrame, InstanceKlass* holder) {
|
||||
if (MemberNameInStackFrame) {
|
||||
return holder->source_file_name();
|
||||
} else {
|
||||
short version = stackFrame->short_field(_version_offset);
|
||||
return Backtrace::get_source_file_name(holder, version);
|
||||
}
|
||||
Handle mname(THREAD, stackFrame->obj_field(_memberName_offset));
|
||||
Method* method = (Method*)java_lang_invoke_MemberName::vmtarget(mname());
|
||||
// we should expand MemberName::name when Throwable uses StackTrace
|
||||
// MethodHandles::expand_MemberName(mname, MethodHandles::_suppress_defc|MethodHandles::_suppress_type, CHECK_NULL);
|
||||
return method;
|
||||
}
|
||||
|
||||
void java_lang_StackFrameInfo::set_method_and_bci(Handle stackFrame, const methodHandle& method, int bci) {
|
||||
// set Method* or mid/cpref
|
||||
if (MemberNameInStackFrame) {
|
||||
oop mname = stackFrame->obj_field(_memberName_offset);
|
||||
InstanceKlass* ik = method->method_holder();
|
||||
CallInfo info(method(), ik);
|
||||
MethodHandles::init_method_MemberName(mname, info);
|
||||
} else {
|
||||
int mid = method->orig_method_idnum();
|
||||
int cpref = method->name_index();
|
||||
assert((jushort)mid == mid, "mid should be short");
|
||||
assert((jushort)cpref == cpref, "cpref should be short");
|
||||
java_lang_StackFrameInfo::set_mid(stackFrame(), (short)mid);
|
||||
java_lang_StackFrameInfo::set_cpref(stackFrame(), (short)cpref);
|
||||
}
|
||||
oop mname = stackFrame->obj_field(_memberName_offset);
|
||||
InstanceKlass* ik = method->method_holder();
|
||||
CallInfo info(method(), ik);
|
||||
MethodHandles::init_method_MemberName(mname, info);
|
||||
// set bci
|
||||
java_lang_StackFrameInfo::set_bci(stackFrame(), bci);
|
||||
// method may be redefined; store the version
|
||||
@ -2232,52 +2208,23 @@ void java_lang_StackFrameInfo::set_method_and_bci(Handle stackFrame, const metho
|
||||
java_lang_StackFrameInfo::set_version(stackFrame(), (short)version);
|
||||
}
|
||||
|
||||
void java_lang_StackFrameInfo::fill_methodInfo(Handle stackFrame, TRAPS) {
|
||||
void java_lang_StackFrameInfo::to_stack_trace_element(Handle stackFrame, Handle stack_trace_element, TRAPS) {
|
||||
ResourceMark rm(THREAD);
|
||||
oop k = stackFrame->obj_field(_declaringClass_offset);
|
||||
InstanceKlass* holder = InstanceKlass::cast(java_lang_Class::as_Klass(k));
|
||||
Handle k (THREAD, stackFrame->obj_field(_declaringClass_offset));
|
||||
InstanceKlass* holder = InstanceKlass::cast(java_lang_Class::as_Klass(k()));
|
||||
Method* method = java_lang_StackFrameInfo::get_method(stackFrame, holder, CHECK);
|
||||
int bci = stackFrame->int_field(_bci_offset);
|
||||
|
||||
// The method can be NULL if the requested class version is gone
|
||||
Symbol* sym = (method != NULL) ? method->name() : NULL;
|
||||
if (MemberNameInStackFrame) {
|
||||
assert(sym != NULL, "MemberName must have method name");
|
||||
} else {
|
||||
// The method can be NULL if the requested class version is gone
|
||||
if (sym == NULL) {
|
||||
short cpref = stackFrame->short_field(_cpref_offset);
|
||||
sym = holder->constants()->symbol_at(cpref);
|
||||
}
|
||||
}
|
||||
|
||||
// set method name
|
||||
oop methodname = StringTable::intern(sym, CHECK);
|
||||
java_lang_StackFrameInfo::set_methodName(stackFrame(), methodname);
|
||||
|
||||
// set file name and line number
|
||||
Symbol* source = get_file_name(stackFrame, holder);
|
||||
if (source != NULL) {
|
||||
oop filename = StringTable::intern(source, CHECK);
|
||||
java_lang_StackFrameInfo::set_fileName(stackFrame(), filename);
|
||||
}
|
||||
|
||||
// if the method has been redefined, the bci is no longer applicable
|
||||
short version = stackFrame->short_field(_version_offset);
|
||||
if (version_matches(method, version)) {
|
||||
int line_number = Backtrace::get_line_number(method, bci);
|
||||
java_lang_StackFrameInfo::set_lineNumber(stackFrame(), line_number);
|
||||
}
|
||||
short bci = stackFrame->short_field(_bci_offset);
|
||||
int cpref = method->name_index();
|
||||
java_lang_StackTraceElement::fill_in(stack_trace_element, holder, method, version, bci, cpref, CHECK);
|
||||
}
|
||||
|
||||
void java_lang_StackFrameInfo::compute_offsets() {
|
||||
Klass* k = SystemDictionary::StackFrameInfo_klass();
|
||||
compute_offset(_declaringClass_offset, k, vmSymbols::declaringClass_name(), vmSymbols::class_signature());
|
||||
compute_offset(_memberName_offset, k, vmSymbols::memberName_name(), vmSymbols::object_signature());
|
||||
compute_offset(_bci_offset, k, vmSymbols::bci_name(), vmSymbols::int_signature());
|
||||
compute_offset(_methodName_offset, k, vmSymbols::methodName_name(), vmSymbols::string_signature());
|
||||
compute_offset(_fileName_offset, k, vmSymbols::fileName_name(), vmSymbols::string_signature());
|
||||
compute_offset(_lineNumber_offset, k, vmSymbols::lineNumber_name(), vmSymbols::int_signature());
|
||||
compute_offset(_bci_offset, k, vmSymbols::bci_name(), vmSymbols::short_signature());
|
||||
STACKFRAMEINFO_INJECTED_FIELDS(INJECTED_FIELD_COMPUTE_OFFSET);
|
||||
}
|
||||
|
||||
@ -3690,12 +3637,7 @@ int java_lang_StackTraceElement::moduleVersion_offset;
|
||||
int java_lang_StackFrameInfo::_declaringClass_offset;
|
||||
int java_lang_StackFrameInfo::_memberName_offset;
|
||||
int java_lang_StackFrameInfo::_bci_offset;
|
||||
int java_lang_StackFrameInfo::_methodName_offset;
|
||||
int java_lang_StackFrameInfo::_fileName_offset;
|
||||
int java_lang_StackFrameInfo::_lineNumber_offset;
|
||||
int java_lang_StackFrameInfo::_mid_offset;
|
||||
int java_lang_StackFrameInfo::_version_offset;
|
||||
int java_lang_StackFrameInfo::_cpref_offset;
|
||||
int java_lang_LiveStackFrameInfo::_monitors_offset;
|
||||
int java_lang_LiveStackFrameInfo::_locals_offset;
|
||||
int java_lang_LiveStackFrameInfo::_operands_offset;
|
||||
@ -3741,34 +3683,14 @@ void java_lang_StackFrameInfo::set_declaringClass(oop element, oop value) {
|
||||
element->obj_field_put(_declaringClass_offset, value);
|
||||
}
|
||||
|
||||
void java_lang_StackFrameInfo::set_mid(oop element, short value) {
|
||||
element->short_field_put(_mid_offset, value);
|
||||
}
|
||||
|
||||
void java_lang_StackFrameInfo::set_version(oop element, short value) {
|
||||
element->short_field_put(_version_offset, value);
|
||||
}
|
||||
|
||||
void java_lang_StackFrameInfo::set_cpref(oop element, short value) {
|
||||
element->short_field_put(_cpref_offset, value);
|
||||
}
|
||||
|
||||
void java_lang_StackFrameInfo::set_bci(oop element, int value) {
|
||||
element->int_field_put(_bci_offset, value);
|
||||
}
|
||||
|
||||
void java_lang_StackFrameInfo::set_fileName(oop element, oop value) {
|
||||
element->obj_field_put(_fileName_offset, value);
|
||||
}
|
||||
|
||||
void java_lang_StackFrameInfo::set_methodName(oop element, oop value) {
|
||||
element->obj_field_put(_methodName_offset, value);
|
||||
}
|
||||
|
||||
void java_lang_StackFrameInfo::set_lineNumber(oop element, int value) {
|
||||
element->int_field_put(_lineNumber_offset, value);
|
||||
}
|
||||
|
||||
void java_lang_LiveStackFrameInfo::set_monitors(oop element, oop value) {
|
||||
element->obj_field_put(_monitors_offset, value);
|
||||
}
|
||||
|
@ -1364,25 +1364,16 @@ class Backtrace: AllStatic {
|
||||
// Interface to java.lang.StackFrameInfo objects
|
||||
|
||||
#define STACKFRAMEINFO_INJECTED_FIELDS(macro) \
|
||||
macro(java_lang_StackFrameInfo, mid, short_signature, false) \
|
||||
macro(java_lang_StackFrameInfo, version, short_signature, false) \
|
||||
macro(java_lang_StackFrameInfo, cpref, short_signature, false)
|
||||
macro(java_lang_StackFrameInfo, version, short_signature, false)
|
||||
|
||||
class java_lang_StackFrameInfo: AllStatic {
|
||||
private:
|
||||
static int _declaringClass_offset;
|
||||
static int _memberName_offset;
|
||||
static int _bci_offset;
|
||||
static int _methodName_offset;
|
||||
static int _fileName_offset;
|
||||
static int _lineNumber_offset;
|
||||
|
||||
static int _mid_offset;
|
||||
static int _version_offset;
|
||||
static int _cpref_offset;
|
||||
|
||||
static Method* get_method(Handle stackFrame, InstanceKlass* holder, TRAPS);
|
||||
static Symbol* get_file_name(Handle stackFrame, InstanceKlass* holder);
|
||||
|
||||
public:
|
||||
// Setters
|
||||
@ -1390,19 +1381,12 @@ public:
|
||||
static void set_method_and_bci(Handle stackFrame, const methodHandle& method, int bci);
|
||||
static void set_bci(oop info, int value);
|
||||
|
||||
// set method info in an instance of StackFrameInfo
|
||||
static void fill_methodInfo(Handle info, TRAPS);
|
||||
static void set_methodName(oop info, oop value);
|
||||
static void set_fileName(oop info, oop value);
|
||||
static void set_lineNumber(oop info, int value);
|
||||
|
||||
// these injected fields are only used if -XX:-MemberNameInStackFrame set
|
||||
static void set_mid(oop info, short value);
|
||||
static void set_version(oop info, short value);
|
||||
static void set_cpref(oop info, short value);
|
||||
|
||||
static void compute_offsets();
|
||||
|
||||
static void to_stack_trace_element(Handle stackFrame, Handle stack_trace_element, TRAPS);
|
||||
|
||||
// Debugging
|
||||
friend class JavaClasses;
|
||||
};
|
||||
|
@ -534,7 +534,6 @@ JVM_END
|
||||
|
||||
JVM_ENTRY(jobject, JVM_CallStackWalk(JNIEnv *env, jobject stackStream, jlong mode,
|
||||
jint skip_frames, jint frame_count, jint start_index,
|
||||
jobjectArray classes,
|
||||
jobjectArray frames))
|
||||
JVMWrapper("JVM_CallStackWalk");
|
||||
JavaThread* jt = (JavaThread*) THREAD;
|
||||
@ -543,78 +542,51 @@ JVM_ENTRY(jobject, JVM_CallStackWalk(JNIEnv *env, jobject stackStream, jlong mod
|
||||
}
|
||||
|
||||
Handle stackStream_h(THREAD, JNIHandles::resolve_non_null(stackStream));
|
||||
objArrayOop ca = objArrayOop(JNIHandles::resolve_non_null(classes));
|
||||
objArrayHandle classes_array_h(THREAD, ca);
|
||||
|
||||
// frames array is null when only getting caller reference
|
||||
objArrayOop fa = objArrayOop(JNIHandles::resolve(frames));
|
||||
// frames array is a Class<?>[] array when only getting caller reference,
|
||||
// and a StackFrameInfo[] array (or derivative) otherwise. It should never
|
||||
// be null.
|
||||
objArrayOop fa = objArrayOop(JNIHandles::resolve_non_null(frames));
|
||||
objArrayHandle frames_array_h(THREAD, fa);
|
||||
|
||||
int limit = start_index + frame_count;
|
||||
if (classes_array_h->length() < limit) {
|
||||
if (frames_array_h->length() < limit) {
|
||||
THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(), "not enough space in buffers", NULL);
|
||||
}
|
||||
|
||||
Handle result = StackWalk::walk(stackStream_h, mode, skip_frames, frame_count,
|
||||
start_index, classes_array_h,
|
||||
frames_array_h, CHECK_NULL);
|
||||
start_index, frames_array_h, CHECK_NULL);
|
||||
return JNIHandles::make_local(env, result());
|
||||
JVM_END
|
||||
|
||||
|
||||
JVM_ENTRY(jint, JVM_MoreStackWalk(JNIEnv *env, jobject stackStream, jlong mode, jlong anchor,
|
||||
jint frame_count, jint start_index,
|
||||
jobjectArray classes,
|
||||
jobjectArray frames))
|
||||
JVMWrapper("JVM_MoreStackWalk");
|
||||
JavaThread* jt = (JavaThread*) THREAD;
|
||||
objArrayOop ca = objArrayOop(JNIHandles::resolve_non_null(classes));
|
||||
objArrayHandle classes_array_h(THREAD, ca);
|
||||
|
||||
// frames array is null when only getting caller reference
|
||||
objArrayOop fa = objArrayOop(JNIHandles::resolve(frames));
|
||||
// frames array is a Class<?>[] array when only getting caller reference,
|
||||
// and a StackFrameInfo[] array (or derivative) otherwise. It should never
|
||||
// be null.
|
||||
objArrayOop fa = objArrayOop(JNIHandles::resolve_non_null(frames));
|
||||
objArrayHandle frames_array_h(THREAD, fa);
|
||||
|
||||
int limit = start_index+frame_count;
|
||||
if (classes_array_h->length() < limit) {
|
||||
if (frames_array_h->length() < limit) {
|
||||
THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "not enough space in buffers");
|
||||
}
|
||||
|
||||
Handle stackStream_h(THREAD, JNIHandles::resolve_non_null(stackStream));
|
||||
return StackWalk::moreFrames(stackStream_h, mode, anchor, frame_count,
|
||||
start_index, classes_array_h,
|
||||
frames_array_h, THREAD);
|
||||
start_index, frames_array_h, THREAD);
|
||||
JVM_END
|
||||
|
||||
JVM_ENTRY(void, JVM_FillStackFrames(JNIEnv *env, jclass stackStream,
|
||||
jint start_index,
|
||||
jobjectArray frames,
|
||||
jint from_index, jint to_index))
|
||||
JVMWrapper("JVM_FillStackFrames");
|
||||
if (TraceStackWalk) {
|
||||
tty->print("JVM_FillStackFrames() start_index=%d from_index=%d to_index=%d\n",
|
||||
start_index, from_index, to_index);
|
||||
}
|
||||
|
||||
JavaThread* jt = (JavaThread*) THREAD;
|
||||
|
||||
objArrayOop fa = objArrayOop(JNIHandles::resolve_non_null(frames));
|
||||
objArrayHandle frames_array_h(THREAD, fa);
|
||||
|
||||
if (frames_array_h->length() < to_index) {
|
||||
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "array length not matched");
|
||||
}
|
||||
|
||||
for (int i = from_index; i < to_index; i++) {
|
||||
Handle stackFrame(THREAD, frames_array_h->obj_at(i));
|
||||
java_lang_StackFrameInfo::fill_methodInfo(stackFrame, CHECK);
|
||||
}
|
||||
JVM_END
|
||||
|
||||
JVM_ENTRY(void, JVM_SetMethodInfo(JNIEnv *env, jobject frame))
|
||||
JVMWrapper("JVM_SetMethodInfo");
|
||||
Handle stackFrame(THREAD, JNIHandles::resolve(frame));
|
||||
java_lang_StackFrameInfo::fill_methodInfo(stackFrame, THREAD);
|
||||
JVM_ENTRY(void, JVM_ToStackTraceElement(JNIEnv *env, jobject frame, jobject stack))
|
||||
JVMWrapper("JVM_ToStackTraceElement");
|
||||
Handle stack_frame_info(THREAD, JNIHandles::resolve_non_null(frame));
|
||||
Handle stack_trace_element(THREAD, JNIHandles::resolve_non_null(stack));
|
||||
java_lang_StackFrameInfo::to_stack_trace_element(stack_frame_info, stack_trace_element, THREAD);
|
||||
JVM_END
|
||||
|
||||
// java.lang.Object ///////////////////////////////////////////////
|
||||
|
@ -209,7 +209,6 @@ JVM_GetStackTraceElements(JNIEnv *env, jobject throwable, jobjectArray elements)
|
||||
*/
|
||||
enum {
|
||||
JVM_STACKWALK_FILL_CLASS_REFS_ONLY = 0x2,
|
||||
JVM_STACKWALK_FILTER_FILL_IN_STACK_TRACE = 0x10,
|
||||
JVM_STACKWALK_SHOW_HIDDEN_FRAMES = 0x20,
|
||||
JVM_STACKWALK_FILL_LIVE_STACK_FRAMES = 0x100
|
||||
};
|
||||
@ -217,23 +216,15 @@ enum {
|
||||
JNIEXPORT jobject JNICALL
|
||||
JVM_CallStackWalk(JNIEnv *env, jobject stackStream, jlong mode,
|
||||
jint skip_frames, jint frame_count, jint start_index,
|
||||
jobjectArray classes,
|
||||
jobjectArray frames);
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
JVM_MoreStackWalk(JNIEnv *env, jobject stackStream, jlong mode, jlong anchor,
|
||||
jint frame_count, jint start_index,
|
||||
jobjectArray classes,
|
||||
jobjectArray frames);
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
JVM_FillStackFrames(JNIEnv* env, jclass cls,
|
||||
jint start_index,
|
||||
jobjectArray frames,
|
||||
jint from_index, jint toIndex);
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
JVM_SetMethodInfo(JNIEnv* env, jobject frame);
|
||||
JVM_ToStackTraceElement(JNIEnv* env, jobject frame, jobject stackElement);
|
||||
|
||||
/*
|
||||
* java.lang.Thread
|
||||
|
@ -37,22 +37,22 @@
|
||||
#include "utilities/globalDefinitions.hpp"
|
||||
|
||||
// setup and cleanup actions
|
||||
void StackWalkAnchor::setup_magic_on_entry(objArrayHandle classes_array) {
|
||||
classes_array->obj_at_put(magic_pos, _thread->threadObj());
|
||||
void StackWalkAnchor::setup_magic_on_entry(objArrayHandle frames_array) {
|
||||
frames_array->obj_at_put(magic_pos, _thread->threadObj());
|
||||
_anchor = address_value();
|
||||
assert(check_magic(classes_array), "invalid magic");
|
||||
assert(check_magic(frames_array), "invalid magic");
|
||||
}
|
||||
|
||||
bool StackWalkAnchor::check_magic(objArrayHandle classes_array) {
|
||||
oop m1 = classes_array->obj_at(magic_pos);
|
||||
bool StackWalkAnchor::check_magic(objArrayHandle frames_array) {
|
||||
oop m1 = frames_array->obj_at(magic_pos);
|
||||
jlong m2 = _anchor;
|
||||
if (m1 == _thread->threadObj() && m2 == address_value()) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool StackWalkAnchor::cleanup_magic_on_exit(objArrayHandle classes_array) {
|
||||
bool ok = check_magic(classes_array);
|
||||
classes_array->obj_at_put(magic_pos, NULL);
|
||||
bool StackWalkAnchor::cleanup_magic_on_exit(objArrayHandle frames_array) {
|
||||
bool ok = check_magic(frames_array);
|
||||
frames_array->obj_at_put(magic_pos, NULL);
|
||||
_anchor = 0L;
|
||||
return ok;
|
||||
}
|
||||
@ -62,18 +62,18 @@ bool StackWalkAnchor::cleanup_magic_on_exit(objArrayHandle classes_array) {
|
||||
// Parameters:
|
||||
// thread Current Java thread.
|
||||
// magic Magic value used for each stack walking
|
||||
// classes_array User-supplied buffers. The 0th element is reserved
|
||||
// frames_array User-supplied buffers. The 0th element is reserved
|
||||
// to this StackWalkAnchor to use
|
||||
//
|
||||
StackWalkAnchor* StackWalkAnchor::from_current(JavaThread* thread, jlong magic,
|
||||
objArrayHandle classes_array)
|
||||
objArrayHandle frames_array)
|
||||
{
|
||||
assert(thread != NULL && thread->is_Java_thread(), "");
|
||||
oop m1 = classes_array->obj_at(magic_pos);
|
||||
oop m1 = frames_array->obj_at(magic_pos);
|
||||
if (m1 != thread->threadObj()) return NULL;
|
||||
if (magic == 0L) return NULL;
|
||||
StackWalkAnchor* anchor = (StackWalkAnchor*) (intptr_t) magic;
|
||||
if (!anchor->is_valid_in(thread, classes_array)) return NULL;
|
||||
if (!anchor->is_valid_in(thread, frames_array)) return NULL;
|
||||
return anchor;
|
||||
}
|
||||
|
||||
@ -88,24 +88,24 @@ StackWalkAnchor* StackWalkAnchor::from_current(JavaThread* thread, jlong magic,
|
||||
// vfst vFrameStream.
|
||||
// max_nframes Maximum number of frames to be filled.
|
||||
// start_index Start index to the user-supplied buffers.
|
||||
// classes_array Buffer to store classes in, starting at start_index.
|
||||
// frames_array Buffer to store StackFrame in, starting at start_index.
|
||||
// NULL if not used.
|
||||
// frames_array Buffer to store Class or StackFrame in, starting at start_index.
|
||||
// frames array is a Class<?>[] array when only getting caller
|
||||
// reference, and a StackFrameInfo[] array (or derivative)
|
||||
// otherwise. It should never be null.
|
||||
// end_index End index to the user-supplied buffers with unpacked frames.
|
||||
//
|
||||
// Returns the number of frames whose information was transferred into the buffers.
|
||||
//
|
||||
int StackWalk::fill_in_frames(jlong mode, vframeStream& vfst,
|
||||
int max_nframes, int start_index,
|
||||
objArrayHandle classes_array,
|
||||
objArrayHandle frames_array,
|
||||
int& end_index, TRAPS) {
|
||||
if (TraceStackWalk) {
|
||||
tty->print_cr("fill_in_frames limit=%d start=%d frames length=%d",
|
||||
max_nframes, start_index, classes_array->length());
|
||||
max_nframes, start_index, frames_array->length());
|
||||
}
|
||||
assert(max_nframes > 0, "invalid max_nframes");
|
||||
assert(start_index + max_nframes <= classes_array->length(), "oob");
|
||||
assert(start_index + max_nframes <= frames_array->length(), "oob");
|
||||
|
||||
int frames_decoded = 0;
|
||||
for (; !vfst.at_end(); vfst.next()) {
|
||||
@ -129,14 +129,18 @@ int StackWalk::fill_in_frames(jlong mode, vframeStream& vfst,
|
||||
tty->print_cr(" bci=%d", bci);
|
||||
}
|
||||
|
||||
classes_array->obj_at_put(index, method->method_holder()->java_mirror());
|
||||
// fill in StackFrameInfo and initialize MemberName
|
||||
if (live_frame_info(mode)) {
|
||||
assert (use_frames_array(mode), "Bad mode for get live frame");
|
||||
Handle stackFrame(frames_array->obj_at(index));
|
||||
fill_live_stackframe(stackFrame, method, bci, vfst.java_frame(), CHECK_0);
|
||||
} else if (need_method_info(mode)) {
|
||||
assert (use_frames_array(mode), "Bad mode for get stack frame");
|
||||
Handle stackFrame(frames_array->obj_at(index));
|
||||
fill_stackframe(stackFrame, method, bci);
|
||||
} else {
|
||||
assert (use_frames_array(mode) == false, "Bad mode for get caller class");
|
||||
frames_array->obj_at_put(index, method->method_holder()->java_mirror());
|
||||
}
|
||||
if (++frames_decoded >= max_nframes) break;
|
||||
}
|
||||
@ -279,15 +283,15 @@ void StackWalk::fill_live_stackframe(Handle stackFrame, const methodHandle& meth
|
||||
// skip_frames Number of frames to be skipped.
|
||||
// frame_count Number of frames to be traversed.
|
||||
// start_index Start index to the user-supplied buffers.
|
||||
// classes_array Buffer to store classes in, starting at start_index.
|
||||
// frames_array Buffer to store StackFrame in, starting at start_index.
|
||||
// NULL if not used.
|
||||
// frames array is a Class<?>[] array when only getting caller
|
||||
// reference, and a StackFrameInfo[] array (or derivative)
|
||||
// otherwise. It should never be null.
|
||||
//
|
||||
// Returns Object returned from AbstractStackWalker::doStackWalk call.
|
||||
//
|
||||
oop StackWalk::walk(Handle stackStream, jlong mode,
|
||||
int skip_frames, int frame_count, int start_index,
|
||||
objArrayHandle classes_array,
|
||||
objArrayHandle frames_array,
|
||||
TRAPS) {
|
||||
JavaThread* jt = (JavaThread*)THREAD;
|
||||
@ -296,10 +300,8 @@ oop StackWalk::walk(Handle stackStream, jlong mode,
|
||||
mode, skip_frames, frame_count);
|
||||
}
|
||||
|
||||
if (need_method_info(mode)) {
|
||||
if (frames_array.is_null()) {
|
||||
THROW_MSG_(vmSymbols::java_lang_NullPointerException(), "frames_array is NULL", NULL);
|
||||
}
|
||||
if (frames_array.is_null()) {
|
||||
THROW_MSG_(vmSymbols::java_lang_NullPointerException(), "frames_array is NULL", NULL);
|
||||
}
|
||||
|
||||
Klass* stackWalker_klass = SystemDictionary::StackWalker_klass();
|
||||
@ -313,48 +315,17 @@ oop StackWalk::walk(Handle stackStream, jlong mode,
|
||||
vframeStream& vfst = anchor.vframe_stream();
|
||||
|
||||
{
|
||||
// Skip all methods from AbstractStackWalker and StackWalk (enclosing method)
|
||||
if (!fill_in_stacktrace(mode)) {
|
||||
while (!vfst.at_end()) {
|
||||
InstanceKlass* ik = vfst.method()->method_holder();
|
||||
if (ik != stackWalker_klass &&
|
||||
ik != abstractStackWalker_klass && ik->super() != abstractStackWalker_klass) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (TraceStackWalk) {
|
||||
tty->print(" skip "); vfst.method()->print_short_name(); tty->print("\n");
|
||||
}
|
||||
vfst.next();
|
||||
while (!vfst.at_end()) {
|
||||
InstanceKlass* ik = vfst.method()->method_holder();
|
||||
if (ik != stackWalker_klass &&
|
||||
ik != abstractStackWalker_klass && ik->super() != abstractStackWalker_klass) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// For exceptions, skip Throwable::fillInStackTrace and <init> methods
|
||||
// of the exception class and superclasses
|
||||
if (fill_in_stacktrace(mode)) {
|
||||
bool skip_to_fillInStackTrace = false;
|
||||
bool skip_throwableInit_check = false;
|
||||
while (!vfst.at_end() && !skip_throwableInit_check) {
|
||||
InstanceKlass* ik = vfst.method()->method_holder();
|
||||
Method* method = vfst.method();
|
||||
if (!skip_to_fillInStackTrace) {
|
||||
if (ik == SystemDictionary::Throwable_klass() &&
|
||||
method->name() == vmSymbols::fillInStackTrace_name()) {
|
||||
// this frame will be skipped
|
||||
skip_to_fillInStackTrace = true;
|
||||
}
|
||||
} else if (!(ik->is_subclass_of(SystemDictionary::Throwable_klass()) &&
|
||||
method->name() == vmSymbols::object_initializer_name())) {
|
||||
// there are none or we've seen them all - either way stop checking
|
||||
skip_throwableInit_check = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (TraceStackWalk) {
|
||||
tty->print("stack walk: skip "); vfst.method()->print_short_name(); tty->print("\n");
|
||||
}
|
||||
vfst.next();
|
||||
if (TraceStackWalk) {
|
||||
tty->print(" skip "); vfst.method()->print_short_name(); tty->print("\n");
|
||||
}
|
||||
vfst.next();
|
||||
}
|
||||
|
||||
// stack frame has been traversed individually and resume stack walk
|
||||
@ -372,7 +343,7 @@ oop StackWalk::walk(Handle stackStream, jlong mode,
|
||||
int end_index = start_index;
|
||||
int numFrames = 0;
|
||||
if (!vfst.at_end()) {
|
||||
numFrames = fill_in_frames(mode, vfst, frame_count, start_index, classes_array,
|
||||
numFrames = fill_in_frames(mode, vfst, frame_count, start_index,
|
||||
frames_array, end_index, CHECK_NULL);
|
||||
if (numFrames < 1) {
|
||||
THROW_MSG_(vmSymbols::java_lang_InternalError(), "stack walk: decode failed", NULL);
|
||||
@ -392,12 +363,12 @@ oop StackWalk::walk(Handle stackStream, jlong mode,
|
||||
args.push_int(end_index);
|
||||
|
||||
// Link the thread and vframe stream into the callee-visible object
|
||||
anchor.setup_magic_on_entry(classes_array);
|
||||
anchor.setup_magic_on_entry(frames_array);
|
||||
|
||||
JavaCalls::call(&result, m_doStackWalk, &args, THREAD);
|
||||
|
||||
// Do this before anything else happens, to disable any lingering stream objects
|
||||
bool ok = anchor.cleanup_magic_on_exit(classes_array);
|
||||
bool ok = anchor.cleanup_magic_on_exit(frames_array);
|
||||
|
||||
// Throw pending exception if we must
|
||||
(void) (CHECK_NULL);
|
||||
@ -419,31 +390,28 @@ oop StackWalk::walk(Handle stackStream, jlong mode,
|
||||
// magic Must be valid value to continue the stack walk
|
||||
// frame_count Number of frames to be decoded.
|
||||
// start_index Start index to the user-supplied buffers.
|
||||
// classes_array Buffer to store classes in, starting at start_index.
|
||||
// frames_array Buffer to store StackFrame in, starting at start_index.
|
||||
// NULL if not used.
|
||||
//
|
||||
// Returns the end index of frame filled in the buffer.
|
||||
//
|
||||
jint StackWalk::moreFrames(Handle stackStream, jlong mode, jlong magic,
|
||||
int frame_count, int start_index,
|
||||
objArrayHandle classes_array,
|
||||
objArrayHandle frames_array,
|
||||
TRAPS)
|
||||
{
|
||||
JavaThread* jt = (JavaThread*)THREAD;
|
||||
StackWalkAnchor* existing_anchor = StackWalkAnchor::from_current(jt, magic, classes_array);
|
||||
StackWalkAnchor* existing_anchor = StackWalkAnchor::from_current(jt, magic, frames_array);
|
||||
if (existing_anchor == NULL) {
|
||||
THROW_MSG_(vmSymbols::java_lang_InternalError(), "doStackWalk: corrupted buffers", 0L);
|
||||
}
|
||||
|
||||
if ((need_method_info(mode) || live_frame_info(mode)) && frames_array.is_null()) {
|
||||
if (frames_array.is_null()) {
|
||||
THROW_MSG_(vmSymbols::java_lang_NullPointerException(), "frames_array is NULL", 0L);
|
||||
}
|
||||
|
||||
if (TraceStackWalk) {
|
||||
tty->print_cr("StackWalk::moreFrames frame_count %d existing_anchor " PTR_FORMAT " start %d frames %d",
|
||||
frame_count, p2i(existing_anchor), start_index, classes_array->length());
|
||||
frame_count, p2i(existing_anchor), start_index, frames_array->length());
|
||||
}
|
||||
int end_index = start_index;
|
||||
if (frame_count <= 0) {
|
||||
@ -451,14 +419,14 @@ jint StackWalk::moreFrames(Handle stackStream, jlong mode, jlong magic,
|
||||
}
|
||||
|
||||
int count = frame_count + start_index;
|
||||
assert (classes_array->length() >= count, "not enough space in buffers");
|
||||
assert (frames_array->length() >= count, "not enough space in buffers");
|
||||
|
||||
StackWalkAnchor& anchor = (*existing_anchor);
|
||||
vframeStream& vfst = anchor.vframe_stream();
|
||||
if (!vfst.at_end()) {
|
||||
vfst.next(); // this was the last frame decoded in the previous batch
|
||||
if (!vfst.at_end()) {
|
||||
int n = fill_in_frames(mode, vfst, frame_count, start_index, classes_array,
|
||||
int n = fill_in_frames(mode, vfst, frame_count, start_index,
|
||||
frames_array, end_index, CHECK_0);
|
||||
if (n < 1) {
|
||||
THROW_MSG_(vmSymbols::java_lang_InternalError(), "doStackWalk: later decode failed", 0L);
|
||||
|
@ -45,12 +45,12 @@ public:
|
||||
vframeStream& vframe_stream() { return _vfst; }
|
||||
JavaThread* thread() { return _thread; }
|
||||
|
||||
void setup_magic_on_entry(objArrayHandle classes_array);
|
||||
bool check_magic(objArrayHandle classes_array);
|
||||
bool cleanup_magic_on_exit(objArrayHandle classes_array);
|
||||
void setup_magic_on_entry(objArrayHandle frames_array);
|
||||
bool check_magic(objArrayHandle frames_array);
|
||||
bool cleanup_magic_on_exit(objArrayHandle frames_array);
|
||||
|
||||
bool is_valid_in(Thread* thread, objArrayHandle classes_array) {
|
||||
return (_thread == thread && check_magic(classes_array));
|
||||
bool is_valid_in(Thread* thread, objArrayHandle frames_array) {
|
||||
return (_thread == thread && check_magic(frames_array));
|
||||
}
|
||||
|
||||
jlong address_value() {
|
||||
@ -64,7 +64,6 @@ class StackWalk : public AllStatic {
|
||||
private:
|
||||
static int fill_in_frames(jlong mode, vframeStream& vfst,
|
||||
int max_nframes, int start_index,
|
||||
objArrayHandle classes_array,
|
||||
objArrayHandle frames_array,
|
||||
int& end_index, TRAPS);
|
||||
|
||||
@ -82,20 +81,18 @@ private:
|
||||
static inline bool live_frame_info(int mode) {
|
||||
return (mode & JVM_STACKWALK_FILL_LIVE_STACK_FRAMES) != 0;
|
||||
}
|
||||
static inline bool fill_in_stacktrace(int mode) {
|
||||
return (mode & JVM_STACKWALK_FILTER_FILL_IN_STACK_TRACE) != 0;
|
||||
}
|
||||
|
||||
public:
|
||||
static inline bool use_frames_array(int mode) {
|
||||
return (mode & JVM_STACKWALK_FILL_CLASS_REFS_ONLY) == 0;
|
||||
}
|
||||
static oop walk(Handle stackStream, jlong mode,
|
||||
int skip_frames, int frame_count, int start_index,
|
||||
objArrayHandle classes_array,
|
||||
objArrayHandle frames_array,
|
||||
TRAPS);
|
||||
|
||||
static jint moreFrames(Handle stackStream, jlong mode, jlong magic,
|
||||
int frame_count, int start_index,
|
||||
objArrayHandle classes_array,
|
||||
objArrayHandle frames_array,
|
||||
TRAPS);
|
||||
};
|
||||
|
@ -2958,9 +2958,6 @@ public:
|
||||
develop(bool, TraceStackWalk, false, \
|
||||
"Trace stack walking") \
|
||||
\
|
||||
product(bool, MemberNameInStackFrame, true, \
|
||||
"Use MemberName in StackFrame") \
|
||||
\
|
||||
/* notice: the max range value here is max_jint, not max_intx */ \
|
||||
/* because of overflow issue */ \
|
||||
NOT_EMBEDDED(diagnostic(intx, GuaranteedSafepointInterval, 1000, \
|
||||
|
Loading…
Reference in New Issue
Block a user