Skip to content

Commit 0a91e12

Browse files
committed
Add tracking of sun.misc.Unsafe#allocateInstance and jdk.internal.misc.Unsafe#allocateInstance to DynamicAccessDetectionPhase
1 parent cef3604 commit 0a91e12

File tree

5 files changed

+108
-40
lines changed

5 files changed

+108
-40
lines changed

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -587,9 +587,9 @@ public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Rec
587587
b.add(new KlassFullyInitializedCheckNode(clazzLegal));
588588

589589
if (b.currentBlockCatchesOOME()) {
590-
b.addPush(JavaKind.Object, new DynamicNewInstanceWithExceptionNode(clazzLegal, true));
590+
b.addPush(JavaKind.Object, new DynamicNewInstanceWithExceptionNode(clazzLegal, true, true));
591591
} else {
592-
b.addPush(JavaKind.Object, new DynamicNewInstanceNode(clazzLegal, true));
592+
b.addPush(JavaKind.Object, new DynamicNewInstanceNode(clazzLegal, true, true));
593593
}
594594
return true;
595595
}

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/java/DynamicNewInstanceNode.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,17 +45,27 @@ public final class DynamicNewInstanceNode extends AbstractNewObjectNode implemen
4545
public static final NodeClass<DynamicNewInstanceNode> TYPE = NodeClass.create(DynamicNewInstanceNode.class);
4646

4747
@Input ValueNode clazz;
48+
private final boolean originUnsafeAllocateInstance;
4849

4950
public DynamicNewInstanceNode(ValueNode clazz, boolean fillContents) {
51+
this(clazz, fillContents, false);
52+
}
53+
54+
public DynamicNewInstanceNode(ValueNode clazz, boolean fillContents, boolean originUnsafeAllocateInstance) {
5055
super(TYPE, StampFactory.objectNonNull(), fillContents, null);
5156
this.clazz = clazz;
57+
this.originUnsafeAllocateInstance = originUnsafeAllocateInstance;
5258
assert ((ObjectStamp) clazz.stamp(NodeView.DEFAULT)).nonNull();
5359
}
5460

5561
public ValueNode getInstanceType() {
5662
return clazz;
5763
}
5864

65+
public boolean isOriginUnsafeAllocateInstance() {
66+
return originUnsafeAllocateInstance;
67+
}
68+
5969
static ResolvedJavaType tryConvertToNonDynamic(ValueNode clazz, CoreProviders tool) {
6070
if (clazz.isConstant()) {
6171
ResolvedJavaType type = tool.getConstantReflection().asJavaType(clazz.asConstant());

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/java/DynamicNewInstanceWithExceptionNode.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,17 +44,27 @@ public class DynamicNewInstanceWithExceptionNode extends AllocateWithExceptionNo
4444

4545
@Input ValueNode clazz;
4646
protected boolean fillContents;
47+
private final boolean originUnsafeAllocateInstance;
4748

4849
public DynamicNewInstanceWithExceptionNode(ValueNode clazz, boolean fillContents) {
50+
this(clazz, fillContents, false);
51+
}
52+
53+
public DynamicNewInstanceWithExceptionNode(ValueNode clazz, boolean fillContents, boolean originUnsafeAllocateInstance) {
4954
super(TYPE, StampFactory.objectNonNull());
5055
this.fillContents = fillContents;
5156
this.clazz = clazz;
57+
this.originUnsafeAllocateInstance = originUnsafeAllocateInstance;
5258
}
5359

5460
public ValueNode getInstanceType() {
5561
return clazz;
5662
}
5763

64+
public boolean isOriginUnsafeAllocateInstance() {
65+
return originUnsafeAllocateInstance;
66+
}
67+
5868
@Override
5969
public Node canonical(CanonicalizerTool tool) {
6070
ResolvedJavaType type = tryConvertToNonDynamic(clazz, tool);
@@ -67,7 +77,7 @@ public Node canonical(CanonicalizerTool tool) {
6777
@Override
6878
public FixedNode replaceWithNonThrowing() {
6979
killExceptionEdge();
70-
DynamicNewInstanceNode newInstance = graph().add(new DynamicNewInstanceNode(clazz, fillContents));
80+
DynamicNewInstanceNode newInstance = graph().add(new DynamicNewInstanceNode(clazz, fillContents, originUnsafeAllocateInstance));
7181
newInstance.setStateBefore(stateBefore);
7282
graph().replaceSplitWithFixed(this, newInstance, this.next());
7383
// copy across any original node source position

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/DynamicAccessDetectionPhase.java

Lines changed: 83 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,10 @@
5353
import java.util.Objects;
5454
import java.util.Set;
5555

56+
import com.oracle.svm.util.ReflectionUtil;
57+
import jdk.graal.compiler.graph.Node;
58+
import jdk.graal.compiler.nodes.java.DynamicNewInstanceNode;
59+
import jdk.graal.compiler.nodes.java.DynamicNewInstanceWithExceptionNode;
5660
import org.graalvm.collections.EconomicMap;
5761
import org.graalvm.collections.EconomicSet;
5862

@@ -183,6 +187,13 @@ public record MethodInfo(DynamicAccessKind accessKind, String signature) {
183187
new MethodSignature("resolveConstantDesc", MethodHandles.Lookup.class)));
184188
reflectionMethodSignatures.put(MethodHandleProxies.class, Set.of(
185189
new MethodSignature("asInterfaceInstance", Class.class, MethodHandle.class)));
190+
reflectionMethodSignatures.put(jdk.internal.misc.Unsafe.class, Set.of(
191+
new MethodSignature("allocateInstance", Class.class)));
192+
if (ModuleLayer.boot().findModule("jdk.unsupported").isPresent()) {
193+
Class<?> sunMiscUnsafeClass = ReflectionUtil.lookupClass("sun.misc.Unsafe");
194+
reflectionMethodSignatures.put(sunMiscUnsafeClass, Set.of(
195+
new MethodSignature("allocateInstance", Class.class)));
196+
}
186197

187198
reflectionMethodSignatures.put(ObjectOutputStream.class, Set.of(
188199
new MethodSignature("writeObject", Object.class),
@@ -210,6 +221,7 @@ public record MethodInfo(DynamicAccessKind accessKind, String signature) {
210221
new MethodSignature("getResourceAsStream", String.class)));
211222
resourceMethodSignatures.put(Class.class, Set.of(
212223
new MethodSignature("getResource", String.class),
224+
213225
new MethodSignature("getResourceAsStream", String.class)));
214226

215227
foreignMethodSignatures.put(Linker.class, Set.of(
@@ -224,18 +236,45 @@ public DynamicAccessDetectionPhase() {
224236

225237
@Override
226238
protected void run(StructuredGraph graph, CoreProviders context) {
227-
List<MethodCallTargetNode> callTargetNodes = graph.getNodes(MethodCallTargetNode.TYPE).snapshot();
228-
for (MethodCallTargetNode callTarget : callTargetNodes) {
229-
AnalysisType callerClass = (AnalysisType) graph.method().getDeclaringClass();
230-
String sourceEntry = getSourceEntry(callerClass);
231-
MethodInfo methodInfo = getMethodInfo(callTarget.targetMethod());
232-
233-
if (methodInfo != null && sourceEntry != null) {
234-
NodeSourcePosition nspToShow = callTarget.getNodeSourcePosition();
235-
if (nspToShow != null && !dynamicAccessDetectionFeature.containsFoldEntry(nspToShow.getBCI(), nspToShow.getMethod())) {
236-
String callLocation = nspToShow.getMethod().asStackTraceElement(nspToShow.getBCI()).toString();
237-
dynamicAccessDetectionFeature.addCall(sourceEntry, methodInfo.accessKind(), methodInfo.signature(), callLocation);
238-
}
239+
AnalysisType callerClass = (AnalysisType) graph.method().getDeclaringClass();
240+
String sourceEntry = getSourceEntry(callerClass);
241+
if (sourceEntry == null) {
242+
return;
243+
}
244+
245+
for (Node node : graph.getNodes()) {
246+
ResolvedJavaMethod targetMethod = null;
247+
NodeSourcePosition invokeLocation = null;
248+
if (node instanceof MethodCallTargetNode callTarget) {
249+
targetMethod = callTarget.targetMethod();
250+
invokeLocation = callTarget.getNodeSourcePosition();
251+
} else if (node instanceof DynamicNewInstanceNode unsafeNode && unsafeNode.getNodeSourcePosition() != null && unsafeNode.isOriginUnsafeAllocateInstance()) {
252+
/*
253+
* Match only DynamicNewInstanceNode intrinsified from Unsafe#allocateInstance. The
254+
* NodeSourcePosition of the node preserves both the intrinsified method
255+
* (getMethod()) and its original caller (getCaller()).
256+
*/
257+
targetMethod = unsafeNode.getNodeSourcePosition().getMethod();
258+
invokeLocation = unsafeNode.getNodeSourcePosition().getCaller();
259+
} else if (node instanceof DynamicNewInstanceWithExceptionNode unsafeNodeEx && unsafeNodeEx.getNodeSourcePosition() != null && unsafeNodeEx.isOriginUnsafeAllocateInstance()) {
260+
/*
261+
* Match only DynamicNewInstanceWithExceptionNode intrinsified from
262+
* Unsafe#allocateInstance. The NodeSourcePosition of the node preserves both the
263+
* intrinsified method (getMethod()) and its original caller (getCaller()).
264+
*/
265+
targetMethod = unsafeNodeEx.getNodeSourcePosition().getMethod();
266+
invokeLocation = unsafeNodeEx.getNodeSourcePosition().getCaller();
267+
}
268+
registerDynamicAccessCall(invokeLocation, targetMethod, sourceEntry);
269+
}
270+
}
271+
272+
private void registerDynamicAccessCall(NodeSourcePosition invokeLocation, ResolvedJavaMethod targetMethod, String sourceEntry) {
273+
if (invokeLocation != null && !dynamicAccessDetectionFeature.containsFoldEntry(invokeLocation.getBCI(), invokeLocation.getMethod())) {
274+
MethodInfo dynamicAccessMethodInfo = lookupDynamicAccessMethod(targetMethod);
275+
if (dynamicAccessMethodInfo != null) {
276+
String callLocation = invokeLocation.getMethod().asStackTraceElement(invokeLocation.getBCI()).toString();
277+
dynamicAccessDetectionFeature.addCall(sourceEntry, dynamicAccessMethodInfo.accessKind(), dynamicAccessMethodInfo.signature(), callLocation);
239278
}
240279
}
241280
}
@@ -245,33 +284,31 @@ protected void run(StructuredGraph graph, CoreProviders context) {
245284
* method if it exists in the predetermined set, based on its graph and MethodCallTargetNode;
246285
* otherwise, returns null.
247286
*/
248-
private static MethodInfo getMethodInfo(ResolvedJavaMethod method) {
287+
private static MethodInfo lookupDynamicAccessMethod(ResolvedJavaMethod method) {
249288
Class<?> declaringClass = OriginalClassProvider.getJavaClass(method.getDeclaringClass());
250-
if (!reflectionMethodSignatures.containsKey(declaringClass) &&
251-
!resourceMethodSignatures.containsKey(declaringClass) &&
252-
!foreignMethodSignatures.containsKey(declaringClass)) {
253-
return null;
289+
290+
Set<MethodSignature> reflectionSignatures = reflectionMethodSignatures.get(declaringClass);
291+
if (reflectionSignatures != null) {
292+
MethodSignature methodSignature = new MethodSignature(method);
293+
if (reflectionSignatures.contains(methodSignature)) {
294+
return new MethodInfo(DynamicAccessKind.Reflection, getClassName(declaringClass) + "#" + methodSignature);
295+
}
254296
}
255297

256-
String methodName = method.getName();
257-
Signature signature = method.getSignature();
258-
List<Class<?>> paramList = new ArrayList<>();
259-
for (int i = 0; i < signature.getParameterCount(false); i++) {
260-
JavaType type = signature.getParameterType(i, method.getDeclaringClass());
261-
paramList.add(OriginalClassProvider.getJavaClass(type));
298+
Set<MethodSignature> resourceSignatures = resourceMethodSignatures.get(declaringClass);
299+
if (resourceSignatures != null) {
300+
MethodSignature methodSignature = new MethodSignature(method);
301+
if (resourceSignatures.contains(methodSignature)) {
302+
return new MethodInfo(DynamicAccessKind.Resource, getClassName(declaringClass) + "#" + methodSignature);
303+
}
262304
}
263-
Class<?>[] paramTypes = paramList.toArray(new Class<?>[0]);
264-
MethodSignature methodSignature = new MethodSignature(methodName, paramTypes);
265-
266-
if (reflectionMethodSignatures.containsKey(declaringClass) &&
267-
reflectionMethodSignatures.get(declaringClass).contains(methodSignature)) {
268-
return new MethodInfo(DynamicAccessKind.Reflection, getClassName(declaringClass) + "#" + methodSignature);
269-
} else if (resourceMethodSignatures.containsKey(declaringClass) &&
270-
resourceMethodSignatures.get(declaringClass).contains(methodSignature)) {
271-
return new MethodInfo(DynamicAccessKind.Resource, getClassName(declaringClass) + "#" + methodSignature);
272-
} else if (foreignMethodSignatures.containsKey(declaringClass) &&
273-
foreignMethodSignatures.get(declaringClass).contains(methodSignature)) {
274-
return new MethodInfo(DynamicAccessKind.Foreign, getClassName(declaringClass) + "#" + methodSignature);
305+
306+
Set<MethodSignature> foreignSignatures = foreignMethodSignatures.get(declaringClass);
307+
if (foreignSignatures != null) {
308+
MethodSignature methodSignature = new MethodSignature(method);
309+
if (foreignSignatures.contains(methodSignature)) {
310+
return new MethodInfo(DynamicAccessKind.Foreign, getClassName(declaringClass) + "#" + methodSignature);
311+
}
275312
}
276313

277314
return null;
@@ -332,6 +369,17 @@ private static class MethodSignature {
332369
this.paramTypes = paramTypes;
333370
}
334371

372+
MethodSignature(ResolvedJavaMethod method) {
373+
this.name = method.getName();
374+
Signature signature = method.getSignature();
375+
List<Class<?>> paramList = new ArrayList<>();
376+
for (int i = 0; i < signature.getParameterCount(false); i++) {
377+
JavaType type = signature.getParameterType(i, method.getDeclaringClass());
378+
paramList.add(OriginalClassProvider.getJavaClass(type));
379+
}
380+
paramTypes = paramList.toArray(new Class<?>[0]);
381+
}
382+
335383
@Override
336384
public boolean equals(Object o) {
337385
if (this == o) {

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/snippets/SubstrateGraphBuilderPlugins.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -844,9 +844,9 @@ public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Rec
844844

845845
ValidateNewInstanceClassNode clazzLegal = b.add(new ValidateNewInstanceClassNode(clazzNonNull));
846846
if (b.currentBlockCatchesOOME()) {
847-
b.addPush(JavaKind.Object, new DynamicNewInstanceWithExceptionNode(clazzLegal, true));
847+
b.addPush(JavaKind.Object, new DynamicNewInstanceWithExceptionNode(clazzLegal, true, true));
848848
} else {
849-
b.addPush(JavaKind.Object, new DynamicNewInstanceNode(clazzLegal, true));
849+
b.addPush(JavaKind.Object, new DynamicNewInstanceNode(clazzLegal, true, true));
850850
}
851851
return true;
852852
}

0 commit comments

Comments
 (0)