Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
e3ff41f
StackWalker::walkClass support
mlchung Nov 17, 2022
02e010d
merge
mlchung Aug 1, 2023
94ad294
Merge branch 'master' of https://github.com/openjdk/jdk into stackwal…
mlchung Aug 2, 2023
6f88fea
Merge branch 'master' of https://github.com/openjdk/jdk into stackwal…
mlchung Aug 3, 2023
6c18ae6
Merge branch 'master' of https://github.com/openjdk/jdk into stackwal…
mlchung Aug 3, 2023
83045b6
Merge branch 'master' of https://github.com/openjdk/jdk into stackwal…
mlchung Aug 15, 2023
063bf1b
Merge branch 'master' of https://github.com/openjdk/jdk into stackwal…
mlchung Aug 16, 2023
573d3e2
Add StackWalker.Option.NO_METHOD_INFO
mlchung Aug 18, 2023
24d4f33
Merge branch 'master' of https://github.com/openjdk/jdk into stackwal…
mlchung Aug 18, 2023
aab371f
clean up
mlchung Aug 18, 2023
5d301e1
Update LocalLongHelper.java
mlchung Aug 20, 2023
019f156
Merge branch 'master' of https://github.com/openjdk/jdk into stackwal…
mlchung Aug 21, 2023
e9e2b39
fix trailing whitespace
mlchung Aug 21, 2023
8777555
clean up
mlchung Aug 21, 2023
7ec716c
Merge branch 'master' of https://github.com/openjdk/jdk into stackwal…
mlchung Aug 22, 2023
434d90c
Replace NO_METHOD_INFO option with StackWalker.Kind enums
mlchung Aug 22, 2023
3569000
fixup the factory methods
mlchung Aug 23, 2023
e8743be
move retainClassRef to ClassFrameInfo as a bit set in the flags field
mlchung Aug 23, 2023
3098425
fix whitespace
mlchung Aug 23, 2023
a3a4457
review feedback and javadoc clean up
mlchung Aug 24, 2023
4ef3d95
Review feedback: move JLIA to ClassFrameInfo
mlchung Aug 25, 2023
4c5c5d7
fixup javadoc
mlchung Aug 25, 2023
a0e1a50
Review feedback from Remi
mlchung Aug 28, 2023
3ca53c7
Revised the API change. Add Option::DROP_METHOD_INFO
mlchung Aug 28, 2023
8f93611
Review feedback on javadoc
mlchung Aug 29, 2023
ffc366d
update tests
mlchung Aug 29, 2023
5a48c70
update mode to be int rather than long
mlchung Aug 29, 2023
a50fb2b
Remove the new getInstance method taking varargs
mlchung Aug 31, 2023
111661b
Merge
mlchung Aug 31, 2023
9e881a3
replace href with @linkplain
mlchung Sep 6, 2023
a623b9d
Generify StackFrameInfo to replace duplicated code
mlchung Sep 6, 2023
0e6abc4
review feedback
mlchung Sep 7, 2023
c3746f5
Fix @Param due to the rename from default to class+method
mlchung Sep 7, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions make/data/hotspot-symbols/symbols-unix
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ JVM_DumpAllStacks
JVM_DumpClassListToFile
JVM_DumpDynamicArchive
JVM_DumpThreads
JVM_ExpandStackFrameInfo
JVM_FillInStackTrace
JVM_FindClassFromCaller
JVM_FindClassFromClass
Expand Down
140 changes: 109 additions & 31 deletions src/hotspot/share/classfile/javaClasses.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2956,15 +2956,78 @@ void java_lang_StackTraceElement::decode(const methodHandle& method, int bci,
}
#endif // INCLUDE_JVMCI

// java_lang_ClassFrameInfo

int java_lang_ClassFrameInfo::_classOrMemberName_offset;
int java_lang_ClassFrameInfo::_flags_offset;

#define CLASSFRAMEINFO_FIELDS_DO(macro) \
macro(_classOrMemberName_offset, k, "classOrMemberName", object_signature, false); \
macro(_flags_offset, k, vmSymbols::flags_name(), int_signature, false)

void java_lang_ClassFrameInfo::compute_offsets() {
InstanceKlass* k = vmClasses::ClassFrameInfo_klass();
CLASSFRAMEINFO_FIELDS_DO(FIELD_COMPUTE_OFFSET);
}

#if INCLUDE_CDS
void java_lang_ClassFrameInfo::serialize_offsets(SerializeClosure* f) {
CLASSFRAMEINFO_FIELDS_DO(FIELD_SERIALIZE_OFFSET);
}
#endif

static int get_flags(const methodHandle& m) {
int flags = (jushort)( m->access_flags().as_short() & JVM_RECOGNIZED_METHOD_MODIFIERS );
if (m->is_initializer()) {
flags |= java_lang_invoke_MemberName::MN_IS_CONSTRUCTOR;
} else {
flags |= java_lang_invoke_MemberName::MN_IS_METHOD;
}
if (m->caller_sensitive()) {
flags |= java_lang_invoke_MemberName::MN_CALLER_SENSITIVE;
}
if (m->is_hidden()) {
flags |= java_lang_invoke_MemberName::MN_HIDDEN_MEMBER;
}
assert((flags & 0xFF000000) == 0, "unexpected flags");
return flags;
}

oop java_lang_ClassFrameInfo::classOrMemberName(oop obj) {
return obj->obj_field(_classOrMemberName_offset);
}

int java_lang_ClassFrameInfo::flags(oop obj) {
return obj->int_field(_flags_offset);
}

void java_lang_ClassFrameInfo::init_class(Handle stackFrame, const methodHandle& m) {
stackFrame->obj_field_put(_classOrMemberName_offset, m->method_holder()->java_mirror());
// flags is initialized when ClassFrameInfo object is constructed and retain the value
int flags = java_lang_ClassFrameInfo::flags(stackFrame()) | get_flags(m);
stackFrame->int_field_put(_flags_offset, flags);
}

void java_lang_ClassFrameInfo::init_method(Handle stackFrame, const methodHandle& m, TRAPS) {
oop rmethod_name = java_lang_invoke_ResolvedMethodName::find_resolved_method(m, CHECK);
stackFrame->obj_field_put(_classOrMemberName_offset, rmethod_name);
// flags is initialized when ClassFrameInfo object is constructed and retain the value
int flags = java_lang_ClassFrameInfo::flags(stackFrame()) | get_flags(m);
stackFrame->int_field_put(_flags_offset, flags);
}


// java_lang_StackFrameInfo

int java_lang_StackFrameInfo::_memberName_offset;
int java_lang_StackFrameInfo::_type_offset;
int java_lang_StackFrameInfo::_name_offset;
int java_lang_StackFrameInfo::_bci_offset;
int java_lang_StackFrameInfo::_version_offset;
int java_lang_StackFrameInfo::_contScope_offset;

#define STACKFRAMEINFO_FIELDS_DO(macro) \
macro(_memberName_offset, k, "memberName", object_signature, false); \
macro(_type_offset, k, "type", object_signature, false); \
macro(_name_offset, k, "name", string_signature, false); \
macro(_bci_offset, k, "bci", int_signature, false); \
macro(_contScope_offset, k, "contScope", continuationscope_signature, false)

Expand All @@ -2981,23 +3044,18 @@ void java_lang_StackFrameInfo::serialize_offsets(SerializeClosure* f) {
}
#endif

Method* java_lang_StackFrameInfo::get_method(Handle stackFrame, InstanceKlass* holder, TRAPS) {
HandleMark hm(THREAD);
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);
Method* java_lang_StackFrameInfo::get_method(oop obj) {
oop m = java_lang_ClassFrameInfo::classOrMemberName(obj);
Method* method = java_lang_invoke_ResolvedMethodName::vmtarget(m);
return method;
}

void java_lang_StackFrameInfo::set_method_and_bci(Handle stackFrame, const methodHandle& method, int bci, oop cont, TRAPS) {
// set Method* or mid/cpref
HandleMark hm(THREAD);
Handle mname(THREAD, stackFrame->obj_field(_memberName_offset));
Handle cont_h (THREAD, cont);
InstanceKlass* ik = method->method_holder();
CallInfo info(method(), ik, CHECK);
MethodHandles::init_method_MemberName(mname, info);
Handle cont_h(THREAD, cont);
java_lang_ClassFrameInfo::init_method(stackFrame, method, CHECK);

// set bci
java_lang_StackFrameInfo::set_bci(stackFrame(), bci);
// method may be redefined; store the version
Expand All @@ -3012,28 +3070,42 @@ void java_lang_StackFrameInfo::set_method_and_bci(Handle stackFrame, const metho
void java_lang_StackFrameInfo::to_stack_trace_element(Handle stackFrame, Handle stack_trace_element, TRAPS) {
ResourceMark rm(THREAD);
HandleMark hm(THREAD);
Handle mname(THREAD, stackFrame->obj_field(java_lang_StackFrameInfo::_memberName_offset));
Klass* clazz = java_lang_Class::as_Klass(java_lang_invoke_MemberName::clazz(mname()));
InstanceKlass* holder = InstanceKlass::cast(clazz);
Method* method = java_lang_StackFrameInfo::get_method(stackFrame, holder, CHECK);

Method* method = java_lang_StackFrameInfo::get_method(stackFrame());
InstanceKlass* holder = method->method_holder();
short version = stackFrame->short_field(_version_offset);
int bci = stackFrame->int_field(_bci_offset);
Symbol* name = method->name();
java_lang_StackTraceElement::fill_in(stack_trace_element, holder, methodHandle(THREAD, method), version, bci, name, CHECK);
}

void java_lang_StackFrameInfo::set_version(oop element, short value) {
element->short_field_put(_version_offset, value);
oop java_lang_StackFrameInfo::type(oop obj) {
return obj->obj_field(_type_offset);
}

void java_lang_StackFrameInfo::set_bci(oop element, int value) {
void java_lang_StackFrameInfo::set_type(oop obj, oop value) {
obj->obj_field_put(_type_offset, value);
}

oop java_lang_StackFrameInfo::name(oop obj) {
return obj->obj_field(_name_offset);
}

void java_lang_StackFrameInfo::set_name(oop obj, oop value) {
obj->obj_field_put(_name_offset, value);
}

void java_lang_StackFrameInfo::set_version(oop obj, short value) {
obj->short_field_put(_version_offset, value);
}

void java_lang_StackFrameInfo::set_bci(oop obj, int value) {
assert(value >= 0 && value < max_jushort, "must be a valid bci value");
element->int_field_put(_bci_offset, value);
obj->int_field_put(_bci_offset, value);
}

void java_lang_StackFrameInfo::set_contScope(oop element, oop value) {
element->obj_field_put(_contScope_offset, value);
void java_lang_StackFrameInfo::set_contScope(oop obj, oop value) {
obj->obj_field_put(_contScope_offset, value);
}

int java_lang_LiveStackFrameInfo::_monitors_offset;
Expand All @@ -3058,20 +3130,20 @@ void java_lang_LiveStackFrameInfo::serialize_offsets(SerializeClosure* f) {
}
#endif

void java_lang_LiveStackFrameInfo::set_monitors(oop element, oop value) {
element->obj_field_put(_monitors_offset, value);
void java_lang_LiveStackFrameInfo::set_monitors(oop obj, oop value) {
obj->obj_field_put(_monitors_offset, value);
}

void java_lang_LiveStackFrameInfo::set_locals(oop element, oop value) {
element->obj_field_put(_locals_offset, value);
void java_lang_LiveStackFrameInfo::set_locals(oop obj, oop value) {
obj->obj_field_put(_locals_offset, value);
}

void java_lang_LiveStackFrameInfo::set_operands(oop element, oop value) {
element->obj_field_put(_operands_offset, value);
void java_lang_LiveStackFrameInfo::set_operands(oop obj, oop value) {
obj->obj_field_put(_operands_offset, value);
}

void java_lang_LiveStackFrameInfo::set_mode(oop element, int value) {
element->int_field_put(_mode_offset, value);
void java_lang_LiveStackFrameInfo::set_mode(oop obj, int value) {
obj->int_field_put(_mode_offset, value);
}


Expand Down Expand Up @@ -3947,14 +4019,19 @@ void java_lang_invoke_MemberName::serialize_offsets(SerializeClosure* f) {
}
#endif

#define RESOLVEDMETHOD_FIELDS_DO(macro) \
macro(_vmholder_offset, k, "vmholder", class_signature, false)

void java_lang_invoke_ResolvedMethodName::compute_offsets() {
InstanceKlass* k = vmClasses::ResolvedMethodName_klass();
assert(k != nullptr, "jdk mismatch");
RESOLVEDMETHOD_FIELDS_DO(FIELD_COMPUTE_OFFSET);
RESOLVEDMETHOD_INJECTED_FIELDS(INJECTED_FIELD_COMPUTE_OFFSET);
}

#if INCLUDE_CDS
void java_lang_invoke_ResolvedMethodName::serialize_offsets(SerializeClosure* f) {
RESOLVEDMETHOD_FIELDS_DO(FIELD_SERIALIZE_OFFSET);
RESOLVEDMETHOD_INJECTED_FIELDS(INJECTED_FIELD_SERIALIZE_OFFSET);
}
#endif
Expand Down Expand Up @@ -5217,6 +5294,7 @@ void java_lang_InternalError::serialize_offsets(SerializeClosure* f) {
f(java_lang_reflect_Parameter) \
f(java_lang_Module) \
f(java_lang_StackTraceElement) \
f(java_lang_ClassFrameInfo) \
f(java_lang_StackFrameInfo) \
f(java_lang_LiveStackFrameInfo) \
f(jdk_internal_vm_ContinuationScope) \
Expand Down
34 changes: 30 additions & 4 deletions src/hotspot/share/classfile/javaClasses.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1199,7 +1199,6 @@ class jdk_internal_foreign_abi_CallConv: AllStatic {
// (These are a private interface for Java code to query the class hierarchy.)

#define RESOLVEDMETHOD_INJECTED_FIELDS(macro) \
macro(java_lang_invoke_ResolvedMethodName, vmholder, object_signature, false) \
macro(java_lang_invoke_ResolvedMethodName, vmtarget, intptr_signature, false)

class java_lang_invoke_ResolvedMethodName : AllStatic {
Expand Down Expand Up @@ -1288,6 +1287,7 @@ class java_lang_invoke_MemberName: AllStatic {
MN_IS_TYPE = 0x00080000, // nested type
MN_CALLER_SENSITIVE = 0x00100000, // @CallerSensitive annotation detected
MN_TRUSTED_FINAL = 0x00200000, // trusted final field
MN_HIDDEN_MEMBER = 0x00400000, // @Hidden annotation detected
MN_REFERENCE_KIND_SHIFT = 24, // refKind
MN_REFERENCE_KIND_MASK = 0x0F000000 >> MN_REFERENCE_KIND_SHIFT,
MN_NESTMATE_CLASS = 0x00000001,
Expand Down Expand Up @@ -1591,23 +1591,49 @@ class Backtrace: AllStatic {
friend class JavaClasses;
};

class java_lang_ClassFrameInfo: AllStatic {
private:
static int _classOrMemberName_offset;
static int _flags_offset;

public:
static oop classOrMemberName(oop info);
static int flags(oop info);

// Setters
static void init_class(Handle stackFrame, const methodHandle& m);
static void init_method(Handle stackFrame, const methodHandle& m, TRAPS);

static void compute_offsets();
static void serialize_offsets(SerializeClosure* f) NOT_CDS_RETURN;

// Debugging
friend class JavaClasses;
};

// Interface to java.lang.StackFrameInfo objects

#define STACKFRAMEINFO_INJECTED_FIELDS(macro) \
macro(java_lang_StackFrameInfo, version, short_signature, false)

class java_lang_StackFrameInfo: AllStatic {
private:
static int _memberName_offset;
static int _type_offset;
static int _name_offset;
static int _bci_offset;
static int _version_offset;
static int _contScope_offset;

static Method* get_method(Handle stackFrame, InstanceKlass* holder, TRAPS);

public:
// Getters
static oop name(oop info);
static oop type(oop info);
static Method* get_method(oop info);

// Setters
static void set_method_and_bci(Handle stackFrame, const methodHandle& method, int bci, oop cont, TRAPS);
static void set_name(oop info, oop value);
static void set_type(oop info, oop value);
static void set_bci(oop info, int value);

static void set_version(oop info, short value);
Expand Down
1 change: 1 addition & 0 deletions src/hotspot/share/classfile/vmClassMacros.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@
/* Stack Walking */ \
do_klass(StackWalker_klass, java_lang_StackWalker ) \
do_klass(AbstractStackWalker_klass, java_lang_StackStreamFactory_AbstractStackWalker ) \
do_klass(ClassFrameInfo_klass, java_lang_ClassFrameInfo ) \
do_klass(StackFrameInfo_klass, java_lang_StackFrameInfo ) \
do_klass(LiveStackFrameInfo_klass, java_lang_LiveStackFrameInfo ) \
\
Expand Down
1 change: 1 addition & 0 deletions src/hotspot/share/classfile/vmSymbols.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,7 @@ class SerializeClosure;
/* Support for JVMCI */ \
JVMCI_VM_SYMBOLS_DO(template, do_alias) \
\
template(java_lang_ClassFrameInfo, "java/lang/ClassFrameInfo") \
template(java_lang_StackWalker, "java/lang/StackWalker") \
template(java_lang_StackFrameInfo, "java/lang/StackFrameInfo") \
template(java_lang_LiveStackFrameInfo, "java/lang/LiveStackFrameInfo") \
Expand Down
10 changes: 6 additions & 4 deletions src/hotspot/share/include/jvm.h
Original file line number Diff line number Diff line change
Expand Up @@ -244,19 +244,21 @@ JVM_GetExtendedNPEMessage(JNIEnv *env, jthrowable throwable);
* java.lang.StackWalker
*/
enum {
JVM_STACKWALK_FILL_CLASS_REFS_ONLY = 0x2,
JVM_STACKWALK_GET_CALLER_CLASS = 0x04,
JVM_STACKWALK_CLASS_INFO_ONLY = 0x2,
JVM_STACKWALK_SHOW_HIDDEN_FRAMES = 0x20,
JVM_STACKWALK_FILL_LIVE_STACK_FRAMES = 0x100
};

JNIEXPORT void JNICALL
JVM_ExpandStackFrameInfo(JNIEnv *env, jobject obj);

JNIEXPORT jobject JNICALL
JVM_CallStackWalk(JNIEnv *env, jobject stackStream, jlong mode,
JVM_CallStackWalk(JNIEnv *env, jobject stackStream, jint mode,
jint skip_frames, jobject contScope, jobject cont,
jint frame_count, jint start_index, jobjectArray frames);

JNIEXPORT jint JNICALL
JVM_MoreStackWalk(JNIEnv *env, jobject stackStream, jlong mode, jlong anchor,
JVM_MoreStackWalk(JNIEnv *env, jobject stackStream, jint mode, jlong anchor,
jint frame_count, jint start_index,
jobjectArray frames);

Expand Down
24 changes: 19 additions & 5 deletions src/hotspot/share/prims/jvm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -542,14 +542,28 @@ JVM_END
JVM_ENTRY(void, JVM_InitStackTraceElement(JNIEnv* env, jobject element, jobject stackFrameInfo))
Handle stack_frame_info(THREAD, JNIHandles::resolve_non_null(stackFrameInfo));
Handle stack_trace_element(THREAD, JNIHandles::resolve_non_null(element));
java_lang_StackFrameInfo::to_stack_trace_element(stack_frame_info, stack_trace_element, THREAD);
java_lang_StackFrameInfo::to_stack_trace_element(stack_frame_info, stack_trace_element, CHECK);
JVM_END


// java.lang.StackWalker //////////////////////////////////////////////////////
JVM_ENTRY(void, JVM_ExpandStackFrameInfo(JNIEnv *env, jobject obj))
Handle stack_frame_info(THREAD, JNIHandles::resolve_non_null(obj));

bool have_name = (java_lang_StackFrameInfo::name(stack_frame_info()) != nullptr);
bool have_type = (java_lang_StackFrameInfo::type(stack_frame_info()) != nullptr);
Method* method = java_lang_StackFrameInfo::get_method(stack_frame_info());
if (!have_name) {
oop name = StringTable::intern(method->name(), CHECK);
java_lang_StackFrameInfo::set_name(stack_frame_info(), name);
}
if (!have_type) {
Handle type = java_lang_String::create_from_symbol(method->signature(), CHECK);
java_lang_StackFrameInfo::set_type(stack_frame_info(), type());
}
JVM_END

JVM_ENTRY(jobject, JVM_CallStackWalk(JNIEnv *env, jobject stackStream, jlong mode,
JVM_ENTRY(jobject, JVM_CallStackWalk(JNIEnv *env, jobject stackStream, jint mode,
jint skip_frames, jobject contScope, jobject cont,
jint frame_count, jint start_index, jobjectArray frames))
if (!thread->has_last_Java_frame()) {
Expand All @@ -559,7 +573,7 @@ JVM_ENTRY(jobject, JVM_CallStackWalk(JNIEnv *env, jobject stackStream, jlong mod
Handle stackStream_h(THREAD, JNIHandles::resolve_non_null(stackStream));
Handle contScope_h(THREAD, JNIHandles::resolve(contScope));
Handle cont_h(THREAD, JNIHandles::resolve(cont));
// frames array is a Class<?>[] array when only getting caller reference,
// frames array is a ClassFrameInfo[] 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));
Expand All @@ -576,10 +590,10 @@ JVM_ENTRY(jobject, JVM_CallStackWalk(JNIEnv *env, jobject stackStream, jlong mod
JVM_END


JVM_ENTRY(jint, JVM_MoreStackWalk(JNIEnv *env, jobject stackStream, jlong mode, jlong anchor,
JVM_ENTRY(jint, JVM_MoreStackWalk(JNIEnv *env, jobject stackStream, jint mode, jlong anchor,
jint frame_count, jint start_index,
jobjectArray frames))
// frames array is a Class<?>[] array when only getting caller reference,
// frames array is a ClassFrameInfo[] 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));
Expand Down
Loading