From 863ddaad2ba299cc13ac5e765fc2e107babe9bda Mon Sep 17 00:00:00 2001 From: Foivos Zakkak Date: Fri, 10 Dec 2021 15:50:00 +0200 Subject: [PATCH 1/7] Fix line numbers in debuginfotest --- substratevm/mx.substratevm/testhello.py | 94 ++++++++++++------------- 1 file changed, 47 insertions(+), 47 deletions(-) diff --git a/substratevm/mx.substratevm/testhello.py b/substratevm/mx.substratevm/testhello.py index f27c39e0027d..90ec19a4db14 100644 --- a/substratevm/mx.substratevm/testhello.py +++ b/substratevm/mx.substratevm/testhello.py @@ -574,78 +574,78 @@ def test(): checker.check(exec_string, skip_fails=False) exec_string = execute("info break 6") - rexp = [r"6.1%sy%s%s in hello\.Hello::inlineFrom at hello/Hello\.java:140"%(spaces_pattern, spaces_pattern, address_pattern), - r"6.2%sy%s%s in hello\.Hello::inlineFrom at hello/Hello\.java:177"%(spaces_pattern, spaces_pattern, address_pattern), - r"6.3%sy%s%s in hello\.Hello::inlineFrom at hello/Hello\.java:160"%(spaces_pattern, spaces_pattern, address_pattern), - r"6.4%sy%s%s in hello\.Hello::inlineFrom at hello/Hello\.java:177"%(spaces_pattern, spaces_pattern, address_pattern)] + rexp = [r"6.1%sy%s%s in hello\.Hello::inlineFrom at hello/Hello\.java:141"%(spaces_pattern, spaces_pattern, address_pattern), + r"6.2%sy%s%s in hello\.Hello::inlineFrom at hello/Hello\.java:179"%(spaces_pattern, spaces_pattern, address_pattern), + r"6.3%sy%s%s in hello\.Hello::inlineFrom at hello/Hello\.java:162"%(spaces_pattern, spaces_pattern, address_pattern), + r"6.4%sy%s%s in hello\.Hello::inlineFrom at hello/Hello\.java:179"%(spaces_pattern, spaces_pattern, address_pattern)] checker = Checker('info break inlineFrom', rexp) checker.check(exec_string) execute("delete breakpoints") - exec_string = execute("break Hello.java:155") - rexp = r"Breakpoint %s at %s: file hello/Hello\.java, line 155\."%(digits_pattern, address_pattern) - checker = Checker('break Hello.java:155', rexp) + exec_string = execute("break Hello.java:157") + rexp = r"Breakpoint %s at %s: file hello/Hello\.java, line 157\."%(digits_pattern, address_pattern) + checker = Checker('break Hello.java:157', rexp) checker.check(exec_string) execute("continue 5") exec_string = execute("backtrace 14") - rexp = [r"#0%shello\.Hello::inlineMixTo \(\) at hello/Hello\.java:155"%(spaces_pattern), - r"#1%shello\.Hello::noInlineHere\(int\) \(\) at hello/Hello\.java:147"%(spaces_pattern), - r"#2%s%s in hello\.Hello::inlineMixTo \(\) at hello/Hello\.java:153"%(spaces_pattern, address_pattern), - r"#3%shello\.Hello::noInlineHere\(int\) \(\) at hello/Hello\.java:147"%(spaces_pattern), - r"#4%s%s in hello\.Hello::inlineMixTo \(\) at hello/Hello\.java:153"%(spaces_pattern, address_pattern), - r"#5%shello\.Hello::noInlineHere\(int\) \(\) at hello/Hello\.java:147"%(spaces_pattern), - r"#6%s%s in hello\.Hello::inlineMixTo \(\) at hello/Hello\.java:153"%(spaces_pattern, address_pattern), - r"#7%shello\.Hello::noInlineHere\(int\) \(\) at hello/Hello\.java:147"%(spaces_pattern), - r"#8%s%s in hello\.Hello::inlineMixTo \(\) at hello/Hello\.java:153"%(spaces_pattern, address_pattern), - r"#9%shello\.Hello::noInlineHere\(int\) \(\) at hello/Hello\.java:147"%(spaces_pattern), - r"#10%s%s in hello\.Hello::inlineMixTo \(\) at hello/Hello\.java:153"%(spaces_pattern, address_pattern), - r"#11%shello\.Hello::noInlineHere\(int\) \(\) at hello/Hello\.java:147"%(spaces_pattern), - r"#12%s%s in hello\.Hello::inlineFrom \(\) at hello/Hello\.java:140"%(spaces_pattern, address_pattern), + rexp = [r"#0%shello\.Hello::inlineMixTo \(\) at hello/Hello\.java:157"%(spaces_pattern), + r"#1%shello\.Hello::noInlineHere\(int\) \(\) at hello/Hello\.java:149"%(spaces_pattern), + r"#2%s%s in hello\.Hello::inlineMixTo \(\) at hello/Hello\.java:155"%(spaces_pattern, address_pattern), + r"#3%shello\.Hello::noInlineHere\(int\) \(\) at hello/Hello\.java:149"%(spaces_pattern), + r"#4%s%s in hello\.Hello::inlineMixTo \(\) at hello/Hello\.java:155"%(spaces_pattern, address_pattern), + r"#5%shello\.Hello::noInlineHere\(int\) \(\) at hello/Hello\.java:149"%(spaces_pattern), + r"#6%s%s in hello\.Hello::inlineMixTo \(\) at hello/Hello\.java:155"%(spaces_pattern, address_pattern), + r"#7%shello\.Hello::noInlineHere\(int\) \(\) at hello/Hello\.java:149"%(spaces_pattern), + r"#8%s%s in hello\.Hello::inlineMixTo \(\) at hello/Hello\.java:155"%(spaces_pattern, address_pattern), + r"#9%shello\.Hello::noInlineHere\(int\) \(\) at hello/Hello\.java:149"%(spaces_pattern), + r"#10%s%s in hello\.Hello::inlineMixTo \(\) at hello/Hello\.java:155"%(spaces_pattern, address_pattern), + r"#11%shello\.Hello::noInlineHere\(int\) \(\) at hello/Hello\.java:149"%(spaces_pattern), + r"#12%s%s in hello\.Hello::inlineFrom \(\) at hello/Hello\.java:141"%(spaces_pattern, address_pattern), r"#13%shello\.Hello::main\(java\.lang\.String\[\] \*\) \(\) at hello/Hello\.java:94"%(spaces_pattern)] checker = Checker('backtrace in recursive inlineMixTo', rexp) checker.check(exec_string, skip_fails=False) execute("delete breakpoints") - exec_string = execute("break Hello.java:168") - rexp = r"Breakpoint %s at %s: Hello\.java:168\. \(2 locations\)"%(digits_pattern, address_pattern) - checker = Checker('break Hello.java:168', rexp) + exec_string = execute("break Hello.java:170") + rexp = r"Breakpoint %s at %s: Hello\.java:170\. \(2 locations\)"%(digits_pattern, address_pattern) + checker = Checker('break Hello.java:170', rexp) checker.check(exec_string) - execute("continue 5") + execute("continue") exec_string = execute("backtrace 14") - rexp = [r"#0%shello\.Hello::inlineTo\(int\) \(\) at hello/Hello\.java:168"%(spaces_pattern), - r"#1%s%s in hello\.Hello::inlineHere \(\) at hello/Hello\.java:160"%(spaces_pattern, address_pattern), - r"#2%shello\.Hello::inlineTo\(int\) \(\) at hello/Hello\.java:166"%(spaces_pattern), - r"#3%s%s in hello\.Hello::inlineHere \(\) at hello/Hello\.java:160"%(spaces_pattern, address_pattern), - r"#4%shello\.Hello::inlineTo\(int\) \(\) at hello/Hello\.java:166"%(spaces_pattern), - r"#5%s%s in hello\.Hello::inlineHere \(\) at hello/Hello\.java:160"%(spaces_pattern, address_pattern), - r"#6%shello\.Hello::inlineTo\(int\) \(\) at hello/Hello\.java:166"%(spaces_pattern), - r"#7%s%s in hello\.Hello::inlineHere \(\) at hello/Hello\.java:160"%(spaces_pattern, address_pattern), - r"#8%shello\.Hello::inlineTo\(int\) \(\) at hello/Hello\.java:166"%(spaces_pattern), - r"#9%s%s in hello\.Hello::inlineHere \(\) at hello/Hello\.java:160"%(spaces_pattern, address_pattern), - r"#10%shello\.Hello::inlineTo \(\) at hello/Hello\.java:166"%(spaces_pattern), - r"#11%shello\.Hello::inlineHere \(\) at hello/Hello\.java:160"%(spaces_pattern), - r"#12%shello\.Hello::inlineFrom \(\) at hello/Hello\.java:141"%(spaces_pattern), + rexp = [r"#0%shello\.Hello::inlineTo\(int\) \(\) at hello/Hello\.java:170"%(spaces_pattern), + r"#1%s%s in hello\.Hello::inlineHere \(\) at hello/Hello\.java:162"%(spaces_pattern, address_pattern), + r"#2%shello\.Hello::inlineTo\(int\) \(\) at hello/Hello\.java:168"%(spaces_pattern), + r"#3%s%s in hello\.Hello::inlineHere \(\) at hello/Hello\.java:162"%(spaces_pattern, address_pattern), + r"#4%shello\.Hello::inlineTo\(int\) \(\) at hello/Hello\.java:168"%(spaces_pattern), + r"#5%s%s in hello\.Hello::inlineHere \(\) at hello/Hello\.java:162"%(spaces_pattern, address_pattern), + r"#6%shello\.Hello::inlineTo\(int\) \(\) at hello/Hello\.java:168"%(spaces_pattern), + r"#7%s%s in hello\.Hello::inlineHere \(\) at hello/Hello\.java:162"%(spaces_pattern, address_pattern), + r"#8%shello\.Hello::inlineTo\(int\) \(\) at hello/Hello\.java:168"%(spaces_pattern), + r"#9%s%s in hello\.Hello::inlineHere \(\) at hello/Hello\.java:162"%(spaces_pattern, address_pattern), + r"#10%shello\.Hello::inlineTo \(\) at hello/Hello\.java:168"%(spaces_pattern), + r"#11%shello\.Hello::inlineHere \(\) at hello/Hello\.java:162"%(spaces_pattern), + r"#12%shello\.Hello::inlineFrom \(\) at hello/Hello\.java:143"%(spaces_pattern), r"#13%shello\.Hello::main\(java\.lang\.String\[\] \*\) \(\) at hello/Hello\.java:94"%(spaces_pattern)] checker = Checker('backtrace in recursive inlineTo', rexp) checker.check(exec_string, skip_fails=False) execute("delete breakpoints") - exec_string = execute("break Hello.java:174") - rexp = r"Breakpoint %s at %s: file hello/Hello\.java, line 174\."%(digits_pattern, address_pattern) - checker = Checker('break Hello.java:174', rexp) + exec_string = execute("break Hello.java:176") + rexp = r"Breakpoint %s at %s: file hello/Hello\.java, line 176\."%(digits_pattern, address_pattern) + checker = Checker('break Hello.java:176', rexp) checker.check(exec_string) execute("continue 5") exec_string = execute("backtrace 8") - rexp = [r"#0%shello\.Hello::inlineTailRecursion\(int\) \(\) at hello/Hello\.java:174"%(spaces_pattern), - r"#1%s%s in hello\.Hello::inlineTailRecursion\(int\) \(\) at hello/Hello\.java:177"%(spaces_pattern, address_pattern), - r"#2%s%s in hello\.Hello::inlineTailRecursion\(int\) \(\) at hello/Hello\.java:177"%(spaces_pattern, address_pattern), - r"#3%s%s in hello\.Hello::inlineTailRecursion\(int\) \(\) at hello/Hello\.java:177"%(spaces_pattern, address_pattern), - r"#4%s%s in hello\.Hello::inlineTailRecursion\(int\) \(\) at hello/Hello\.java:177"%(spaces_pattern, address_pattern), - r"#5%s%s in hello\.Hello::inlineTailRecursion \(\) at hello/Hello\.java:177"%(spaces_pattern, address_pattern), - r"#6%shello\.Hello::inlineFrom \(\) at hello/Hello\.java:142"%(spaces_pattern), + rexp = [r"#0%shello\.Hello::inlineTailRecursion\(int\) \(\) at hello/Hello\.java:176"%(spaces_pattern), + r"#1%s%s in hello\.Hello::inlineTailRecursion\(int\) \(\) at hello/Hello\.java:179"%(spaces_pattern, address_pattern), + r"#2%s%s in hello\.Hello::inlineTailRecursion\(int\) \(\) at hello/Hello\.java:179"%(spaces_pattern, address_pattern), + r"#3%s%s in hello\.Hello::inlineTailRecursion\(int\) \(\) at hello/Hello\.java:179"%(spaces_pattern, address_pattern), + r"#4%s%s in hello\.Hello::inlineTailRecursion\(int\) \(\) at hello/Hello\.java:179"%(spaces_pattern, address_pattern), + r"#5%s%s in hello\.Hello::inlineTailRecursion \(\) at hello/Hello\.java:179"%(spaces_pattern, address_pattern), + r"#6%shello\.Hello::inlineFrom \(\) at hello/Hello\.java:144"%(spaces_pattern), r"#7%shello\.Hello::main\(java\.lang\.String\[\] \*\) \(\) at hello/Hello\.java:94"%(spaces_pattern)] checker = Checker('backtrace in recursive inlineTo', rexp) checker.check(exec_string, skip_fails=False) From 7b70d5a6cb06e080e7717dabd056364b65cd9fe8 Mon Sep 17 00:00:00 2001 From: Foivos Zakkak Date: Fri, 10 Dec 2021 16:20:35 +0200 Subject: [PATCH 2/7] Don't create JNINativeCallWrapperMethods for JNICallTrampolineMethods `JNICallTrampolineMethod`s can not be invoked from Java, so creating `JNINativeCallWrapperMethod`s for them is not needed. Closes: #4018 --- .github/workflows/main.yml | 2 - .../oracle/svm/jni/JNIJavaCallWrappers.java | 9 +--- .../svm/jni/access/JNIAccessFeature.java | 51 ++++++++++--------- ...ativeCallWrapperSubstitutionProcessor.java | 8 +++ 4 files changed, 36 insertions(+), 34 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 2584b75b7736..25035d790e7b 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -79,12 +79,10 @@ jobs: JDK: "labsjdk-ce-17" GATE: "build,debuginfotest" PRIMARY: "substratevm" - GHA_EXPECTED_FAILURE: true # temporarily marked as expected failure due to #4018 / GR-35118 - env: JDK: "labsjdk-ce-11" GATE: "build,debuginfotest" PRIMARY: "substratevm" - GHA_EXPECTED_FAILURE: true # temporarily marked as expected failure due to #4018 / GR-35118 - env: JDK: "labsjdk-ce-11" GATE: "hellomodule" diff --git a/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/JNIJavaCallWrappers.java b/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/JNIJavaCallWrappers.java index e481d3d11eb9..f0221e464a8d 100644 --- a/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/JNIJavaCallWrappers.java +++ b/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/JNIJavaCallWrappers.java @@ -30,7 +30,6 @@ import jdk.vm.ci.meta.ConstantPool; import jdk.vm.ci.meta.MetaAccessProvider; -import jdk.vm.ci.meta.ResolvedJavaMethod; /** * Holder class for generated {@link JNIJavaCallWrapperMethod} code. @@ -42,7 +41,7 @@ public static ConstantPool getConstantPool(MetaAccessProvider metaAccess) { return metaAccess.lookupJavaType(JNIJavaCallWrappers.class).getDeclaredConstructors()[0].getConstantPool(); } - public static ResolvedJavaMethod lookupJavaCallTrampoline(MetaAccessProvider metaAccess, CallVariant variant, boolean nonVirtual) { + public static String getTrampolineName(CallVariant variant, boolean nonVirtual) { StringBuilder name = new StringBuilder(48); if (variant == CallVariant.VARARGS) { name.append("varargs"); @@ -57,11 +56,7 @@ public static ResolvedJavaMethod lookupJavaCallTrampoline(MetaAccessProvider met name.append("Nonvirtual"); } name.append("JavaCallTrampoline"); - try { - return metaAccess.lookupJavaMethod(JNIJavaCallWrappers.class.getDeclaredMethod(name.toString())); - } catch (NoSuchMethodException e) { - throw VMError.shouldNotReachHere(e); - } + return name.toString(); } private JNIJavaCallWrappers() { diff --git a/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/access/JNIAccessFeature.java b/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/access/JNIAccessFeature.java index 433d14283a67..da292cd61153 100644 --- a/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/access/JNIAccessFeature.java +++ b/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/access/JNIAccessFeature.java @@ -31,11 +31,13 @@ import java.lang.reflect.Modifier; import java.util.Arrays; import java.util.Collections; +import java.util.HashMap; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Stream; +import com.oracle.svm.core.util.VMError; import org.graalvm.compiler.api.replacements.Fold; import org.graalvm.compiler.options.Option; import org.graalvm.nativeimage.ImageSingletons; @@ -90,12 +92,7 @@ public static JNIAccessFeature singleton() { private boolean sealed = false; private NativeLibraries nativeLibraries; - private JNICallTrampolineMethod varargsCallTrampolineMethod; - private JNICallTrampolineMethod arrayCallTrampolineMethod; - private JNICallTrampolineMethod valistCallTrampolineMethod; - private JNICallTrampolineMethod varargsNonvirtualCallTrampolineMethod; - private JNICallTrampolineMethod arrayNonvirtualCallTrampolineMethod; - private JNICallTrampolineMethod valistNonvirtualCallTrampolineMethod; + private final Map trampolineMethods = new HashMap<>(); private int loadedConfigurations; @@ -169,12 +166,12 @@ public void beforeAnalysis(BeforeAnalysisAccess arg) { BeforeAnalysisAccessImpl access = (BeforeAnalysisAccessImpl) arg; this.nativeLibraries = access.getNativeLibraries(); - varargsCallTrampolineMethod = createJavaCallTrampoline(access, CallVariant.VARARGS, false); - arrayCallTrampolineMethod = createJavaCallTrampoline(access, CallVariant.ARRAY, false); - valistCallTrampolineMethod = createJavaCallTrampoline(access, CallVariant.VA_LIST, false); - varargsNonvirtualCallTrampolineMethod = createJavaCallTrampoline(access, CallVariant.VARARGS, true); - arrayNonvirtualCallTrampolineMethod = createJavaCallTrampoline(access, CallVariant.ARRAY, true); - valistNonvirtualCallTrampolineMethod = createJavaCallTrampoline(access, CallVariant.VA_LIST, true); + createJavaCallTrampoline(access, CallVariant.VARARGS, false); + createJavaCallTrampoline(access, CallVariant.ARRAY, false); + createJavaCallTrampoline(access, CallVariant.VA_LIST, false); + createJavaCallTrampoline(access, CallVariant.VARARGS, true); + createJavaCallTrampoline(access, CallVariant.ARRAY, true); + createJavaCallTrampoline(access, CallVariant.VA_LIST, true); /* duplicated to reduce the number of analysis iterations */ getConditionalConfigurationRegistry().flushConditionalConfiguration(access); @@ -184,28 +181,32 @@ private static ConditionalConfigurationRegistry getConditionalConfigurationRegis return (ConditionalConfigurationRegistry) ImageSingletons.lookup(JNIRuntimeAccess.JNIRuntimeAccessibilitySupport.class); } - private static JNICallTrampolineMethod createJavaCallTrampoline(BeforeAnalysisAccessImpl access, CallVariant variant, boolean nonVirtual) { + private void createJavaCallTrampoline(BeforeAnalysisAccessImpl access, CallVariant variant, boolean nonVirtual) { MetaAccessProvider wrappedMetaAccess = access.getMetaAccess().getWrapped(); ResolvedJavaField field = JNIAccessibleMethod.getCallWrapperField(wrappedMetaAccess, variant, nonVirtual); access.getUniverse().lookup(field.getDeclaringClass()).registerAsReachable(); access.registerAsAccessed(access.getUniverse().lookup(field)); - ResolvedJavaMethod method = JNIJavaCallWrappers.lookupJavaCallTrampoline(wrappedMetaAccess, variant, nonVirtual); + String trampolineName = JNIJavaCallWrappers.getTrampolineName(variant, nonVirtual); + ResolvedJavaMethod method; + try { + method = wrappedMetaAccess.lookupJavaMethod(JNIJavaCallWrappers.class.getDeclaredMethod(trampolineName)); + } catch (NoSuchMethodException e) { + throw VMError.shouldNotReachHere(e); + } JNICallTrampolineMethod trampoline = new JNICallTrampolineMethod(method, field, nonVirtual); access.registerAsCompiled(access.getUniverse().lookup(trampoline)); - return trampoline; + trampolineMethods.put(trampolineName, trampoline); } public JNICallTrampolineMethod getCallTrampolineMethod(CallVariant variant, boolean nonVirtual) { - JNICallTrampolineMethod method = null; - if (variant == CallVariant.VARARGS) { - method = nonVirtual ? varargsNonvirtualCallTrampolineMethod : varargsCallTrampolineMethod; - } else if (variant == CallVariant.ARRAY) { - method = nonVirtual ? arrayNonvirtualCallTrampolineMethod : arrayCallTrampolineMethod; - } else if (variant == CallVariant.VA_LIST) { - method = nonVirtual ? valistNonvirtualCallTrampolineMethod : valistCallTrampolineMethod; - } - assert method != null; - return method; + String trampolineName = JNIJavaCallWrappers.getTrampolineName(variant, nonVirtual); + return getCallTrampolineMethod(trampolineName); + } + + public JNICallTrampolineMethod getCallTrampolineMethod(String javaTrampolineName) { + JNICallTrampolineMethod jniCallTrampolineMethod = trampolineMethods.get(javaTrampolineName); + assert jniCallTrampolineMethod != null; + return jniCallTrampolineMethod; } public JNINativeLinkage makeLinkage(String declaringClass, String name, String descriptor) { diff --git a/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/hosted/JNINativeCallWrapperSubstitutionProcessor.java b/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/hosted/JNINativeCallWrapperSubstitutionProcessor.java index ff6f342c4314..7b5137d74310 100644 --- a/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/hosted/JNINativeCallWrapperSubstitutionProcessor.java +++ b/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/hosted/JNINativeCallWrapperSubstitutionProcessor.java @@ -29,6 +29,7 @@ import com.oracle.graal.pointsto.infrastructure.SubstitutionProcessor; +import com.oracle.svm.jni.access.JNIAccessFeature; import jdk.vm.ci.meta.ResolvedJavaMethod; /** @@ -41,6 +42,13 @@ class JNINativeCallWrapperSubstitutionProcessor extends SubstitutionProcessor { @Override public ResolvedJavaMethod lookup(ResolvedJavaMethod method) { assert method.isNative() : "Must have been registered as a native substitution processor"; + if (method.getDeclaringClass().getName().equals("Lcom/oracle/svm/jni/JNIJavaCallWrappers;")) { + // Avoid generating JNINativeCallWrapperMethods for trampolines + JNICallTrampolineMethod callTrampolineMethod = JNIAccessFeature.singleton().getCallTrampolineMethod(method.getName()); + if (callTrampolineMethod != null) { + return callTrampolineMethod; + } + } return callWrappers.computeIfAbsent(method, JNINativeCallWrapperMethod::new); } From 74dca9ae57172f5840363b8336abbb390fb5fe28 Mon Sep 17 00:00:00 2001 From: Foivos Zakkak Date: Mon, 13 Dec 2021 16:23:40 +0200 Subject: [PATCH 3/7] Refactor: Don't generate 0-sized arrays for methods with no arguments --- .../objectfile/debugentry/ClassEntry.java | 18 +++++++++++------- .../objectfile/debugentry/MethodEntry.java | 4 ++-- .../oracle/objectfile/debugentry/Range.java | 13 ++++++++----- .../elf/dwarf/DwarfInfoSectionImpl.java | 3 +++ 4 files changed, 24 insertions(+), 14 deletions(-) diff --git a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/debugentry/ClassEntry.java b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/debugentry/ClassEntry.java index 643ad61ec936..fc21a324bf03 100644 --- a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/debugentry/ClassEntry.java +++ b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/debugentry/ClassEntry.java @@ -292,14 +292,18 @@ protected MethodEntry processMethod(DebugMethodInfo debugMethodInfo, DebugInfoBa debugContext.log("typename %s adding %s method %s %s(%s)\n", typeName, memberModifiers(modifiers), resultTypeName, methodName, formatParams(paramTypes, paramNames)); TypeEntry resultType = debugInfoBase.lookupTypeEntry(resultTypeName); - TypeEntry[] paramTypeArray = new TypeEntry[paramCount]; - String[] paramNameArray = new String[paramCount]; - int idx = 0; - for (String paramTypeName : paramTypes) { - TypeEntry paramType = debugInfoBase.lookupTypeEntry(TypeEntry.canonicalize(paramTypeName)); - paramTypeArray[idx++] = paramType; + TypeEntry[] paramTypeArray = null; + String[] paramNameArray = null; + if (paramCount != 0) { + paramTypeArray = new TypeEntry[paramCount]; + paramNameArray = new String[paramCount]; + int idx = 0; + for (String paramTypeName : paramTypes) { + TypeEntry paramType = debugInfoBase.lookupTypeEntry(TypeEntry.canonicalize(paramTypeName)); + paramTypeArray[idx++] = paramType; + } + paramNameArray = paramNames.toArray(paramNameArray); } - paramNameArray = paramNames.toArray(paramNameArray); /* * n.b. the method file may differ from the owning class file when the method is a * substitution diff --git a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/debugentry/MethodEntry.java b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/debugentry/MethodEntry.java index a5ab87a66717..3f1172b612d0 100644 --- a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/debugentry/MethodEntry.java +++ b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/debugentry/MethodEntry.java @@ -31,8 +31,8 @@ import com.oracle.objectfile.debuginfo.DebugInfoProvider.DebugMethodInfo; public class MethodEntry extends MemberEntry { - final TypeEntry[] paramTypes; - final String[] paramNames; + private final TypeEntry[] paramTypes; + private final String[] paramNames; static final int DEOPT = 1 << 0; static final int IN_RANGE = 1 << 1; static final int INLINED = 1 << 2; diff --git a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/debugentry/Range.java b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/debugentry/Range.java index c3f7e5ca594e..71d3674ae61c 100644 --- a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/debugentry/Range.java +++ b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/debugentry/Range.java @@ -182,11 +182,14 @@ private String getExtendedMethodName(boolean includeClass, boolean includeParams builder.append(getMethodName()); if (includeParams) { builder.append("("); - String prefix = ""; - for (TypeEntry t : methodEntry.paramTypes) { - builder.append(prefix); - builder.append(t.getTypeName()); - prefix = ", "; + TypeEntry[] paramTypes = methodEntry.getParamTypes(); + if (paramTypes != null) { + String prefix = ""; + for (TypeEntry t : paramTypes) { + builder.append(prefix); + builder.append(t.getTypeName()); + prefix = ", "; + } } builder.append(')'); } diff --git a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/elf/dwarf/DwarfInfoSectionImpl.java b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/elf/dwarf/DwarfInfoSectionImpl.java index 9a93f68fd374..b8341cf197de 100644 --- a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/elf/dwarf/DwarfInfoSectionImpl.java +++ b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/elf/dwarf/DwarfInfoSectionImpl.java @@ -737,6 +737,9 @@ private int writeMethodParameterDeclarations(DebugContext context, ClassEntry cl if (!Modifier.isStatic(method.getModifiers())) { pos = writeMethodParameterDeclaration(context, "this", classEntry.getTypeName(), true, isSpecification, buffer, pos); } + if (method.getParamTypes() == null) { + return pos; + } for (TypeEntry paramType : method.getParamTypes()) { String paramTypeName = paramType.getTypeName(); String paramName = uniqueDebugString(""); From 4737755d62df93680b49f6606d87b5aefac9baef Mon Sep 17 00:00:00 2001 From: Foivos Zakkak Date: Tue, 14 Dec 2021 10:29:17 +0200 Subject: [PATCH 4/7] fixup! Don't create JNINativeCallWrapperMethods for JNICallTrampolineMethods --- .../svm/jni/JNIJavaCallTrampolines.java | 76 +++++++++++++++++++ .../oracle/svm/jni/JNIJavaCallWrappers.java | 38 +--------- .../svm/jni/access/JNIAccessFeature.java | 17 ++--- ...ativeCallWrapperSubstitutionProcessor.java | 7 +- 4 files changed, 92 insertions(+), 46 deletions(-) create mode 100644 substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/JNIJavaCallTrampolines.java diff --git a/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/JNIJavaCallTrampolines.java b/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/JNIJavaCallTrampolines.java new file mode 100644 index 000000000000..41e2875e29be --- /dev/null +++ b/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/JNIJavaCallTrampolines.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.svm.jni; + +import com.oracle.svm.core.util.VMError; +import com.oracle.svm.jni.hosted.JNIJavaCallWrapperMethod; +import com.oracle.svm.jni.hosted.JNIJavaCallWrapperMethod.CallVariant; + +import jdk.vm.ci.meta.ConstantPool; +import jdk.vm.ci.meta.MetaAccessProvider; + +/** + * Holder class for generated {@link JNIJavaCallWrapperMethod} code. + */ +public final class JNIJavaCallTrampolines { + public static ConstantPool getConstantPool(MetaAccessProvider metaAccess) { + // Each generated call wrapper needs an actual constant pool, so we provide our + // private constructor's + return metaAccess.lookupJavaType(JNIJavaCallWrappers.class).getDeclaredConstructors()[0].getConstantPool(); + } + + public static String getTrampolineName(CallVariant variant, boolean nonVirtual) { + StringBuilder name = new StringBuilder(48); + if (variant == CallVariant.VARARGS) { + name.append("varargs"); + } else if (variant == CallVariant.ARRAY) { + name.append("array"); + } else if (variant == CallVariant.VA_LIST) { + name.append("valist"); + } else { + throw VMError.shouldNotReachHere(); + } + if (nonVirtual) { + name.append("Nonvirtual"); + } + name.append("JavaCallTrampoline"); + return name.toString(); + } + + private JNIJavaCallTrampolines() { + } + + private native void varargsJavaCallTrampoline(); + + private native void arrayJavaCallTrampoline(); + + private native void valistJavaCallTrampoline(); + + private native void varargsNonvirtualJavaCallTrampoline(); + + private native void arrayNonvirtualJavaCallTrampoline(); + + private native void valistNonvirtualJavaCallTrampoline(); +} diff --git a/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/JNIJavaCallWrappers.java b/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/JNIJavaCallWrappers.java index f0221e464a8d..cfa79ed072c6 100644 --- a/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/JNIJavaCallWrappers.java +++ b/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/JNIJavaCallWrappers.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,15 +24,13 @@ */ package com.oracle.svm.jni; -import com.oracle.svm.core.util.VMError; -import com.oracle.svm.jni.hosted.JNIJavaCallWrapperMethod; -import com.oracle.svm.jni.hosted.JNIJavaCallWrapperMethod.CallVariant; +import com.oracle.svm.jni.hosted.JNICallTrampolineMethod; import jdk.vm.ci.meta.ConstantPool; import jdk.vm.ci.meta.MetaAccessProvider; /** - * Holder class for generated {@link JNIJavaCallWrapperMethod} code. + * Holder class for generated {@link JNICallTrampolineMethod} code. */ public final class JNIJavaCallWrappers { public static ConstantPool getConstantPool(MetaAccessProvider metaAccess) { @@ -41,36 +39,6 @@ public static ConstantPool getConstantPool(MetaAccessProvider metaAccess) { return metaAccess.lookupJavaType(JNIJavaCallWrappers.class).getDeclaredConstructors()[0].getConstantPool(); } - public static String getTrampolineName(CallVariant variant, boolean nonVirtual) { - StringBuilder name = new StringBuilder(48); - if (variant == CallVariant.VARARGS) { - name.append("varargs"); - } else if (variant == CallVariant.ARRAY) { - name.append("array"); - } else if (variant == CallVariant.VA_LIST) { - name.append("valist"); - } else { - throw VMError.shouldNotReachHere(); - } - if (nonVirtual) { - name.append("Nonvirtual"); - } - name.append("JavaCallTrampoline"); - return name.toString(); - } - private JNIJavaCallWrappers() { } - - private native void varargsJavaCallTrampoline(); - - private native void arrayJavaCallTrampoline(); - - private native void valistJavaCallTrampoline(); - - private native void varargsNonvirtualJavaCallTrampoline(); - - private native void arrayNonvirtualJavaCallTrampoline(); - - private native void valistNonvirtualJavaCallTrampoline(); } diff --git a/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/access/JNIAccessFeature.java b/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/access/JNIAccessFeature.java index da292cd61153..4ec513213fef 100644 --- a/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/access/JNIAccessFeature.java +++ b/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/access/JNIAccessFeature.java @@ -28,6 +28,7 @@ import java.lang.reflect.Executable; import java.lang.reflect.Field; +import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.Arrays; import java.util.Collections; @@ -37,7 +38,8 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Stream; -import com.oracle.svm.core.util.VMError; +import com.oracle.svm.jni.JNIJavaCallTrampolines; +import com.oracle.svm.util.ReflectionUtil; import org.graalvm.compiler.api.replacements.Fold; import org.graalvm.compiler.options.Option; import org.graalvm.nativeimage.ImageSingletons; @@ -68,7 +70,6 @@ import com.oracle.svm.hosted.config.ConfigurationParserUtils; import com.oracle.svm.hosted.meta.MaterializedConstantFields; import com.oracle.svm.hosted.substitute.SubstitutionReflectivityFilter; -import com.oracle.svm.jni.JNIJavaCallWrappers; import com.oracle.svm.jni.JNISupport; import com.oracle.svm.jni.hosted.JNICallTrampolineMethod; import com.oracle.svm.jni.hosted.JNIFieldAccessorMethod; @@ -186,20 +187,16 @@ private void createJavaCallTrampoline(BeforeAnalysisAccessImpl access, CallVaria ResolvedJavaField field = JNIAccessibleMethod.getCallWrapperField(wrappedMetaAccess, variant, nonVirtual); access.getUniverse().lookup(field.getDeclaringClass()).registerAsReachable(); access.registerAsAccessed(access.getUniverse().lookup(field)); - String trampolineName = JNIJavaCallWrappers.getTrampolineName(variant, nonVirtual); - ResolvedJavaMethod method; - try { - method = wrappedMetaAccess.lookupJavaMethod(JNIJavaCallWrappers.class.getDeclaredMethod(trampolineName)); - } catch (NoSuchMethodException e) { - throw VMError.shouldNotReachHere(e); - } + 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); access.registerAsCompiled(access.getUniverse().lookup(trampoline)); trampolineMethods.put(trampolineName, trampoline); } public JNICallTrampolineMethod getCallTrampolineMethod(CallVariant variant, boolean nonVirtual) { - String trampolineName = JNIJavaCallWrappers.getTrampolineName(variant, nonVirtual); + String trampolineName = JNIJavaCallTrampolines.getTrampolineName(variant, nonVirtual); return getCallTrampolineMethod(trampolineName); } diff --git a/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/hosted/JNINativeCallWrapperSubstitutionProcessor.java b/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/hosted/JNINativeCallWrapperSubstitutionProcessor.java index 7b5137d74310..e968aafb7863 100644 --- a/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/hosted/JNINativeCallWrapperSubstitutionProcessor.java +++ b/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/hosted/JNINativeCallWrapperSubstitutionProcessor.java @@ -29,7 +29,9 @@ import com.oracle.graal.pointsto.infrastructure.SubstitutionProcessor; +import com.oracle.svm.jni.JNIJavaCallTrampolines; import com.oracle.svm.jni.access.JNIAccessFeature; +import jdk.vm.ci.meta.MetaUtil; import jdk.vm.ci.meta.ResolvedJavaMethod; /** @@ -42,7 +44,8 @@ class JNINativeCallWrapperSubstitutionProcessor extends SubstitutionProcessor { @Override public ResolvedJavaMethod lookup(ResolvedJavaMethod method) { assert method.isNative() : "Must have been registered as a native substitution processor"; - if (method.getDeclaringClass().getName().equals("Lcom/oracle/svm/jni/JNIJavaCallWrappers;")) { + 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) { @@ -56,6 +59,8 @@ public ResolvedJavaMethod lookup(ResolvedJavaMethod method) { public ResolvedJavaMethod resolve(ResolvedJavaMethod method) { if (method instanceof JNINativeCallWrapperMethod) { return ((JNINativeCallWrapperMethod) method).getOriginal(); + } else if (method instanceof JNICallTrampolineMethod) { + return ((JNICallTrampolineMethod) method).getOriginal(); } return method; } From 6a98c7c2d2de97f58a5a699318096fc87820a731 Mon Sep 17 00:00:00 2001 From: Foivos Zakkak Date: Tue, 21 Dec 2021 13:51:26 +0200 Subject: [PATCH 5/7] fixup! Don't create JNINativeCallWrapperMethods for JNICallTrampolineMethods --- .../svm/jni/JNIJavaCallTrampolines.java | 19 ++++++++++- .../svm/jni/access/JNIAccessFeature.java | 32 ++++++++++++++++--- .../svm/jni/hosted/JNICallWrapperFeature.java | 2 +- ...ativeCallWrapperSubstitutionProcessor.java | 12 ++++--- 4 files changed, 54 insertions(+), 11 deletions(-) diff --git a/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/JNIJavaCallTrampolines.java b/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/JNIJavaCallTrampolines.java index 41e2875e29be..58a571ac8a58 100644 --- a/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/JNIJavaCallTrampolines.java +++ b/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/JNIJavaCallTrampolines.java @@ -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) { @@ -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(); diff --git a/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/access/JNIAccessFeature.java b/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/access/JNIAccessFeature.java index 4ec513213fef..7061d0bad371 100644 --- a/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/access/JNIAccessFeature.java +++ b/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/access/JNIAccessFeature.java @@ -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; @@ -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) { @@ -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", diff --git a/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/hosted/JNICallWrapperFeature.java b/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/hosted/JNICallWrapperFeature.java index 4f2eec53caef..d64f1ed0c0a2 100644 --- a/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/hosted/JNICallWrapperFeature.java +++ b/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/hosted/JNICallWrapperFeature.java @@ -74,6 +74,6 @@ public List> getRequiredFeatures() { @Override public void duringSetup(DuringSetupAccess access) { DuringSetupAccessImpl config = (DuringSetupAccessImpl) access; - config.registerNativeSubstitutionProcessor(new JNINativeCallWrapperSubstitutionProcessor()); + config.registerNativeSubstitutionProcessor(new JNINativeCallWrapperSubstitutionProcessor(config)); } } diff --git a/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/hosted/JNINativeCallWrapperSubstitutionProcessor.java b/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/hosted/JNINativeCallWrapperSubstitutionProcessor.java index e968aafb7863..fe53c3fbf9ae 100644 --- a/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/hosted/JNINativeCallWrapperSubstitutionProcessor.java +++ b/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/hosted/JNINativeCallWrapperSubstitutionProcessor.java @@ -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; @@ -40,6 +41,12 @@ */ class JNINativeCallWrapperSubstitutionProcessor extends SubstitutionProcessor { private final Map callWrappers = new ConcurrentHashMap<>(); + private final DuringSetupAccessImpl access; + + JNINativeCallWrapperSubstitutionProcessor(DuringSetupAccessImpl access) { + super(); + this.access = access; + } @Override public ResolvedJavaMethod lookup(ResolvedJavaMethod method) { @@ -47,10 +54,7 @@ public ResolvedJavaMethod lookup(ResolvedJavaMethod method) { 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); } From 7554ca1c78545be6240919583c28b887e89e6417 Mon Sep 17 00:00:00 2001 From: Foivos Zakkak Date: Thu, 23 Dec 2021 16:05:01 +0200 Subject: [PATCH 6/7] fixup! Don't create JNINativeCallWrapperMethods for JNICallTrampolineMethods --- .../svm/jni/JNIJavaCallTrampolines.java | 8 -------- .../svm/jni/access/JNIAccessFeature.java | 19 +++++++++---------- ...ativeCallWrapperSubstitutionProcessor.java | 10 +++++----- 3 files changed, 14 insertions(+), 23 deletions(-) diff --git a/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/JNIJavaCallTrampolines.java b/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/JNIJavaCallTrampolines.java index 58a571ac8a58..da0e60266f81 100644 --- a/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/JNIJavaCallTrampolines.java +++ b/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/JNIJavaCallTrampolines.java @@ -28,18 +28,10 @@ import com.oracle.svm.jni.hosted.JNIJavaCallWrapperMethod; import com.oracle.svm.jni.hosted.JNIJavaCallWrapperMethod.CallVariant; -import jdk.vm.ci.meta.ConstantPool; -import jdk.vm.ci.meta.MetaAccessProvider; - /** * Holder class for generated {@link JNIJavaCallWrapperMethod} code. */ public final class JNIJavaCallTrampolines { - public static ConstantPool getConstantPool(MetaAccessProvider metaAccess) { - // Each generated call wrapper needs an actual constant pool, so we provide our - // private constructor's - return metaAccess.lookupJavaType(JNIJavaCallWrappers.class).getDeclaredConstructors()[0].getConstantPool(); - } private JNIJavaCallTrampolines() { } diff --git a/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/access/JNIAccessFeature.java b/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/access/JNIAccessFeature.java index 7061d0bad371..c650d94b9533 100644 --- a/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/access/JNIAccessFeature.java +++ b/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/access/JNIAccessFeature.java @@ -169,12 +169,12 @@ public void beforeAnalysis(BeforeAnalysisAccess arg) { BeforeAnalysisAccessImpl access = (BeforeAnalysisAccessImpl) arg; this.nativeLibraries = access.getNativeLibraries(); - createJavaCallTrampoline(access, CallVariant.VARARGS, false); - createJavaCallTrampoline(access, CallVariant.ARRAY, false); - createJavaCallTrampoline(access, CallVariant.VA_LIST, false); - createJavaCallTrampoline(access, CallVariant.VARARGS, true); - createJavaCallTrampoline(access, CallVariant.ARRAY, true); - createJavaCallTrampoline(access, CallVariant.VA_LIST, true); + registerJavaCallTrampoline(access, CallVariant.VARARGS, false); + registerJavaCallTrampoline(access, CallVariant.ARRAY, false); + registerJavaCallTrampoline(access, CallVariant.VA_LIST, false); + registerJavaCallTrampoline(access, CallVariant.VARARGS, true); + registerJavaCallTrampoline(access, CallVariant.ARRAY, true); + registerJavaCallTrampoline(access, CallVariant.VA_LIST, true); /* duplicated to reduce the number of analysis iterations */ getConditionalConfigurationRegistry().flushConditionalConfiguration(access); @@ -184,7 +184,7 @@ private static ConditionalConfigurationRegistry getConditionalConfigurationRegis return (ConditionalConfigurationRegistry) ImageSingletons.lookup(JNIRuntimeAccess.JNIRuntimeAccessibilitySupport.class); } - private void createJavaCallTrampoline(BeforeAnalysisAccessImpl access, CallVariant variant, boolean nonVirtual) { + private static void registerJavaCallTrampoline(BeforeAnalysisAccessImpl access, CallVariant variant, boolean nonVirtual) { AnalysisMetaAccess metaAccess = access.getMetaAccess(); ResolvedJavaField field = JNIAccessibleMethod.getCallWrapperField(metaAccess.getWrapped(), variant, nonVirtual); access.getUniverse().lookup(field.getDeclaringClass()).registerAsReachable(); @@ -193,9 +193,8 @@ private void createJavaCallTrampoline(BeforeAnalysisAccessImpl access, CallVaria Method reflectionMethod = ReflectionUtil.lookupMethod(JNIJavaCallTrampolines.class, trampolineName); // 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)); + AnalysisMethod trampoline = metaAccess.lookupJavaMethod(reflectionMethod); + access.registerAsCompiled(trampoline); } public JNICallTrampolineMethod getCallTrampolineMethod(CallVariant variant, boolean nonVirtual) { diff --git a/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/hosted/JNINativeCallWrapperSubstitutionProcessor.java b/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/hosted/JNINativeCallWrapperSubstitutionProcessor.java index fe53c3fbf9ae..17267b59fda6 100644 --- a/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/hosted/JNINativeCallWrapperSubstitutionProcessor.java +++ b/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/hosted/JNINativeCallWrapperSubstitutionProcessor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,8 +32,8 @@ 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; import jdk.vm.ci.meta.ResolvedJavaMethod; +import jdk.vm.ci.meta.ResolvedJavaType; /** * Substitutes methods declared as {@code native} with {@link JNINativeCallWrapperMethod} instances @@ -42,17 +42,17 @@ class JNINativeCallWrapperSubstitutionProcessor extends SubstitutionProcessor { private final Map callWrappers = new ConcurrentHashMap<>(); private final DuringSetupAccessImpl access; + private final ResolvedJavaType jniJavaCallTrampolinesType; JNINativeCallWrapperSubstitutionProcessor(DuringSetupAccessImpl access) { - super(); this.access = access; + this.jniJavaCallTrampolinesType = access.getMetaAccess().lookupJavaType(JNIJavaCallTrampolines.class).getWrapped(); } @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)) { + if (method.getDeclaringClass() == jniJavaCallTrampolinesType) { // Avoid generating JNINativeCallWrapperMethods for trampolines return JNIAccessFeature.singleton().getOrCreateCallTrampolineMethod(access, method.getName()); } From 691ecc4a1bc7543819e25b61647eeb63403aa811 Mon Sep 17 00:00:00 2001 From: Foivos Zakkak Date: Thu, 23 Dec 2021 16:10:49 +0200 Subject: [PATCH 7/7] fixup! Don't create JNINativeCallWrapperMethods for JNICallTrampolineMethods --- .../svm/jni/access/JNIAccessFeature.java | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/access/JNIAccessFeature.java b/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/access/JNIAccessFeature.java index c650d94b9533..d4cf2b3c0b15 100644 --- a/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/access/JNIAccessFeature.java +++ b/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/access/JNIAccessFeature.java @@ -189,30 +189,30 @@ private static void registerJavaCallTrampoline(BeforeAnalysisAccessImpl access, 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); + String name = JNIJavaCallTrampolines.getTrampolineName(variant, nonVirtual); + Method method = ReflectionUtil.lookupMethod(JNIJavaCallTrampolines.class, name); // Look up the java method to ensure a JNICallTrampolineMethod gets created for it through // com.oracle.svm.jni.hosted.JNINativeCallWrapperSubstitutionProcessor.lookup - AnalysisMethod trampoline = metaAccess.lookupJavaMethod(reflectionMethod); + AnalysisMethod trampoline = metaAccess.lookupJavaMethod(method); access.registerAsCompiled(trampoline); } public JNICallTrampolineMethod getCallTrampolineMethod(CallVariant variant, boolean nonVirtual) { - String trampolineName = JNIJavaCallTrampolines.getTrampolineName(variant, nonVirtual); - return getCallTrampolineMethod(trampolineName); + String name = JNIJavaCallTrampolines.getTrampolineName(variant, nonVirtual); + return getCallTrampolineMethod(name); } public JNICallTrampolineMethod getCallTrampolineMethod(String javaTrampolineName) { - JNICallTrampolineMethod jniCallTrampolineMethod = trampolineMethods.get(javaTrampolineName); - assert jniCallTrampolineMethod != null; - return jniCallTrampolineMethod; + JNICallTrampolineMethod trampoline = trampolineMethods.get(javaTrampolineName); + assert trampoline != null; + return trampoline; } public JNICallTrampolineMethod getOrCreateCallTrampolineMethod(DuringSetupAccessImpl access, String trampolineName) { - JNICallTrampolineMethod jniCallTrampolineMethod = trampolineMethods.get(trampolineName); + JNICallTrampolineMethod trampoline = trampolineMethods.get(trampolineName); - if (jniCallTrampolineMethod != null) { - return jniCallTrampolineMethod; + if (trampoline != null) { + return trampoline; } MetaAccessProvider wrappedMetaAccess = access.getMetaAccess().getWrapped(); @@ -222,7 +222,7 @@ public JNICallTrampolineMethod getOrCreateCallTrampolineMethod(DuringSetupAccess // 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); + trampoline = new JNICallTrampolineMethod(method, field, nonVirtual); trampolineMethods.put(trampolineName, trampoline); return trampoline; }