Skip to content

Commit

Permalink
8313421: [JVMCI] avoid locking class loader in CompilerToVM.lookupType
Browse files Browse the repository at this point in the history
Reviewed-by: never, thartmann
  • Loading branch information
Doug Simon committed Aug 10, 2023
1 parent 35b60f9 commit 83adaf5
Show file tree
Hide file tree
Showing 8 changed files with 74 additions and 52 deletions.
15 changes: 10 additions & 5 deletions src/hotspot/share/jvmci/jvmciCompilerToVM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -576,7 +576,7 @@ C2V_VMENTRY_0(jboolean, shouldInlineMethod,(JNIEnv* env, jobject, ARGUMENT_PAIR(
return CompilerOracle::should_inline(method) || method->force_inline();
C2V_END

C2V_VMENTRY_NULL(jobject, lookupType, (JNIEnv* env, jobject, jstring jname, ARGUMENT_PAIR(accessing_klass), jboolean resolve))
C2V_VMENTRY_NULL(jobject, lookupType, (JNIEnv* env, jobject, jstring jname, ARGUMENT_PAIR(accessing_klass), jint accessing_klass_loader, jboolean resolve))
JVMCIObject name = JVMCIENV->wrap(jname);
const char* str = JVMCIENV->as_utf8_string(name);
TempNewSymbol class_name = SymbolTable::new_symbol(str);
Expand All @@ -593,15 +593,20 @@ C2V_VMENTRY_NULL(jobject, lookupType, (JNIEnv* env, jobject, jstring jname, ARGU
class_loader = Handle(THREAD, accessing_klass->class_loader());
protection_domain = Handle(THREAD, accessing_klass->protection_domain());
} else {
// Use the System class loader
class_loader = Handle(THREAD, SystemDictionary::java_system_loader());
switch (accessing_klass_loader) {
case 0: break; // class_loader is already null, the boot loader
case 1: class_loader = Handle(THREAD, SystemDictionary::java_platform_loader()); break;
case 2: class_loader = Handle(THREAD, SystemDictionary::java_system_loader()); break;
default:
JVMCI_THROW_MSG_0(InternalError, err_msg("Illegal class loader value: %d", accessing_klass_loader));
}
JVMCIENV->runtime()->initialize(JVMCI_CHECK_NULL);
}

if (resolve) {
resolved_klass = SystemDictionary::resolve_or_null(class_name, class_loader, protection_domain, CHECK_NULL);
if (resolved_klass == nullptr) {
JVMCI_THROW_MSG_NULL(ClassNotFoundException, str);
JVMCI_THROW_MSG_NULL(NoClassDefFoundError, str);
}
} else {
if (Signature::has_envelope(class_name)) {
Expand Down Expand Up @@ -3108,7 +3113,7 @@ JNINativeMethod CompilerToVM::methods[] = {
{CC "isCompilable", CC "(" HS_METHOD2 ")Z", FN_PTR(isCompilable)},
{CC "hasNeverInlineDirective", CC "(" HS_METHOD2 ")Z", FN_PTR(hasNeverInlineDirective)},
{CC "shouldInlineMethod", CC "(" HS_METHOD2 ")Z", FN_PTR(shouldInlineMethod)},
{CC "lookupType", CC "(" STRING HS_KLASS2 "Z)" HS_RESOLVED_TYPE, FN_PTR(lookupType)},
{CC "lookupType", CC "(" STRING HS_KLASS2 "IZ)" HS_RESOLVED_TYPE, FN_PTR(lookupType)},
{CC "lookupJClass", CC "(J)" HS_RESOLVED_TYPE, FN_PTR(lookupJClass)},
{CC "getArrayType", CC "(C" HS_KLASS2 ")" HS_KLASS, FN_PTR(getArrayType)},
{CC "lookupClass", CC "(" CLASS ")" HS_RESOLVED_TYPE, FN_PTR(lookupClass)},
Expand Down
2 changes: 1 addition & 1 deletion src/hotspot/share/jvmci/jvmciEnv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -864,7 +864,7 @@ DO_THROW(InvalidInstalledCodeException)
DO_THROW(UnsatisfiedLinkError)
DO_THROW(UnsupportedOperationException)
DO_THROW(OutOfMemoryError)
DO_THROW(ClassNotFoundException)
DO_THROW(NoClassDefFoundError)

#undef DO_THROW

Expand Down
2 changes: 1 addition & 1 deletion src/hotspot/share/jvmci/jvmciEnv.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,7 @@ class JVMCIEnv : public ResourceObj {
DO_THROW(UnsatisfiedLinkError)
DO_THROW(UnsupportedOperationException)
DO_THROW(OutOfMemoryError)
DO_THROW(ClassNotFoundException)
DO_THROW(NoClassDefFoundError)

#undef DO_THROW

Expand Down
8 changes: 4 additions & 4 deletions src/hotspot/share/jvmci/jvmciJavaClasses.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -243,11 +243,11 @@
start_class(InternalError, java_lang_InternalError) \
jvmci_constructor(InternalError, "(Ljava/lang/String;)V") \
end_class \
start_class(OutOfMemoryError, java_lang_OutOfMemoryError) \
jvmci_constructor(OutOfMemoryError, "(Ljava/lang/String;)V") \
start_class(OutOfMemoryError, java_lang_OutOfMemoryError) \
jvmci_constructor(OutOfMemoryError, "(Ljava/lang/String;)V") \
end_class \
start_class(ClassNotFoundException, java_lang_ClassNotFoundException) \
jvmci_constructor(ClassNotFoundException, "(Ljava/lang/String;)V") \
start_class(NoClassDefFoundError, java_lang_NoClassDefFoundError) \
jvmci_constructor(NoClassDefFoundError, "(Ljava/lang/String;)V") \
end_class \
start_class(InvalidInstalledCodeException, jdk_vm_ci_code_InvalidInstalledCodeException) \
jvmci_constructor(InvalidInstalledCodeException, "(Ljava/lang/String;)V") \
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -240,20 +240,52 @@ boolean methodIsIgnoredBySecurityStackWalk(HotSpotResolvedJavaMethodImpl method)
* Converts a name to a type.
*
* @param name a well formed Java type in {@linkplain JavaType#getName() internal} format
* @param accessingClass the context of resolution. A value of {@code null} implies that the
* class should be resolved with the {@linkplain ClassLoader#getSystemClassLoader()
* system class loader}.
* @param accessingClass the class loader of this class is used for resolution. Must not be null.
* @param resolve force resolution to a {@link ResolvedJavaType}. If true, this method will
* either return a {@link ResolvedJavaType} or throw an exception
* @return the type for {@code name} or 0 if resolution failed and {@code resolve == false}
* @throws ClassNotFoundException if {@code resolve == true} and the resolution failed
* @throws NoClassDefFoundError if {@code resolve == true} and the resolution failed
*/
HotSpotResolvedJavaType lookupType(String name, HotSpotResolvedObjectTypeImpl accessingClass, boolean resolve) throws ClassNotFoundException {
return lookupType(name, accessingClass, accessingClass != null ? accessingClass.getKlassPointer() : 0L, resolve);
HotSpotResolvedJavaType lookupType(String name, HotSpotResolvedObjectTypeImpl accessingClass, boolean resolve) throws NoClassDefFoundError {
return lookupType(name, accessingClass, accessingClass.getKlassPointer(), -1, resolve);
}

private native HotSpotResolvedJavaType lookupType(String name, HotSpotResolvedObjectTypeImpl accessingClass, long klassPointer, boolean resolve) throws ClassNotFoundException;
/**
* Converts a name to a type.
*
* @param classLoader the class loader to use for resolution. Must not be {@code null},
* {@link ClassLoader#getPlatformClassLoader} or {@link ClassLoader#getSystemClassLoader}
* @param name a well formed Java type in {@linkplain JavaType#getName() internal} format
* @return the type for {@code name}
* @throws NoClassDefFoundError if resolution failed
*/
HotSpotResolvedJavaType lookupType(ClassLoader classLoader, String name) throws NoClassDefFoundError {
int accessingClassLoader;
if (classLoader == null) {
accessingClassLoader = 0;
} else if (classLoader == ClassLoader.getPlatformClassLoader()) {
accessingClassLoader = 1;
} else if (classLoader == ClassLoader.getSystemClassLoader()) {
accessingClassLoader = 2;
} else {
throw new IllegalArgumentException("Unsupported class loader for lookup: " + classLoader);
}
return lookupType(name, null, 0L, accessingClassLoader, true);
}

/**
* @param accessingClassLoader ignored if {@code accessingKlassPointer != 0L}. Otherwise, the supported values are:
* 0 - boot class loader
* 1 - {@linkplain ClassLoader#getPlatformClassLoader() platform class loader}
* 2 - {@linkplain ClassLoader#getSystemClassLoader() system class loader}
*/
private native HotSpotResolvedJavaType lookupType(String name, HotSpotResolvedObjectTypeImpl accessingClass, long accessingKlassPointer, int accessingClassLoader, boolean resolve) throws NoClassDefFoundError;

/**
* Converts {@code javaClass} to a HotSpotResolvedJavaType.
*
* Must not be called if {@link Services#IS_IN_NATIVE_IMAGE} is {@code true}.
*/
native HotSpotResolvedJavaType lookupClass(Class<?> javaClass);

native HotSpotResolvedJavaType lookupJClass(long jclass);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -627,11 +627,7 @@ HotSpotResolvedJavaType createClass(Class<?> javaClass) {
return HotSpotResolvedPrimitiveType.forKind(JavaKind.fromJavaClass(javaClass));
}
if (IS_IN_NATIVE_IMAGE) {
try {
return compilerToVm.lookupType(javaClass.getName().replace('.', '/'), null, true);
} catch (ClassNotFoundException e) {
throw new JVMCIError(e);
}
return compilerToVm.lookupType(javaClass.getClassLoader(), javaClass.getName().replace('.', '/'));
}
return compilerToVm.lookupClass(javaClass);
}
Expand Down Expand Up @@ -869,17 +865,13 @@ JavaType lookupTypeInternal(String name, HotSpotResolvedObjectType accessingType

// Resolve non-primitive types in the VM.
HotSpotResolvedObjectTypeImpl hsAccessingType = (HotSpotResolvedObjectTypeImpl) accessingType;
try {
final HotSpotResolvedJavaType klass = compilerToVm.lookupType(name, hsAccessingType, resolve);
final HotSpotResolvedJavaType klass = compilerToVm.lookupType(name, hsAccessingType, resolve);

if (klass == null) {
assert resolve == false : name;
return UnresolvedJavaType.create(name);
}
return klass;
} catch (ClassNotFoundException e) {
throw (NoClassDefFoundError) new NoClassDefFoundError().initCause(e);
if (klass == null) {
assert resolve == false : name;
return UnresolvedJavaType.create(name);
}
return klass;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,26 +77,27 @@ private static ResolvedJavaField findFieldInClass(ResolvedJavaType declaringType
throw new NoSuchFieldError(declaringType + "." + fieldName);
}

private static ResolvedJavaType resolveType(String className) {
return (ResolvedJavaType) runtime().lookupTypeInternal(className, null, true);
private static ResolvedJavaType resolveType(String className, HotSpotResolvedObjectType accessingType) {
return (ResolvedJavaType) runtime().lookupTypeInternal(className, accessingType, true);
}

private Internals() {
try {
ResolvedJavaType methodHandleType = resolveType("Ljava/lang/invoke/MethodHandle;");
ResolvedJavaType memberNameType = resolveType("Ljava/lang/invoke/MemberName;");
lambdaFormType = resolveType("Ljava/lang/invoke/LambdaForm;");
HotSpotResolvedObjectType accessingType = runtime().getJavaLangObject();
ResolvedJavaType methodHandleType = resolveType("Ljava/lang/invoke/MethodHandle;", accessingType);
ResolvedJavaType memberNameType = resolveType("Ljava/lang/invoke/MemberName;", accessingType);
lambdaFormType = resolveType("Ljava/lang/invoke/LambdaForm;", accessingType);
methodHandleFormField = findFieldInClass(methodHandleType, "form", lambdaFormType);
lambdaFormVmentryField = findFieldInClass(lambdaFormType, "vmentry", memberNameType);

ResolvedJavaType methodType = resolveType("Ljava/lang/invoke/ResolvedMethodName;");
ResolvedJavaType methodType = resolveType("Ljava/lang/invoke/ResolvedMethodName;", accessingType);
methodField = findFieldInClass(memberNameType, "method", methodType);
vmtargetField = (HotSpotResolvedJavaField) findFieldInClass(methodType, "vmtarget", resolveType(Character.toString(HotSpotJVMCIRuntime.getHostWordKind().getTypeChar())));
vmtargetField = (HotSpotResolvedJavaField) findFieldInClass(methodType, "vmtarget", resolveType(Character.toString(HotSpotJVMCIRuntime.getHostWordKind().getTypeChar()), accessingType));

ResolvedJavaType callSiteType = resolveType("Ljava/lang/invoke/CallSite;");
ResolvedJavaType callSiteType = resolveType("Ljava/lang/invoke/CallSite;", accessingType);
callSiteTargetField = (HotSpotResolvedJavaField) findFieldInClass(callSiteType, "target", methodHandleType);
ResolvedJavaType constantCallSiteType = resolveType("Ljava/lang/invoke/ConstantCallSite;");
ResolvedJavaType booleanType = resolveType("Z");
ResolvedJavaType constantCallSiteType = resolveType("Ljava/lang/invoke/ConstantCallSite;", accessingType);
ResolvedJavaType booleanType = resolveType("Z", accessingType);
constantCallSiteFrozenField = (HotSpotResolvedJavaField) findFieldInClass(constantCallSiteType, "isFrozen", booleanType);
} catch (Throwable ex) {
throw new JVMCIError(ex);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -188,16 +188,8 @@ <T extends Annotation> T getFieldAnnotation(HotSpotResolvedJavaFieldImpl javaFie
HotSpotResolvedObjectTypeImpl getType(HotSpotObjectConstantImpl object) {
if (object instanceof DirectHotSpotObjectConstantImpl) {
Class<?> theClass = ((DirectHotSpotObjectConstantImpl) object).object.getClass();
try {
String name = theClass.getName().replace('.', '/');
HotSpotResolvedObjectTypeImpl type = (HotSpotResolvedObjectTypeImpl) runtime().compilerToVm.lookupType(name, null, true);
if (type == null) {
throw new InternalError(name);
}
return type;
} catch (ClassNotFoundException e) {
throw new InternalError(e);
}
String name = theClass.getName().replace('.', '/');
return (HotSpotResolvedObjectTypeImpl) runtime().compilerToVm.lookupType(theClass.getClassLoader(), name);
}
return runtime().compilerToVm.getResolvedJavaType(object, runtime().getConfig().hubOffset, false);
}
Expand Down

1 comment on commit 83adaf5

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.