Skip to content

Commit 011a661

Browse files
committed
Trace reflective accesses
1 parent 9acd1b0 commit 011a661

File tree

4 files changed

+95
-2
lines changed

4 files changed

+95
-2
lines changed

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/SubstrateAllocationSnippets.java

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import static jdk.graal.compiler.nodes.extended.BranchProbabilityNode.EXTREMELY_FAST_PATH_PROBABILITY;
3131
import static jdk.graal.compiler.nodes.extended.BranchProbabilityNode.FAST_PATH_PROBABILITY;
3232
import static jdk.graal.compiler.nodes.extended.BranchProbabilityNode.LIKELY_PROBABILITY;
33+
import static jdk.graal.compiler.nodes.extended.BranchProbabilityNode.SLOW_PATH_PROBABILITY;
3334
import static jdk.graal.compiler.nodes.extended.BranchProbabilityNode.probability;
3435
import static jdk.graal.compiler.replacements.SnippetTemplate.DEFAULT_REPLACER;
3536

@@ -59,6 +60,7 @@
5960
import com.oracle.svm.core.hub.RuntimeClassLoading;
6061
import com.oracle.svm.core.identityhashcode.IdentityHashCodeSupport;
6162
import com.oracle.svm.core.meta.SharedType;
63+
import com.oracle.svm.core.metadata.MetadataTracer;
6264
import com.oracle.svm.core.option.HostedOptionValues;
6365
import com.oracle.svm.core.reflect.MissingReflectionRegistrationUtils;
6466
import com.oracle.svm.core.snippets.SnippetRuntime;
@@ -126,8 +128,11 @@ public class SubstrateAllocationSnippets extends AllocationSnippets {
126128
private static final SubstrateForeignCallDescriptor NEW_MULTI_ARRAY = SnippetRuntime.findForeignCall(SubstrateAllocationSnippets.class, "newMultiArrayStub", NO_SIDE_EFFECT);
127129
private static final SubstrateForeignCallDescriptor SLOW_PATH_HUB_OR_UNSAFE_INSTANTIATE_ERROR = SnippetRuntime.findForeignCall(SubstrateAllocationSnippets.class,
128130
"slowPathHubOrUnsafeInstantiationError", NO_SIDE_EFFECT);
131+
132+
private static final SubstrateForeignCallDescriptor TRACE_ARRAY_HUB = SnippetRuntime.findForeignCall(SubstrateAllocationSnippets.class, "traceArrayHubStub", NO_SIDE_EFFECT);
129133
private static final SubstrateForeignCallDescriptor ARRAY_HUB_ERROR = SnippetRuntime.findForeignCall(SubstrateAllocationSnippets.class, "arrayHubErrorStub", NO_SIDE_EFFECT);
130-
private static final SubstrateForeignCallDescriptor[] FOREIGN_CALLS = new SubstrateForeignCallDescriptor[]{NEW_MULTI_ARRAY, SLOW_PATH_HUB_OR_UNSAFE_INSTANTIATE_ERROR, ARRAY_HUB_ERROR};
134+
private static final SubstrateForeignCallDescriptor[] FOREIGN_CALLS = new SubstrateForeignCallDescriptor[]{NEW_MULTI_ARRAY, SLOW_PATH_HUB_OR_UNSAFE_INSTANTIATE_ERROR, TRACE_ARRAY_HUB,
135+
ARRAY_HUB_ERROR};
131136

132137
public void registerForeignCalls(SubstrateForeignCallsProvider foreignCalls) {
133138
foreignCalls.register(FOREIGN_CALLS);
@@ -365,6 +370,12 @@ private static DynamicHub getCheckedArrayHub(DynamicHub elementType) {
365370
if (probability(EXTREMELY_FAST_PATH_PROBABILITY, arrayHub != null)) {
366371
DynamicHub nonNullArrayHub = (DynamicHub) PiNode.piCastNonNull(arrayHub, SnippetAnchorNode.anchor());
367372
if (probability(EXTREMELY_FAST_PATH_PROBABILITY, nonNullArrayHub.isInstantiated())) {
373+
if (MetadataTracer.Options.MetadataTracingSupport.getValue()) {
374+
Class<?> clazz = DynamicHub.toClass(elementType);
375+
if (!clazz.isPrimitive()) {
376+
callTraceArrayHubStub(TRACE_ARRAY_HUB, clazz);
377+
}
378+
}
368379
return nonNullArrayHub;
369380
}
370381
}
@@ -374,6 +385,18 @@ private static DynamicHub getCheckedArrayHub(DynamicHub elementType) {
374385
throw UnreachableNode.unreachable();
375386
}
376387

388+
@NodeIntrinsic(value = ForeignCallNode.class)
389+
private static native void callTraceArrayHubStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Class<?> elementType);
390+
391+
/** Foreign call: {@link #TRACE_ARRAY_HUB}. */
392+
@SubstrateForeignCallTarget(stubCallingConvention = true)
393+
private static void traceArrayHubStub(DynamicHub elementType) {
394+
assert MetadataTracer.Options.MetadataTracingSupport.getValue();
395+
if (probability(SLOW_PATH_PROBABILITY, MetadataTracer.singleton().enabled())) {
396+
MetadataTracer.singleton().traceReflectionType(elementType.getName());
397+
}
398+
}
399+
377400
@NodeIntrinsic(value = ForeignCallNode.class)
378401
private static native void callArrayHubErrorStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Class<?> elementType);
379402

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/ClassForNameSupport.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonSupport;
4444
import com.oracle.svm.core.layeredimagesingleton.MultiLayeredImageSingleton;
4545
import com.oracle.svm.core.layeredimagesingleton.UnsavedSingleton;
46+
import com.oracle.svm.core.metadata.MetadataTracer;
4647
import com.oracle.svm.core.reflect.MissingReflectionRegistrationUtils;
4748
import com.oracle.svm.core.util.ImageHeapMap;
4849
import com.oracle.svm.core.util.VMError;
@@ -231,6 +232,9 @@ private static Class<?> forName(String className, ClassLoader classLoader, boole
231232

232233
private Object forName0(String className, ClassLoader classLoader) {
233234
var conditional = knownClasses.get(className);
235+
if (MetadataTracer.Options.MetadataTracingSupport.getValue() && conditional != null && MetadataTracer.singleton().enabled()) {
236+
MetadataTracer.singleton().traceReflectionType(className);
237+
}
234238
Object result = conditional == null ? null : conditional.getValue();
235239
if (result == NEGATIVE_QUERY || className.endsWith("[]")) {
236240
/* Querying array classes with their "TypeName[]" name always throws */
@@ -276,7 +280,13 @@ public static boolean canUnsafeInstantiateAsInstance(DynamicHub hub) {
276280
break;
277281
}
278282
}
279-
return conditionSet != null && conditionSet.satisfied();
283+
if (conditionSet != null) {
284+
if (MetadataTracer.Options.MetadataTracingSupport.getValue() && MetadataTracer.singleton().enabled()) {
285+
MetadataTracer.singleton().traceReflectionType(clazz.getName()).setUnsafeAllocated();
286+
}
287+
return conditionSet.satisfied();
288+
}
289+
return false;
280290
}
281291

282292
@Override

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/DynamicHub.java

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
*/
2525
package com.oracle.svm.core.hub;
2626

27+
import static com.oracle.svm.configure.config.ConfigurationMemberInfo.ConfigurationMemberAccessibility;
28+
import static com.oracle.svm.configure.config.ConfigurationMemberInfo.ConfigurationMemberDeclaration;
2729
import static com.oracle.svm.core.MissingRegistrationUtils.throwMissingRegistrationErrors;
2830
import static com.oracle.svm.core.Uninterruptible.CALLED_FROM_UNINTERRUPTIBLE_CODE;
2931
import static com.oracle.svm.core.annotate.TargetElement.CONSTRUCTOR_NAME;
@@ -86,6 +88,7 @@
8688
import org.graalvm.nativeimage.Platforms;
8789
import org.graalvm.nativeimage.c.function.CFunctionPointer;
8890

91+
import com.oracle.svm.configure.config.ConfigurationType;
8992
import com.oracle.svm.core.BuildPhaseProvider.AfterHostedUniverse;
9093
import com.oracle.svm.core.BuildPhaseProvider.CompileQueueFinished;
9194
import com.oracle.svm.core.NeverInline;
@@ -116,6 +119,7 @@
116119
import com.oracle.svm.core.jdk.ProtectionDomainSupport;
117120
import com.oracle.svm.core.jdk.Resources;
118121
import com.oracle.svm.core.meta.SharedType;
122+
import com.oracle.svm.core.metadata.MetadataTracer;
119123
import com.oracle.svm.core.reflect.MissingReflectionRegistrationUtils;
120124
import com.oracle.svm.core.reflect.RuntimeMetadataDecoder;
121125
import com.oracle.svm.core.reflect.RuntimeMetadataDecoder.ConstructorDescriptor;
@@ -143,6 +147,7 @@
143147
import jdk.internal.reflect.FieldAccessor;
144148
import jdk.internal.reflect.Reflection;
145149
import jdk.internal.reflect.ReflectionFactory;
150+
import jdk.vm.ci.meta.MetaUtil;
146151
import jdk.vm.ci.meta.ResolvedJavaType;
147152
import sun.reflect.annotation.AnnotationType;
148153
import sun.reflect.generics.factory.GenericsFactory;
@@ -694,6 +699,9 @@ private ReflectionMetadata reflectionMetadata() {
694699
}
695700

696701
private void checkClassFlag(int mask, String methodName) {
702+
if (MetadataTracer.Options.MetadataTracingSupport.getValue() && MetadataTracer.singleton().enabled()) {
703+
traceClassFlagQuery(mask);
704+
}
697705
if (throwMissingRegistrationErrors() && !(isClassFlagSet(mask) && getConditions().satisfied())) {
698706
MissingReflectionRegistrationUtils.forBulkQuery(DynamicHub.toClass(this), methodName);
699707
}
@@ -703,6 +711,25 @@ private boolean isClassFlagSet(int mask) {
703711
return (reflectionMetadata() != null && (reflectionMetadata().classFlags & mask) != 0);
704712
}
705713

714+
private void traceClassFlagQuery(int mask) {
715+
ConfigurationType type = MetadataTracer.singleton().traceReflectionType(getName());
716+
switch (mask) {
717+
case ALL_FIELDS_FLAG -> type.setAllPublicFields(ConfigurationMemberAccessibility.ACCESSED);
718+
case ALL_DECLARED_FIELDS_FLAG -> type.setAllDeclaredFields(ConfigurationMemberAccessibility.ACCESSED);
719+
case ALL_METHODS_FLAG -> type.setAllPublicMethods(ConfigurationMemberAccessibility.QUERIED);
720+
case ALL_DECLARED_METHODS_FLAG -> type.setAllDeclaredMethods(ConfigurationMemberAccessibility.QUERIED);
721+
case ALL_CONSTRUCTORS_FLAG -> type.setAllPublicConstructors(ConfigurationMemberAccessibility.QUERIED);
722+
case ALL_DECLARED_CONSTRUCTORS_FLAG -> type.setAllDeclaredConstructors(ConfigurationMemberAccessibility.QUERIED);
723+
case ALL_CLASSES_FLAG -> type.setAllPublicClasses();
724+
case ALL_DECLARED_CLASSES_FLAG -> type.setAllDeclaredClasses();
725+
case ALL_RECORD_COMPONENTS_FLAG -> type.setAllRecordComponents();
726+
case ALL_PERMITTED_SUBCLASSES_FLAG -> type.setAllPermittedSubclasses();
727+
case ALL_NEST_MEMBERS_FLAG -> type.setAllNestMembers();
728+
case ALL_SIGNERS_FLAG -> type.setAllSigners();
729+
default -> throw VMError.shouldNotReachHere("unknown class flag " + mask);
730+
}
731+
}
732+
706733
/** Executed at runtime. */
707734
private static Object initEnumConstantsAtRuntime(Method values) {
708735
try {
@@ -1261,6 +1288,14 @@ private void checkField(String fieldName, Field field, boolean publicOnly) throw
12611288
*/
12621289
throw new NoSuchFieldException(fieldName);
12631290
} else {
1291+
if (MetadataTracer.Options.MetadataTracingSupport.getValue() && MetadataTracer.singleton().enabled()) {
1292+
ConfigurationMemberDeclaration declaration = publicOnly ? ConfigurationMemberDeclaration.PRESENT : ConfigurationMemberDeclaration.DECLARED;
1293+
// register declaring type and field
1294+
ConfigurationType declaringType = MetadataTracer.singleton().traceReflectionType(field.getDeclaringClass().getName());
1295+
declaringType.addField(fieldName, declaration, false);
1296+
// register receiver type
1297+
MetadataTracer.singleton().traceReflectionType(getName());
1298+
}
12641299
RuntimeMetadataDecoder decoder = ImageSingletons.lookup(RuntimeMetadataDecoder.class);
12651300
int fieldModifiers = field.getModifiers();
12661301
boolean negative = decoder.isNegative(fieldModifiers);
@@ -1328,13 +1363,31 @@ private boolean checkExecutableExists(String methodName, Class<?>[] parameterTyp
13281363
int methodModifiers = method.getModifiers();
13291364
boolean negative = decoder.isNegative(methodModifiers);
13301365
boolean hiding = decoder.isHiding(methodModifiers);
1366+
if (MetadataTracer.Options.MetadataTracingSupport.getValue() && MetadataTracer.singleton().enabled()) {
1367+
ConfigurationMemberDeclaration declaration = publicOnly ? ConfigurationMemberDeclaration.PRESENT : ConfigurationMemberDeclaration.DECLARED;
1368+
// register declaring type and method
1369+
ConfigurationType declaringType = MetadataTracer.singleton().traceReflectionType(method.getDeclaringClass().getName());
1370+
declaringType.addMethod(methodName, toInternalSignature(parameterTypes), declaration);
1371+
// register receiver type
1372+
MetadataTracer.singleton().traceReflectionType(getName());
1373+
}
13311374
if (throwMissingErrors && hiding) {
13321375
MissingReflectionRegistrationUtils.forMethod(clazz, methodName, parameterTypes);
13331376
}
13341377
return !(negative || hiding);
13351378
}
13361379
}
13371380

1381+
private static String toInternalSignature(Class<?>[] classes) {
1382+
StringBuilder sb = new StringBuilder("(");
1383+
if (classes != null) {
1384+
for (Class<?> clazz : classes) {
1385+
sb.append(MetaUtil.toInternalName(clazz.getName()));
1386+
}
1387+
}
1388+
return sb.append(')').toString();
1389+
}
1390+
13381391
private boolean allElementsRegistered(boolean publicOnly, int allDeclaredElementsFlag, int allPublicElementsFlag) {
13391392
return isClassFlagSet(allDeclaredElementsFlag) || (publicOnly && isClassFlagSet(allPublicElementsFlag));
13401393
}
@@ -1824,6 +1877,8 @@ public DynamicHub arrayType() {
18241877
}
18251878
if (companion.arrayHub == null) {
18261879
MissingReflectionRegistrationUtils.forClass(getTypeName() + "[]");
1880+
} else if (MetadataTracer.Options.MetadataTracingSupport.getValue() && MetadataTracer.singleton().enabled() && !isPrimitive()) {
1881+
MetadataTracer.singleton().traceReflectionType(companion.arrayHub.getTypeName());
18271882
}
18281883
return companion.arrayHub;
18291884
}

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/metadata/MetadataTracer.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,11 @@ public boolean enabled() {
8080
return config != null;
8181
}
8282

83+
public ConfigurationType traceReflectionType(String className) {
84+
assert enabled();
85+
return config.getReflectionConfiguration().getOrCreateType(UnresolvedConfigurationCondition.alwaysTrue(), className);
86+
}
87+
8388
public ConfigurationType traceJNIType(String className) {
8489
assert enabled();
8590
return config.getJniConfiguration().getOrCreateType(UnresolvedConfigurationCondition.alwaysTrue(), className);

0 commit comments

Comments
 (0)