Skip to content

Commit 111ecdb

Browse files
author
Mandy Chung
committed
8268829: Provide an optimized way to walk the stack with Class object only
8210375: StackWalker::getCallerClass throws UnsupportedOperationException Reviewed-by: coleenp, dfuchs, bchristi
1 parent 716201c commit 111ecdb

File tree

34 files changed

+981
-621
lines changed

34 files changed

+981
-621
lines changed

make/data/hotspot-symbols/symbols-unix

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ JVM_DumpAllStacks
5757
JVM_DumpClassListToFile
5858
JVM_DumpDynamicArchive
5959
JVM_DumpThreads
60+
JVM_ExpandStackFrameInfo
6061
JVM_FillInStackTrace
6162
JVM_FindClassFromCaller
6263
JVM_FindClassFromClass

src/hotspot/share/classfile/javaClasses.cpp

Lines changed: 109 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -2956,15 +2956,78 @@ void java_lang_StackTraceElement::decode(const methodHandle& method, int bci,
29562956
}
29572957
#endif // INCLUDE_JVMCI
29582958

2959+
// java_lang_ClassFrameInfo
2960+
2961+
int java_lang_ClassFrameInfo::_classOrMemberName_offset;
2962+
int java_lang_ClassFrameInfo::_flags_offset;
2963+
2964+
#define CLASSFRAMEINFO_FIELDS_DO(macro) \
2965+
macro(_classOrMemberName_offset, k, "classOrMemberName", object_signature, false); \
2966+
macro(_flags_offset, k, vmSymbols::flags_name(), int_signature, false)
2967+
2968+
void java_lang_ClassFrameInfo::compute_offsets() {
2969+
InstanceKlass* k = vmClasses::ClassFrameInfo_klass();
2970+
CLASSFRAMEINFO_FIELDS_DO(FIELD_COMPUTE_OFFSET);
2971+
}
2972+
2973+
#if INCLUDE_CDS
2974+
void java_lang_ClassFrameInfo::serialize_offsets(SerializeClosure* f) {
2975+
CLASSFRAMEINFO_FIELDS_DO(FIELD_SERIALIZE_OFFSET);
2976+
}
2977+
#endif
2978+
2979+
static int get_flags(const methodHandle& m) {
2980+
int flags = (jushort)( m->access_flags().as_short() & JVM_RECOGNIZED_METHOD_MODIFIERS );
2981+
if (m->is_initializer()) {
2982+
flags |= java_lang_invoke_MemberName::MN_IS_CONSTRUCTOR;
2983+
} else {
2984+
flags |= java_lang_invoke_MemberName::MN_IS_METHOD;
2985+
}
2986+
if (m->caller_sensitive()) {
2987+
flags |= java_lang_invoke_MemberName::MN_CALLER_SENSITIVE;
2988+
}
2989+
if (m->is_hidden()) {
2990+
flags |= java_lang_invoke_MemberName::MN_HIDDEN_MEMBER;
2991+
}
2992+
assert((flags & 0xFF000000) == 0, "unexpected flags");
2993+
return flags;
2994+
}
2995+
2996+
oop java_lang_ClassFrameInfo::classOrMemberName(oop obj) {
2997+
return obj->obj_field(_classOrMemberName_offset);
2998+
}
2999+
3000+
int java_lang_ClassFrameInfo::flags(oop obj) {
3001+
return obj->int_field(_flags_offset);
3002+
}
3003+
3004+
void java_lang_ClassFrameInfo::init_class(Handle stackFrame, const methodHandle& m) {
3005+
stackFrame->obj_field_put(_classOrMemberName_offset, m->method_holder()->java_mirror());
3006+
// flags is initialized when ClassFrameInfo object is constructed and retain the value
3007+
int flags = java_lang_ClassFrameInfo::flags(stackFrame()) | get_flags(m);
3008+
stackFrame->int_field_put(_flags_offset, flags);
3009+
}
3010+
3011+
void java_lang_ClassFrameInfo::init_method(Handle stackFrame, const methodHandle& m, TRAPS) {
3012+
oop rmethod_name = java_lang_invoke_ResolvedMethodName::find_resolved_method(m, CHECK);
3013+
stackFrame->obj_field_put(_classOrMemberName_offset, rmethod_name);
3014+
// flags is initialized when ClassFrameInfo object is constructed and retain the value
3015+
int flags = java_lang_ClassFrameInfo::flags(stackFrame()) | get_flags(m);
3016+
stackFrame->int_field_put(_flags_offset, flags);
3017+
}
3018+
3019+
29593020
// java_lang_StackFrameInfo
29603021

2961-
int java_lang_StackFrameInfo::_memberName_offset;
3022+
int java_lang_StackFrameInfo::_type_offset;
3023+
int java_lang_StackFrameInfo::_name_offset;
29623024
int java_lang_StackFrameInfo::_bci_offset;
29633025
int java_lang_StackFrameInfo::_version_offset;
29643026
int java_lang_StackFrameInfo::_contScope_offset;
29653027

29663028
#define STACKFRAMEINFO_FIELDS_DO(macro) \
2967-
macro(_memberName_offset, k, "memberName", object_signature, false); \
3029+
macro(_type_offset, k, "type", object_signature, false); \
3030+
macro(_name_offset, k, "name", string_signature, false); \
29683031
macro(_bci_offset, k, "bci", int_signature, false); \
29693032
macro(_contScope_offset, k, "contScope", continuationscope_signature, false)
29703033

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

2984-
Method* java_lang_StackFrameInfo::get_method(Handle stackFrame, InstanceKlass* holder, TRAPS) {
2985-
HandleMark hm(THREAD);
2986-
Handle mname(THREAD, stackFrame->obj_field(_memberName_offset));
2987-
Method* method = (Method*)java_lang_invoke_MemberName::vmtarget(mname());
2988-
// we should expand MemberName::name when Throwable uses StackTrace
2989-
// MethodHandles::expand_MemberName(mname, MethodHandles::_suppress_defc|MethodHandles::_suppress_type, CHECK_NULL);
3047+
Method* java_lang_StackFrameInfo::get_method(oop obj) {
3048+
oop m = java_lang_ClassFrameInfo::classOrMemberName(obj);
3049+
Method* method = java_lang_invoke_ResolvedMethodName::vmtarget(m);
29903050
return method;
29913051
}
29923052

29933053
void java_lang_StackFrameInfo::set_method_and_bci(Handle stackFrame, const methodHandle& method, int bci, oop cont, TRAPS) {
29943054
// set Method* or mid/cpref
29953055
HandleMark hm(THREAD);
2996-
Handle mname(THREAD, stackFrame->obj_field(_memberName_offset));
2997-
Handle cont_h (THREAD, cont);
2998-
InstanceKlass* ik = method->method_holder();
2999-
CallInfo info(method(), ik, CHECK);
3000-
MethodHandles::init_method_MemberName(mname, info);
3056+
Handle cont_h(THREAD, cont);
3057+
java_lang_ClassFrameInfo::init_method(stackFrame, method, CHECK);
3058+
30013059
// set bci
30023060
java_lang_StackFrameInfo::set_bci(stackFrame(), bci);
30033061
// method may be redefined; store the version
@@ -3012,28 +3070,42 @@ void java_lang_StackFrameInfo::set_method_and_bci(Handle stackFrame, const metho
30123070
void java_lang_StackFrameInfo::to_stack_trace_element(Handle stackFrame, Handle stack_trace_element, TRAPS) {
30133071
ResourceMark rm(THREAD);
30143072
HandleMark hm(THREAD);
3015-
Handle mname(THREAD, stackFrame->obj_field(java_lang_StackFrameInfo::_memberName_offset));
3016-
Klass* clazz = java_lang_Class::as_Klass(java_lang_invoke_MemberName::clazz(mname()));
3017-
InstanceKlass* holder = InstanceKlass::cast(clazz);
3018-
Method* method = java_lang_StackFrameInfo::get_method(stackFrame, holder, CHECK);
30193073

3074+
Method* method = java_lang_StackFrameInfo::get_method(stackFrame());
3075+
InstanceKlass* holder = method->method_holder();
30203076
short version = stackFrame->short_field(_version_offset);
30213077
int bci = stackFrame->int_field(_bci_offset);
30223078
Symbol* name = method->name();
30233079
java_lang_StackTraceElement::fill_in(stack_trace_element, holder, methodHandle(THREAD, method), version, bci, name, CHECK);
30243080
}
30253081

3026-
void java_lang_StackFrameInfo::set_version(oop element, short value) {
3027-
element->short_field_put(_version_offset, value);
3082+
oop java_lang_StackFrameInfo::type(oop obj) {
3083+
return obj->obj_field(_type_offset);
30283084
}
30293085

3030-
void java_lang_StackFrameInfo::set_bci(oop element, int value) {
3086+
void java_lang_StackFrameInfo::set_type(oop obj, oop value) {
3087+
obj->obj_field_put(_type_offset, value);
3088+
}
3089+
3090+
oop java_lang_StackFrameInfo::name(oop obj) {
3091+
return obj->obj_field(_name_offset);
3092+
}
3093+
3094+
void java_lang_StackFrameInfo::set_name(oop obj, oop value) {
3095+
obj->obj_field_put(_name_offset, value);
3096+
}
3097+
3098+
void java_lang_StackFrameInfo::set_version(oop obj, short value) {
3099+
obj->short_field_put(_version_offset, value);
3100+
}
3101+
3102+
void java_lang_StackFrameInfo::set_bci(oop obj, int value) {
30313103
assert(value >= 0 && value < max_jushort, "must be a valid bci value");
3032-
element->int_field_put(_bci_offset, value);
3104+
obj->int_field_put(_bci_offset, value);
30333105
}
30343106

3035-
void java_lang_StackFrameInfo::set_contScope(oop element, oop value) {
3036-
element->obj_field_put(_contScope_offset, value);
3107+
void java_lang_StackFrameInfo::set_contScope(oop obj, oop value) {
3108+
obj->obj_field_put(_contScope_offset, value);
30373109
}
30383110

30393111
int java_lang_LiveStackFrameInfo::_monitors_offset;
@@ -3058,20 +3130,20 @@ void java_lang_LiveStackFrameInfo::serialize_offsets(SerializeClosure* f) {
30583130
}
30593131
#endif
30603132

3061-
void java_lang_LiveStackFrameInfo::set_monitors(oop element, oop value) {
3062-
element->obj_field_put(_monitors_offset, value);
3133+
void java_lang_LiveStackFrameInfo::set_monitors(oop obj, oop value) {
3134+
obj->obj_field_put(_monitors_offset, value);
30633135
}
30643136

3065-
void java_lang_LiveStackFrameInfo::set_locals(oop element, oop value) {
3066-
element->obj_field_put(_locals_offset, value);
3137+
void java_lang_LiveStackFrameInfo::set_locals(oop obj, oop value) {
3138+
obj->obj_field_put(_locals_offset, value);
30673139
}
30683140

3069-
void java_lang_LiveStackFrameInfo::set_operands(oop element, oop value) {
3070-
element->obj_field_put(_operands_offset, value);
3141+
void java_lang_LiveStackFrameInfo::set_operands(oop obj, oop value) {
3142+
obj->obj_field_put(_operands_offset, value);
30713143
}
30723144

3073-
void java_lang_LiveStackFrameInfo::set_mode(oop element, int value) {
3074-
element->int_field_put(_mode_offset, value);
3145+
void java_lang_LiveStackFrameInfo::set_mode(oop obj, int value) {
3146+
obj->int_field_put(_mode_offset, value);
30753147
}
30763148

30773149

@@ -3947,14 +4019,19 @@ void java_lang_invoke_MemberName::serialize_offsets(SerializeClosure* f) {
39474019
}
39484020
#endif
39494021

4022+
#define RESOLVEDMETHOD_FIELDS_DO(macro) \
4023+
macro(_vmholder_offset, k, "vmholder", class_signature, false)
4024+
39504025
void java_lang_invoke_ResolvedMethodName::compute_offsets() {
39514026
InstanceKlass* k = vmClasses::ResolvedMethodName_klass();
39524027
assert(k != nullptr, "jdk mismatch");
4028+
RESOLVEDMETHOD_FIELDS_DO(FIELD_COMPUTE_OFFSET);
39534029
RESOLVEDMETHOD_INJECTED_FIELDS(INJECTED_FIELD_COMPUTE_OFFSET);
39544030
}
39554031

39564032
#if INCLUDE_CDS
39574033
void java_lang_invoke_ResolvedMethodName::serialize_offsets(SerializeClosure* f) {
4034+
RESOLVEDMETHOD_FIELDS_DO(FIELD_SERIALIZE_OFFSET);
39584035
RESOLVEDMETHOD_INJECTED_FIELDS(INJECTED_FIELD_SERIALIZE_OFFSET);
39594036
}
39604037
#endif
@@ -5217,6 +5294,7 @@ void java_lang_InternalError::serialize_offsets(SerializeClosure* f) {
52175294
f(java_lang_reflect_Parameter) \
52185295
f(java_lang_Module) \
52195296
f(java_lang_StackTraceElement) \
5297+
f(java_lang_ClassFrameInfo) \
52205298
f(java_lang_StackFrameInfo) \
52215299
f(java_lang_LiveStackFrameInfo) \
52225300
f(jdk_internal_vm_ContinuationScope) \

src/hotspot/share/classfile/javaClasses.hpp

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1199,7 +1199,6 @@ class jdk_internal_foreign_abi_CallConv: AllStatic {
11991199
// (These are a private interface for Java code to query the class hierarchy.)
12001200

12011201
#define RESOLVEDMETHOD_INJECTED_FIELDS(macro) \
1202-
macro(java_lang_invoke_ResolvedMethodName, vmholder, object_signature, false) \
12031202
macro(java_lang_invoke_ResolvedMethodName, vmtarget, intptr_signature, false)
12041203

12051204
class java_lang_invoke_ResolvedMethodName : AllStatic {
@@ -1288,6 +1287,7 @@ class java_lang_invoke_MemberName: AllStatic {
12881287
MN_IS_TYPE = 0x00080000, // nested type
12891288
MN_CALLER_SENSITIVE = 0x00100000, // @CallerSensitive annotation detected
12901289
MN_TRUSTED_FINAL = 0x00200000, // trusted final field
1290+
MN_HIDDEN_MEMBER = 0x00400000, // @Hidden annotation detected
12911291
MN_REFERENCE_KIND_SHIFT = 24, // refKind
12921292
MN_REFERENCE_KIND_MASK = 0x0F000000 >> MN_REFERENCE_KIND_SHIFT,
12931293
MN_NESTMATE_CLASS = 0x00000001,
@@ -1591,23 +1591,49 @@ class Backtrace: AllStatic {
15911591
friend class JavaClasses;
15921592
};
15931593

1594+
class java_lang_ClassFrameInfo: AllStatic {
1595+
private:
1596+
static int _classOrMemberName_offset;
1597+
static int _flags_offset;
1598+
1599+
public:
1600+
static oop classOrMemberName(oop info);
1601+
static int flags(oop info);
1602+
1603+
// Setters
1604+
static void init_class(Handle stackFrame, const methodHandle& m);
1605+
static void init_method(Handle stackFrame, const methodHandle& m, TRAPS);
1606+
1607+
static void compute_offsets();
1608+
static void serialize_offsets(SerializeClosure* f) NOT_CDS_RETURN;
1609+
1610+
// Debugging
1611+
friend class JavaClasses;
1612+
};
1613+
15941614
// Interface to java.lang.StackFrameInfo objects
15951615

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

15991619
class java_lang_StackFrameInfo: AllStatic {
16001620
private:
1601-
static int _memberName_offset;
1621+
static int _type_offset;
1622+
static int _name_offset;
16021623
static int _bci_offset;
16031624
static int _version_offset;
16041625
static int _contScope_offset;
16051626

1606-
static Method* get_method(Handle stackFrame, InstanceKlass* holder, TRAPS);
1607-
16081627
public:
1628+
// Getters
1629+
static oop name(oop info);
1630+
static oop type(oop info);
1631+
static Method* get_method(oop info);
1632+
16091633
// Setters
16101634
static void set_method_and_bci(Handle stackFrame, const methodHandle& method, int bci, oop cont, TRAPS);
1635+
static void set_name(oop info, oop value);
1636+
static void set_type(oop info, oop value);
16111637
static void set_bci(oop info, int value);
16121638

16131639
static void set_version(oop info, short value);

src/hotspot/share/classfile/vmClassMacros.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,7 @@
160160
/* Stack Walking */ \
161161
do_klass(StackWalker_klass, java_lang_StackWalker ) \
162162
do_klass(AbstractStackWalker_klass, java_lang_StackStreamFactory_AbstractStackWalker ) \
163+
do_klass(ClassFrameInfo_klass, java_lang_ClassFrameInfo ) \
163164
do_klass(StackFrameInfo_klass, java_lang_StackFrameInfo ) \
164165
do_klass(LiveStackFrameInfo_klass, java_lang_LiveStackFrameInfo ) \
165166
\

src/hotspot/share/classfile/vmSymbols.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,7 @@ class SerializeClosure;
378378
/* Support for JVMCI */ \
379379
JVMCI_VM_SYMBOLS_DO(template, do_alias) \
380380
\
381+
template(java_lang_ClassFrameInfo, "java/lang/ClassFrameInfo") \
381382
template(java_lang_StackWalker, "java/lang/StackWalker") \
382383
template(java_lang_StackFrameInfo, "java/lang/StackFrameInfo") \
383384
template(java_lang_LiveStackFrameInfo, "java/lang/LiveStackFrameInfo") \

src/hotspot/share/include/jvm.h

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -244,19 +244,21 @@ JVM_GetExtendedNPEMessage(JNIEnv *env, jthrowable throwable);
244244
* java.lang.StackWalker
245245
*/
246246
enum {
247-
JVM_STACKWALK_FILL_CLASS_REFS_ONLY = 0x2,
248-
JVM_STACKWALK_GET_CALLER_CLASS = 0x04,
247+
JVM_STACKWALK_CLASS_INFO_ONLY = 0x2,
249248
JVM_STACKWALK_SHOW_HIDDEN_FRAMES = 0x20,
250249
JVM_STACKWALK_FILL_LIVE_STACK_FRAMES = 0x100
251250
};
252251

252+
JNIEXPORT void JNICALL
253+
JVM_ExpandStackFrameInfo(JNIEnv *env, jobject obj);
254+
253255
JNIEXPORT jobject JNICALL
254-
JVM_CallStackWalk(JNIEnv *env, jobject stackStream, jlong mode,
256+
JVM_CallStackWalk(JNIEnv *env, jobject stackStream, jint mode,
255257
jint skip_frames, jobject contScope, jobject cont,
256258
jint frame_count, jint start_index, jobjectArray frames);
257259

258260
JNIEXPORT jint JNICALL
259-
JVM_MoreStackWalk(JNIEnv *env, jobject stackStream, jlong mode, jlong anchor,
261+
JVM_MoreStackWalk(JNIEnv *env, jobject stackStream, jint mode, jlong anchor,
260262
jint frame_count, jint start_index,
261263
jobjectArray frames);
262264

src/hotspot/share/prims/jvm.cpp

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -542,14 +542,28 @@ JVM_END
542542
JVM_ENTRY(void, JVM_InitStackTraceElement(JNIEnv* env, jobject element, jobject stackFrameInfo))
543543
Handle stack_frame_info(THREAD, JNIHandles::resolve_non_null(stackFrameInfo));
544544
Handle stack_trace_element(THREAD, JNIHandles::resolve_non_null(element));
545-
java_lang_StackFrameInfo::to_stack_trace_element(stack_frame_info, stack_trace_element, THREAD);
545+
java_lang_StackFrameInfo::to_stack_trace_element(stack_frame_info, stack_trace_element, CHECK);
546546
JVM_END
547547

548548

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

553+
bool have_name = (java_lang_StackFrameInfo::name(stack_frame_info()) != nullptr);
554+
bool have_type = (java_lang_StackFrameInfo::type(stack_frame_info()) != nullptr);
555+
Method* method = java_lang_StackFrameInfo::get_method(stack_frame_info());
556+
if (!have_name) {
557+
oop name = StringTable::intern(method->name(), CHECK);
558+
java_lang_StackFrameInfo::set_name(stack_frame_info(), name);
559+
}
560+
if (!have_type) {
561+
Handle type = java_lang_String::create_from_symbol(method->signature(), CHECK);
562+
java_lang_StackFrameInfo::set_type(stack_frame_info(), type());
563+
}
564+
JVM_END
551565

552-
JVM_ENTRY(jobject, JVM_CallStackWalk(JNIEnv *env, jobject stackStream, jlong mode,
566+
JVM_ENTRY(jobject, JVM_CallStackWalk(JNIEnv *env, jobject stackStream, jint mode,
553567
jint skip_frames, jobject contScope, jobject cont,
554568
jint frame_count, jint start_index, jobjectArray frames))
555569
if (!thread->has_last_Java_frame()) {
@@ -559,7 +573,7 @@ JVM_ENTRY(jobject, JVM_CallStackWalk(JNIEnv *env, jobject stackStream, jlong mod
559573
Handle stackStream_h(THREAD, JNIHandles::resolve_non_null(stackStream));
560574
Handle contScope_h(THREAD, JNIHandles::resolve(contScope));
561575
Handle cont_h(THREAD, JNIHandles::resolve(cont));
562-
// frames array is a Class<?>[] array when only getting caller reference,
576+
// frames array is a ClassFrameInfo[] array when only getting caller reference,
563577
// and a StackFrameInfo[] array (or derivative) otherwise. It should never
564578
// be null.
565579
objArrayOop fa = objArrayOop(JNIHandles::resolve_non_null(frames));
@@ -576,10 +590,10 @@ JVM_ENTRY(jobject, JVM_CallStackWalk(JNIEnv *env, jobject stackStream, jlong mod
576590
JVM_END
577591

578592

579-
JVM_ENTRY(jint, JVM_MoreStackWalk(JNIEnv *env, jobject stackStream, jlong mode, jlong anchor,
593+
JVM_ENTRY(jint, JVM_MoreStackWalk(JNIEnv *env, jobject stackStream, jint mode, jlong anchor,
580594
jint frame_count, jint start_index,
581595
jobjectArray frames))
582-
// frames array is a Class<?>[] array when only getting caller reference,
596+
// frames array is a ClassFrameInfo[] array when only getting caller reference,
583597
// and a StackFrameInfo[] array (or derivative) otherwise. It should never
584598
// be null.
585599
objArrayOop fa = objArrayOop(JNIHandles::resolve_non_null(frames));

0 commit comments

Comments
 (0)