Skip to content

Commit 9184657

Browse files
committed
Trace reflective accesses
1 parent ffbdedc commit 9184657

File tree

4 files changed

+96
-2
lines changed

4 files changed

+96
-2
lines changed

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

Lines changed: 21 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;
@@ -127,8 +129,11 @@ public class SubstrateAllocationSnippets extends AllocationSnippets {
127129
private static final SubstrateForeignCallDescriptor NEW_MULTI_ARRAY = SnippetRuntime.findForeignCall(SubstrateAllocationSnippets.class, "newMultiArrayStub", NO_SIDE_EFFECT);
128130
private static final SubstrateForeignCallDescriptor SLOW_PATH_HUB_OR_UNSAFE_INSTANTIATE_ERROR = SnippetRuntime.findForeignCall(SubstrateAllocationSnippets.class,
129131
"slowPathHubOrUnsafeInstantiationError", NO_SIDE_EFFECT);
132+
133+
private static final SubstrateForeignCallDescriptor TRACE_ARRAY_HUB = SnippetRuntime.findForeignCall(SubstrateAllocationSnippets.class, "traceArrayHubStub", NO_SIDE_EFFECT);
130134
private static final SubstrateForeignCallDescriptor ARRAY_HUB_ERROR = SnippetRuntime.findForeignCall(SubstrateAllocationSnippets.class, "arrayHubErrorStub", NO_SIDE_EFFECT);
131-
private static final SubstrateForeignCallDescriptor[] FOREIGN_CALLS = new SubstrateForeignCallDescriptor[]{NEW_MULTI_ARRAY, SLOW_PATH_HUB_OR_UNSAFE_INSTANTIATE_ERROR, ARRAY_HUB_ERROR};
135+
private static final SubstrateForeignCallDescriptor[] FOREIGN_CALLS = new SubstrateForeignCallDescriptor[]{NEW_MULTI_ARRAY, SLOW_PATH_HUB_OR_UNSAFE_INSTANTIATE_ERROR, TRACE_ARRAY_HUB,
136+
ARRAY_HUB_ERROR};
132137

133138
public void registerForeignCalls(SubstrateForeignCallsProvider foreignCalls) {
134139
foreignCalls.register(FOREIGN_CALLS);
@@ -396,6 +401,9 @@ private static DynamicHub getCheckedArrayHub(DynamicHub elementType) {
396401
if (probability(EXTREMELY_FAST_PATH_PROBABILITY, arrayHub != null)) {
397402
DynamicHub nonNullArrayHub = (DynamicHub) PiNode.piCastNonNull(arrayHub, SnippetAnchorNode.anchor());
398403
if (probability(EXTREMELY_FAST_PATH_PROBABILITY, nonNullArrayHub.isInstantiated())) {
404+
if (MetadataTracer.Options.MetadataTracingSupport.getValue()) {
405+
callTraceArrayHubStub(TRACE_ARRAY_HUB, DynamicHub.toClass(elementType));
406+
}
399407
return nonNullArrayHub;
400408
}
401409
}
@@ -405,6 +413,18 @@ private static DynamicHub getCheckedArrayHub(DynamicHub elementType) {
405413
throw UnreachableNode.unreachable();
406414
}
407415

416+
@NodeIntrinsic(value = ForeignCallNode.class)
417+
private static native void callTraceArrayHubStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Class<?> elementType);
418+
419+
/** Foreign call: {@link #TRACE_ARRAY_HUB}. */
420+
@SubstrateForeignCallTarget(stubCallingConvention = true)
421+
private static void traceArrayHubStub(DynamicHub elementType) {
422+
assert MetadataTracer.Options.MetadataTracingSupport.getValue();
423+
if (probability(SLOW_PATH_PROBABILITY, MetadataTracer.singleton().enabled())) {
424+
MetadataTracer.singleton().traceReflectionType(elementType.getName());
425+
}
426+
}
427+
408428
@NodeIntrinsic(value = ForeignCallNode.class)
409429
private static native void callArrayHubErrorStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Class<?> elementType);
410430

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
@@ -44,6 +44,7 @@
4444
import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonSupport;
4545
import com.oracle.svm.core.layeredimagesingleton.MultiLayeredImageSingleton;
4646
import com.oracle.svm.core.layeredimagesingleton.UnsavedSingleton;
47+
import com.oracle.svm.core.metadata.MetadataTracer;
4748
import com.oracle.svm.core.reflect.MissingReflectionRegistrationUtils;
4849
import com.oracle.svm.core.util.ImageHeapMap;
4950
import com.oracle.svm.core.util.VMError;
@@ -237,6 +238,9 @@ private static Class<?> forName(String className, ClassLoader classLoader, boole
237238

238239
private Object forName0(String className, ClassLoader classLoader) {
239240
var conditional = knownClasses.get(className);
241+
if (MetadataTracer.Options.MetadataTracingSupport.getValue() && conditional != null && MetadataTracer.singleton().enabled()) {
242+
MetadataTracer.singleton().traceReflectionType(className);
243+
}
240244
Object result = conditional == null ? null : conditional.getValue();
241245
if (className.endsWith("[]")) {
242246
/* Querying array classes with their "TypeName[]" name always throws */
@@ -296,7 +300,13 @@ public static boolean canUnsafeInstantiateAsInstance(DynamicHub hub) {
296300
break;
297301
}
298302
}
299-
return conditionSet != null && conditionSet.satisfied();
303+
if (conditionSet != null) {
304+
if (MetadataTracer.Options.MetadataTracingSupport.getValue() && MetadataTracer.singleton().enabled()) {
305+
MetadataTracer.singleton().traceReflectionType(clazz.getName()).setUnsafeAllocated();
306+
}
307+
return conditionSet.satisfied();
308+
}
309+
return false;
300310
}
301311

302312
@Override

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

Lines changed: 58 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;
@@ -89,6 +91,8 @@
8991
import org.graalvm.nativeimage.Platforms;
9092
import org.graalvm.word.WordBase;
9193

94+
import com.oracle.svm.configure.config.ConfigurationType;
95+
import com.oracle.svm.configure.config.SignatureUtil;
9296
import com.oracle.svm.core.BuildPhaseProvider.AfterHostedUniverse;
9397
import com.oracle.svm.core.BuildPhaseProvider.CompileQueueFinished;
9498
import com.oracle.svm.core.NeverInline;
@@ -116,6 +120,7 @@
116120
import com.oracle.svm.core.jdk.ProtectionDomainSupport;
117121
import com.oracle.svm.core.jdk.Resources;
118122
import com.oracle.svm.core.meta.SharedType;
123+
import com.oracle.svm.core.metadata.MetadataTracer;
119124
import com.oracle.svm.core.reflect.MissingReflectionRegistrationUtils;
120125
import com.oracle.svm.core.reflect.RuntimeMetadataDecoder;
121126
import com.oracle.svm.core.reflect.RuntimeMetadataDecoder.ConstructorDescriptor;
@@ -698,6 +703,9 @@ private ReflectionMetadata reflectionMetadata() {
698703
}
699704

700705
private void checkClassFlag(int mask, String methodName) {
706+
if (MetadataTracer.Options.MetadataTracingSupport.getValue() && MetadataTracer.singleton().enabled()) {
707+
traceClassFlagQuery(mask);
708+
}
701709
if (throwMissingRegistrationErrors() && !(isClassFlagSet(mask) && getConditions().satisfied())) {
702710
MissingReflectionRegistrationUtils.forBulkQuery(DynamicHub.toClass(this), methodName);
703711
}
@@ -720,6 +728,25 @@ private static boolean isClassFlagSet(int mask, ReflectionMetadata reflectionMet
720728
return reflectionMetadata != null && (reflectionMetadata.classFlags & mask) != 0;
721729
}
722730

731+
private void traceClassFlagQuery(int mask) {
732+
ConfigurationType type = MetadataTracer.singleton().traceReflectionType(getName());
733+
switch (mask) {
734+
case ALL_FIELDS_FLAG -> type.setAllPublicFields(ConfigurationMemberAccessibility.ACCESSED);
735+
case ALL_DECLARED_FIELDS_FLAG -> type.setAllDeclaredFields(ConfigurationMemberAccessibility.ACCESSED);
736+
case ALL_METHODS_FLAG -> type.setAllPublicMethods(ConfigurationMemberAccessibility.ACCESSED);
737+
case ALL_DECLARED_METHODS_FLAG -> type.setAllDeclaredMethods(ConfigurationMemberAccessibility.ACCESSED);
738+
case ALL_CONSTRUCTORS_FLAG -> type.setAllPublicConstructors(ConfigurationMemberAccessibility.ACCESSED);
739+
case ALL_DECLARED_CONSTRUCTORS_FLAG -> type.setAllDeclaredConstructors(ConfigurationMemberAccessibility.ACCESSED);
740+
case ALL_CLASSES_FLAG -> type.setAllPublicClasses();
741+
case ALL_DECLARED_CLASSES_FLAG -> type.setAllDeclaredClasses();
742+
case ALL_RECORD_COMPONENTS_FLAG -> type.setAllRecordComponents();
743+
case ALL_PERMITTED_SUBCLASSES_FLAG -> type.setAllPermittedSubclasses();
744+
case ALL_NEST_MEMBERS_FLAG -> type.setAllNestMembers();
745+
case ALL_SIGNERS_FLAG -> type.setAllSigners();
746+
default -> throw VMError.shouldNotReachHere("unknown class flag " + mask);
747+
}
748+
}
749+
723750
/** Executed at runtime. */
724751
private static Object initEnumConstantsAtRuntime(Method values) {
725752
try {
@@ -1286,6 +1313,14 @@ private void checkField(String fieldName, Field field, boolean publicOnly) throw
12861313
*/
12871314
throw new NoSuchFieldException(fieldName);
12881315
} else {
1316+
if (MetadataTracer.Options.MetadataTracingSupport.getValue() && MetadataTracer.singleton().enabled()) {
1317+
ConfigurationMemberDeclaration declaration = publicOnly ? ConfigurationMemberDeclaration.PRESENT : ConfigurationMemberDeclaration.DECLARED;
1318+
// register declaring type and field
1319+
ConfigurationType declaringType = MetadataTracer.singleton().traceReflectionType(field.getDeclaringClass().getName());
1320+
declaringType.addField(fieldName, declaration, false);
1321+
// register receiver type
1322+
MetadataTracer.singleton().traceReflectionType(getName());
1323+
}
12891324
RuntimeMetadataDecoder decoder = ImageSingletons.lookup(RuntimeMetadataDecoder.class);
12901325
int fieldModifiers = field.getModifiers();
12911326
boolean negative = decoder.isNegative(fieldModifiers);
@@ -1353,13 +1388,34 @@ private boolean checkExecutableExists(String methodName, Class<?>[] parameterTyp
13531388
int methodModifiers = method.getModifiers();
13541389
boolean negative = decoder.isNegative(methodModifiers);
13551390
boolean hiding = decoder.isHiding(methodModifiers);
1391+
if (MetadataTracer.Options.MetadataTracingSupport.getValue() && MetadataTracer.singleton().enabled()) {
1392+
ConfigurationMemberDeclaration declaration = publicOnly ? ConfigurationMemberDeclaration.PRESENT : ConfigurationMemberDeclaration.DECLARED;
1393+
// register declaring type and method
1394+
ConfigurationType declaringType = MetadataTracer.singleton().traceReflectionType(method.getDeclaringClass().getName());
1395+
declaringType.addMethod(methodName, toInternalSignature(parameterTypes), declaration);
1396+
// register receiver type
1397+
MetadataTracer.singleton().traceReflectionType(getName());
1398+
}
13561399
if (throwMissingErrors && hiding) {
13571400
MissingReflectionRegistrationUtils.forMethod(clazz, methodName, parameterTypes);
13581401
}
13591402
return !(negative || hiding);
13601403
}
13611404
}
13621405

1406+
private static String toInternalSignature(Class<?>[] classes) {
1407+
List<String> names;
1408+
if (classes == null) {
1409+
names = List.of();
1410+
} else {
1411+
names = new ArrayList<>(classes.length);
1412+
for (int i = 0; i < classes.length; i++) {
1413+
names.set(i, classes[i].getName());
1414+
}
1415+
}
1416+
return SignatureUtil.toInternalSignature(names);
1417+
}
1418+
13631419
private boolean allElementsRegistered(boolean publicOnly, int allDeclaredElementsFlag, int allPublicElementsFlag) {
13641420
return isClassFlagSet(allDeclaredElementsFlag) || (publicOnly && isClassFlagSet(allPublicElementsFlag));
13651421
}
@@ -1830,6 +1886,8 @@ public DynamicHub arrayType() {
18301886
}
18311887
if (companion.arrayHub == null) {
18321888
MissingReflectionRegistrationUtils.forClass(getTypeName() + "[]");
1889+
} else if (MetadataTracer.Options.MetadataTracingSupport.getValue() && MetadataTracer.singleton().enabled()) {
1890+
MetadataTracer.singleton().traceReflectionType(companion.arrayHub.getTypeName());
18331891
}
18341892
return companion.arrayHub;
18351893
}

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import com.oracle.svm.configure.NamedConfigurationTypeDescriptor;
3737
import com.oracle.svm.configure.UnresolvedConfigurationCondition;
3838
import com.oracle.svm.configure.config.ConfigurationSet;
39+
import com.oracle.svm.configure.config.ConfigurationType;
3940
import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature;
4041
import com.oracle.svm.core.feature.InternalFeature;
4142
import com.oracle.svm.core.jdk.RuntimeSupport;
@@ -79,6 +80,11 @@ public boolean enabled() {
7980
return config != null;
8081
}
8182

83+
public ConfigurationType traceReflectionType(String className) {
84+
assert enabled();
85+
return config.getReflectionConfiguration().getOrCreateType(UnresolvedConfigurationCondition.alwaysTrue(), new NamedConfigurationTypeDescriptor(className));
86+
}
87+
8288
public void traceResource(String resourceName, String moduleName) {
8389
assert enabled();
8490
config.getResourceConfiguration().addGlobPattern(UnresolvedConfigurationCondition.alwaysTrue(), resourceName, moduleName);

0 commit comments

Comments
 (0)