Skip to content

Commit

Permalink
fixup! Don't create JNINativeCallWrapperMethods for JNICallTrampoline…
Browse files Browse the repository at this point in the history
…Methods
  • Loading branch information
zakkak committed Dec 22, 2021
1 parent 92620bf commit c3a8572
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ public static ConstantPool getConstantPool(MetaAccessProvider metaAccess) {
return metaAccess.lookupJavaType(JNIJavaCallWrappers.class).getDeclaredConstructors()[0].getConstantPool();
}

private JNIJavaCallTrampolines() {
}

public static String getTrampolineName(CallVariant variant, boolean nonVirtual) {
StringBuilder name = new StringBuilder(48);
if (variant == CallVariant.VARARGS) {
Expand All @@ -59,7 +62,21 @@ public static String getTrampolineName(CallVariant variant, boolean nonVirtual)
return name.toString();
}

private JNIJavaCallTrampolines() {
public static boolean isNonVirtual(String trampolineName) {
return trampolineName.endsWith("NonvirtualJavaCallTrampoline");
}

public static CallVariant getVariant(String trampolineName) {
if (trampolineName.startsWith("varargs")) {
return CallVariant.VARARGS;
}
if (trampolineName.startsWith("array")) {
return CallVariant.ARRAY;
}
if (trampolineName.startsWith("valist")) {
return CallVariant.VA_LIST;
}
throw VMError.shouldNotReachHere();
}

private native void varargsJavaCallTrampoline();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Stream;

import com.oracle.graal.pointsto.meta.AnalysisMetaAccess;
import com.oracle.svm.hosted.FeatureImpl.DuringSetupAccessImpl;
import com.oracle.svm.jni.JNIJavaCallTrampolines;
import com.oracle.svm.util.ReflectionUtil;
import org.graalvm.compiler.api.replacements.Fold;
Expand Down Expand Up @@ -183,16 +185,17 @@ private static ConditionalConfigurationRegistry getConditionalConfigurationRegis
}

private void createJavaCallTrampoline(BeforeAnalysisAccessImpl access, CallVariant variant, boolean nonVirtual) {
MetaAccessProvider wrappedMetaAccess = access.getMetaAccess().getWrapped();
ResolvedJavaField field = JNIAccessibleMethod.getCallWrapperField(wrappedMetaAccess, variant, nonVirtual);
AnalysisMetaAccess metaAccess = access.getMetaAccess();
ResolvedJavaField field = JNIAccessibleMethod.getCallWrapperField(metaAccess.getWrapped(), variant, nonVirtual);
access.getUniverse().lookup(field.getDeclaringClass()).registerAsReachable();
access.registerAsAccessed(access.getUniverse().lookup(field));
String trampolineName = JNIJavaCallTrampolines.getTrampolineName(variant, nonVirtual);
Method reflectionMethod = ReflectionUtil.lookupMethod(JNIJavaCallTrampolines.class, trampolineName);
ResolvedJavaMethod method = wrappedMetaAccess.lookupJavaMethod(reflectionMethod);
JNICallTrampolineMethod trampoline = new JNICallTrampolineMethod(method, field, nonVirtual);
// Look up the java method to ensure a JNICallTrampolineMethod gets created for it through
// com.oracle.svm.jni.hosted.JNINativeCallWrapperSubstitutionProcessor.lookup
metaAccess.lookupJavaMethod(reflectionMethod);
JNICallTrampolineMethod trampoline = getCallTrampolineMethod(trampolineName);
access.registerAsCompiled(access.getUniverse().lookup(trampoline));
trampolineMethods.put(trampolineName, trampoline);
}

public JNICallTrampolineMethod getCallTrampolineMethod(CallVariant variant, boolean nonVirtual) {
Expand All @@ -206,6 +209,25 @@ public JNICallTrampolineMethod getCallTrampolineMethod(String javaTrampolineName
return jniCallTrampolineMethod;
}

public JNICallTrampolineMethod getOrCreateCallTrampolineMethod(DuringSetupAccessImpl access, String trampolineName) {
JNICallTrampolineMethod jniCallTrampolineMethod = trampolineMethods.get(trampolineName);

if (jniCallTrampolineMethod != null) {
return jniCallTrampolineMethod;
}

MetaAccessProvider wrappedMetaAccess = access.getMetaAccess().getWrapped();
Method reflectionMethod = ReflectionUtil.lookupMethod(JNIJavaCallTrampolines.class, trampolineName);
boolean nonVirtual = JNIJavaCallTrampolines.isNonVirtual(trampolineName);
ResolvedJavaField field = JNIAccessibleMethod.getCallWrapperField(wrappedMetaAccess, JNIJavaCallTrampolines.getVariant(trampolineName), nonVirtual);
// Use wrapped MetaAccess to avoid infinite recursion through
// com.oracle.svm.jni.hosted.JNINativeCallWrapperSubstitutionProcessor.lookup
ResolvedJavaMethod method = wrappedMetaAccess.lookupJavaMethod(reflectionMethod);
JNICallTrampolineMethod trampoline = new JNICallTrampolineMethod(method, field, nonVirtual);
trampolineMethods.put(trampolineName, trampoline);
return trampoline;
}

public JNINativeLinkage makeLinkage(String declaringClass, String name, String descriptor) {
UserError.guarantee(!sealed,
"All linkages for JNI calls must be created before the analysis has completed.%nOffending class: %s name: %s descriptor: %s",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,6 @@ public List<Class<? extends Feature>> getRequiredFeatures() {
@Override
public void duringSetup(DuringSetupAccess access) {
DuringSetupAccessImpl config = (DuringSetupAccessImpl) access;
config.registerNativeSubstitutionProcessor(new JNINativeCallWrapperSubstitutionProcessor());
config.registerNativeSubstitutionProcessor(new JNINativeCallWrapperSubstitutionProcessor(config));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@

import com.oracle.graal.pointsto.infrastructure.SubstitutionProcessor;

import com.oracle.svm.hosted.FeatureImpl.DuringSetupAccessImpl;
import com.oracle.svm.jni.JNIJavaCallTrampolines;
import com.oracle.svm.jni.access.JNIAccessFeature;
import jdk.vm.ci.meta.MetaUtil;
Expand All @@ -40,17 +41,20 @@
*/
class JNINativeCallWrapperSubstitutionProcessor extends SubstitutionProcessor {
private final Map<ResolvedJavaMethod, JNINativeCallWrapperMethod> callWrappers = new ConcurrentHashMap<>();
private final DuringSetupAccessImpl access;

public JNINativeCallWrapperSubstitutionProcessor(DuringSetupAccessImpl access) {
super();
this.access = access;
}

@Override
public ResolvedJavaMethod lookup(ResolvedJavaMethod method) {
assert method.isNative() : "Must have been registered as a native substitution processor";
String jniJavaCallWrappersInternalName = MetaUtil.toInternalName(JNIJavaCallTrampolines.class.getTypeName());
if (method.getDeclaringClass().getName().equals(jniJavaCallWrappersInternalName)) {
// Avoid generating JNINativeCallWrapperMethods for trampolines
JNICallTrampolineMethod callTrampolineMethod = JNIAccessFeature.singleton().getCallTrampolineMethod(method.getName());
if (callTrampolineMethod != null) {
return callTrampolineMethod;
}
return JNIAccessFeature.singleton().getOrCreateCallTrampolineMethod(access, method.getName());
}
return callWrappers.computeIfAbsent(method, JNINativeCallWrapperMethod::new);
}
Expand Down

0 comments on commit c3a8572

Please sign in to comment.