Skip to content

Commit a400faa

Browse files
committed
Implement a bytecode-level analysis for constant reflection calls
1 parent eae9cac commit a400faa

File tree

25 files changed

+2030
-42
lines changed

25 files changed

+2030
-42
lines changed

compiler/mx.compiler/suite.py

+13-1
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,18 @@
120120
"license" : "BSD-new",
121121
},
122122

123+
"ASM_ANALYSIS_9.7.1" : {
124+
"digest" : "sha512:a8bd265c81d9bb4371cafd3f5d18f96ad79aec65031457d518c54599144d199d9feddf13b8dc822b2598b8b504a88edbd81d1f2c52991a70a6b343d8f5bb6fe5",
125+
"sourceDigest" : "sha512:ddfa874109ce46473f0a2aca46880f484bc5f598fccd4ed6dd48df95257114833654d6aed07e3f28994465b8c7b02e01517fedb1fe54cb11b922b1bed97b21b8",
126+
"maven" : {
127+
"groupId" : "org.ow2.asm",
128+
"artifactId" : "asm-analysis",
129+
"version" : "9.7.1",
130+
},
131+
"dependencies" : ["ASM_TREE_9.7.1"],
132+
"license" : "BSD-new",
133+
},
134+
123135
"HSDIS" : {
124136
"urlbase" : "https://lafo.ssw.uni-linz.ac.at/pub/graal-external-deps/hsdis",
125137
"packedResource" : True,
@@ -615,7 +627,7 @@
615627
"jdk.graal.compiler.nodes.graphbuilderconf to org.graalvm.nativeimage.driver,org.graalvm.nativeimage.librarysupport",
616628
"jdk.graal.compiler.options to org.graalvm.nativeimage.driver,org.graalvm.nativeimage.junitsupport",
617629
"jdk.graal.compiler.phases.common to org.graalvm.nativeimage.agent.tracing,org.graalvm.nativeimage.configure",
618-
"jdk.graal.compiler.serviceprovider to jdk.graal.compiler.management,org.graalvm.nativeimage.driver,org.graalvm.nativeimage.agent.jvmtibase,org.graalvm.nativeimage.agent.diagnostics",
630+
"jdk.graal.compiler.serviceprovider to jdk.graal.compiler.management,org.graalvm.nativeimage.driver,org.graalvm.nativeimage.agent.jvmtibase,org.graalvm.nativeimage.agent.diagnostics,org.graalvm.nativeimage.agent.reflection",
619631
"jdk.graal.compiler.util.json to org.graalvm.nativeimage.librarysupport,org.graalvm.nativeimage.agent.tracing,org.graalvm.nativeimage.configure,org.graalvm.nativeimage.driver",
620632
],
621633
"uses" : [

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/graphbuilderconf/GraphBuilderContext.java

+15
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,9 @@
7979
import jdk.vm.ci.meta.JavaType;
8080
import jdk.vm.ci.meta.ResolvedJavaMethod;
8181

82+
import java.util.ArrayList;
83+
import java.util.List;
84+
8285
/**
8386
* Used by a {@link GraphBuilderPlugin} to interface with an object that parses the bytecode of a
8487
* single {@linkplain #getMethod() method} as part of building a {@linkplain #getGraph() graph} .
@@ -278,6 +281,18 @@ default int getDepth() {
278281
return result;
279282
}
280283

284+
/**
285+
* Gets the inlined call stack for this context. A list with only one element implies that no
286+
* inlining has taken place.
287+
*/
288+
default List<StackTraceElement> getCallStack() {
289+
List<StackTraceElement> callStack = new ArrayList<>();
290+
for (GraphBuilderContext cur = this; cur != null; cur = cur.getParent()) {
291+
callStack.add(cur.getMethod().asStackTraceElement(cur.bci()));
292+
}
293+
return callStack;
294+
}
295+
281296
/**
282297
* Computes the recursive inlining depth of the provided method, i.e., counts how often the
283298
* provided method is already in the {@link #getParent()} chain starting at this context.

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/IntrinsicGraphBuilder.java

+8
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,9 @@
7676
import jdk.vm.ci.meta.ResolvedJavaType;
7777
import jdk.vm.ci.meta.Signature;
7878

79+
import java.util.ArrayList;
80+
import java.util.List;
81+
7982
/**
8083
* Implementation of {@link GraphBuilderContext} used to produce a graph for a method based on an
8184
* {@link InvocationPlugin} for the method.
@@ -325,6 +328,11 @@ public int getDepth() {
325328
return 0;
326329
}
327330

331+
@Override
332+
public List<StackTraceElement> getCallStack() {
333+
return new ArrayList<>();
334+
}
335+
328336
@Override
329337
public boolean parsingIntrinsic() {
330338
return false;

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/PEGraphDecoder.java

+13
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,19 @@ public int getDepth() {
412412
return methodScope.inliningDepth;
413413
}
414414

415+
@Override
416+
public List<StackTraceElement> getCallStack() {
417+
List<StackTraceElement> callStack = new ArrayList<>(Arrays.asList(methodScope.getCallStack()));
418+
/*
419+
* If we're processing an invocation plugin, we want the top stack element to be the
420+
* callee of the method targeted by the plugin, and not the target itself.
421+
*/
422+
if (isParsingInvocationPlugin()) {
423+
callStack.removeFirst();
424+
}
425+
return callStack;
426+
}
427+
415428
@Override
416429
public int recursiveInliningDepth(ResolvedJavaMethod method) {
417430
int result = 0;

sdk/mx.sdk/suite.py

+1
Original file line numberDiff line numberDiff line change
@@ -821,6 +821,7 @@ class UniversalDetector {
821821
"org.graalvm.nativeimage.c.constant",
822822
"org.graalvm.nativeimage.c",
823823
"org.graalvm.nativeimage",
824+
"org.graalvm.nativeimage.impl.reflectiontags",
824825
"""org.graalvm.nativeimage.impl to org.graalvm.nativeimage.pointsto,
825826
org.graalvm.nativeimage.base,
826827
org.graalvm.nativeimage.builder,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,226 @@
1+
/*
2+
* Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* The Universal Permissive License (UPL), Version 1.0
6+
*
7+
* Subject to the condition set forth below, permission is hereby granted to any
8+
* person obtaining a copy of this software, associated documentation and/or
9+
* data (collectively the "Software"), free of charge and under any and all
10+
* copyright rights in the Software, and any and all patent rights owned or
11+
* freely licensable by each licensor hereunder covering either (i) the
12+
* unmodified Software as contributed to or provided by such licensor, or (ii)
13+
* the Larger Works (as defined below), to deal in both
14+
*
15+
* (a) the Software, and
16+
*
17+
* (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
18+
* one is included with the Software each a "Larger Work" to which the Software
19+
* is contributed by such licensors),
20+
*
21+
* without restriction, including without limitation the rights to copy, create
22+
* derivative works of, display, perform, and distribute the Software and make,
23+
* use, sell, offer for sale, import, export, have made, and have sold the
24+
* Software and the Larger Work(s), and to sublicense the foregoing rights on
25+
* either these or other terms.
26+
*
27+
* This license is subject to the following condition:
28+
*
29+
* The above copyright notice and either this complete permission notice or at a
30+
* minimum a reference to the UPL must be included in all copies or substantial
31+
* portions of the Software.
32+
*
33+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
34+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
35+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
36+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
37+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
38+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
39+
* SOFTWARE.
40+
*/
41+
package org.graalvm.nativeimage.impl.reflectiontags;
42+
43+
import java.lang.invoke.MethodHandle;
44+
import java.lang.invoke.MethodHandles;
45+
import java.lang.invoke.MethodType;
46+
import java.lang.invoke.VarHandle;
47+
import java.lang.reflect.Constructor;
48+
import java.lang.reflect.Field;
49+
import java.lang.reflect.Method;
50+
import java.lang.reflect.RecordComponent;
51+
import java.util.Collections;
52+
import java.util.HashMap;
53+
import java.util.Map;
54+
55+
/**
56+
* Used for representing constant reflection calls caught by {@link com.oracle.svm.reflectionagent}.
57+
* <p>
58+
* Due to build-time initialization, the calls must implement the equivalent logic of their corresponding
59+
* reflection method. Since these calls will be folded into constants, they will never be executed during
60+
* image run-time.
61+
*/
62+
public final class ConstantTags {
63+
64+
public static final Map<Method, Method> TAG_TO_ORIGINAL_MAPPING;
65+
66+
static {
67+
Map<Method, Method> mapping = new HashMap<>();
68+
try {
69+
mapping.put(ConstantTags.class.getDeclaredMethod("forName", String.class), Class.class.getDeclaredMethod("forName", String.class));
70+
mapping.put(ConstantTags.class.getDeclaredMethod("forName", String.class, boolean.class, ClassLoader.class), Class.class.getDeclaredMethod("forName", String.class, boolean.class, ClassLoader.class));
71+
mapping.put(ConstantTags.class.getDeclaredMethod("getField", Class.class, String.class), Class.class.getDeclaredMethod("getField", String.class));
72+
mapping.put(ConstantTags.class.getDeclaredMethod("getDeclaredField", Class.class, String.class), Class.class.getDeclaredMethod("getDeclaredField", String.class));
73+
mapping.put(ConstantTags.class.getDeclaredMethod("getConstructor", Class.class, Class[].class), Class.class.getDeclaredMethod("getConstructor", Class[].class));
74+
mapping.put(ConstantTags.class.getDeclaredMethod("getDeclaredConstructor", Class.class, Class[].class), Class.class.getDeclaredMethod("getDeclaredConstructor", Class[].class));
75+
mapping.put(ConstantTags.class.getDeclaredMethod("getMethod", Class.class, String.class, Class[].class), Class.class.getDeclaredMethod("getMethod", String.class, Class[].class));
76+
mapping.put(ConstantTags.class.getDeclaredMethod("getDeclaredMethod", Class.class, String.class, Class[].class), Class.class.getDeclaredMethod("getDeclaredMethod", String.class, Class[].class));
77+
mapping.put(ConstantTags.class.getDeclaredMethod("getFields", Class.class), Class.class.getDeclaredMethod("getFields"));
78+
mapping.put(ConstantTags.class.getDeclaredMethod("getDeclaredFields", Class.class), Class.class.getDeclaredMethod("getDeclaredFields"));
79+
mapping.put(ConstantTags.class.getDeclaredMethod("getConstructors", Class.class), Class.class.getDeclaredMethod("getConstructors"));
80+
mapping.put(ConstantTags.class.getDeclaredMethod("getDeclaredConstructors", Class.class), Class.class.getDeclaredMethod("getDeclaredConstructors"));
81+
mapping.put(ConstantTags.class.getDeclaredMethod("getMethods", Class.class), Class.class.getDeclaredMethod("getMethods"));
82+
mapping.put(ConstantTags.class.getDeclaredMethod("getDeclaredMethods", Class.class), Class.class.getDeclaredMethod("getDeclaredMethods"));
83+
mapping.put(ConstantTags.class.getDeclaredMethod("getClasses", Class.class), Class.class.getDeclaredMethod("getClasses"));
84+
mapping.put(ConstantTags.class.getDeclaredMethod("getDeclaredClasses", Class.class), Class.class.getDeclaredMethod("getDeclaredClasses"));
85+
mapping.put(ConstantTags.class.getDeclaredMethod("getNestMembers", Class.class), Class.class.getDeclaredMethod("getNestMembers"));
86+
mapping.put(ConstantTags.class.getDeclaredMethod("getPermittedSubclasses", Class.class), Class.class.getDeclaredMethod("getPermittedSubclasses"));
87+
mapping.put(ConstantTags.class.getDeclaredMethod("getRecordComponents", Class.class), Class.class.getDeclaredMethod("getRecordComponents"));
88+
mapping.put(ConstantTags.class.getDeclaredMethod("getSigners", Class.class), Class.class.getDeclaredMethod("getSigners"));
89+
mapping.put(ConstantTags.class.getDeclaredMethod("findClass", MethodHandles.Lookup.class, String.class), MethodHandles.Lookup.class.getDeclaredMethod("findClass", String.class));
90+
mapping.put(ConstantTags.class.getDeclaredMethod("findVirtual", MethodHandles.Lookup.class, Class.class, String.class, MethodType.class), MethodHandles.Lookup.class.getDeclaredMethod("findVirtual", Class.class, String.class, MethodType.class));
91+
mapping.put(ConstantTags.class.getDeclaredMethod("findStatic", MethodHandles.Lookup.class, Class.class, String.class, MethodType.class), MethodHandles.Lookup.class.getDeclaredMethod("findStatic", Class.class, String.class, MethodType.class));
92+
mapping.put(ConstantTags.class.getDeclaredMethod("findConstructor", MethodHandles.Lookup.class, Class.class, MethodType.class), MethodHandles.Lookup.class.getDeclaredMethod("findConstructor", Class.class, MethodType.class));
93+
mapping.put(ConstantTags.class.getDeclaredMethod("findGetter", MethodHandles.Lookup.class, Class.class, String.class, Class.class), MethodHandles.Lookup.class.getDeclaredMethod("findGetter", Class.class, String.class, Class.class));
94+
mapping.put(ConstantTags.class.getDeclaredMethod("findStaticGetter", MethodHandles.Lookup.class, Class.class, String.class, Class.class), MethodHandles.Lookup.class.getDeclaredMethod("findStaticGetter", Class.class, String.class, Class.class));
95+
mapping.put(ConstantTags.class.getDeclaredMethod("findSetter", MethodHandles.Lookup.class, Class.class, String.class, Class.class), MethodHandles.Lookup.class.getDeclaredMethod("findSetter", Class.class, String.class, Class.class));
96+
mapping.put(ConstantTags.class.getDeclaredMethod("findStaticSetter", MethodHandles.Lookup.class, Class.class, String.class, Class.class), MethodHandles.Lookup.class.getDeclaredMethod("findStaticSetter", Class.class, String.class, Class.class));
97+
mapping.put(ConstantTags.class.getDeclaredMethod("findVarHandle", MethodHandles.Lookup.class, Class.class, String.class, Class.class), MethodHandles.Lookup.class.getDeclaredMethod("findVarHandle", Class.class, String.class, Class.class));
98+
mapping.put(ConstantTags.class.getDeclaredMethod("findStaticVarHandle", MethodHandles.Lookup.class, Class.class, String.class, Class.class), MethodHandles.Lookup.class.getDeclaredMethod("findStaticVarHandle", Class.class, String.class, Class.class));
99+
} catch (NoSuchMethodException e) {
100+
throw new RuntimeException(e);
101+
}
102+
TAG_TO_ORIGINAL_MAPPING = Collections.unmodifiableMap(mapping);
103+
}
104+
105+
private static final StackWalker stackWalker = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE);
106+
107+
public static Class<?> forName(String className) throws ClassNotFoundException {
108+
return Class.forName(className, true, stackWalker.getCallerClass().getClassLoader());
109+
}
110+
111+
public static Class<?> forName(String className, boolean initialize, ClassLoader classLoader) throws ClassNotFoundException {
112+
return Class.forName(className, initialize, classLoader);
113+
}
114+
115+
public static Field getField(Class<?> clazz, String fieldName) throws NoSuchFieldException {
116+
return clazz.getField(fieldName);
117+
}
118+
119+
public static Field getDeclaredField(Class<?> clazz, String fieldName) throws NoSuchFieldException {
120+
return clazz.getDeclaredField(fieldName);
121+
}
122+
123+
public static Constructor<?> getConstructor(Class<?> clazz, Class<?>... parameterTypes) throws NoSuchMethodException {
124+
return clazz.getConstructor(parameterTypes);
125+
}
126+
127+
public static Constructor<?> getDeclaredConstructor(Class<?> clazz, Class<?>... parameterTypes) throws NoSuchMethodException {
128+
return clazz.getDeclaredConstructor(parameterTypes);
129+
}
130+
131+
public static Method getMethod(Class<?> clazz, String methodName, Class<?>... parameterTypes) throws NoSuchMethodException {
132+
return clazz.getMethod(methodName, parameterTypes);
133+
}
134+
135+
public static Method getDeclaredMethod(Class<?> clazz, String methodName, Class<?>... parameterTypes) throws NoSuchMethodException {
136+
return clazz.getDeclaredMethod(methodName, parameterTypes);
137+
}
138+
139+
public static Field[] getFields(Class<?> clazz) {
140+
return clazz.getFields();
141+
}
142+
143+
public static Field[] getDeclaredFields(Class<?> clazz) {
144+
return clazz.getDeclaredFields();
145+
}
146+
147+
public static Constructor<?>[] getConstructors(Class<?> clazz) {
148+
return clazz.getConstructors();
149+
}
150+
151+
public static Constructor<?>[] getDeclaredConstructors(Class<?> clazz) {
152+
return clazz.getDeclaredConstructors();
153+
}
154+
155+
public static Method[] getMethods(Class<?> clazz) {
156+
return clazz.getMethods();
157+
}
158+
159+
public static Method[] getDeclaredMethods(Class<?> clazz) {
160+
return clazz.getDeclaredMethods();
161+
}
162+
163+
public static Class<?>[] getClasses(Class<?> clazz) {
164+
return clazz.getClasses();
165+
}
166+
167+
public static Class<?>[] getDeclaredClasses(Class<?> clazz) {
168+
return clazz.getDeclaredClasses();
169+
}
170+
171+
public static Class<?>[] getNestMembers(Class<?> clazz) {
172+
return clazz.getNestMembers();
173+
}
174+
175+
public static Class<?>[] getPermittedSubclasses(Class<?> clazz) {
176+
return clazz.getPermittedSubclasses();
177+
}
178+
179+
public static RecordComponent[] getRecordComponents(Class<?> clazz) {
180+
return clazz.getRecordComponents();
181+
}
182+
183+
public static Object[] getSigners(Class<?> clazz) {
184+
return clazz.getSigners();
185+
}
186+
187+
public static Class<?> findClass(MethodHandles.Lookup lookup, String className) throws ClassNotFoundException, IllegalAccessException {
188+
return lookup.findClass(className);
189+
}
190+
191+
public static MethodHandle findVirtual(MethodHandles.Lookup lookup, Class<?> clazz, String methodName, MethodType methodType) throws NoSuchMethodException, IllegalAccessException {
192+
return lookup.findVirtual(clazz, methodName, methodType);
193+
}
194+
195+
public static MethodHandle findStatic(MethodHandles.Lookup lookup, Class<?> clazz, String methodName, MethodType methodType) throws NoSuchMethodException, IllegalAccessException {
196+
return lookup.findStatic(clazz, methodName, methodType);
197+
}
198+
199+
public static MethodHandle findConstructor(MethodHandles.Lookup lookup, Class<?> clazz, MethodType methodType) throws NoSuchMethodException, IllegalAccessException {
200+
return lookup.findConstructor(clazz, methodType);
201+
}
202+
203+
public static MethodHandle findGetter(MethodHandles.Lookup lookup, Class<?> clazz, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
204+
return lookup.findGetter(clazz, name, type);
205+
}
206+
207+
public static MethodHandle findStaticGetter(MethodHandles.Lookup lookup, Class<?> clazz, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
208+
return lookup.findStaticGetter(clazz, name, type);
209+
}
210+
211+
public static MethodHandle findSetter(MethodHandles.Lookup lookup, Class<?> clazz, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
212+
return lookup.findSetter(clazz, name, type);
213+
}
214+
215+
public static MethodHandle findStaticSetter(MethodHandles.Lookup lookup, Class<?> clazz, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
216+
return lookup.findStaticSetter(clazz, name, type);
217+
}
218+
219+
public static VarHandle findVarHandle(MethodHandles.Lookup lookup, Class<?> clazz, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
220+
return lookup.findVarHandle(clazz, name, type);
221+
}
222+
223+
public static VarHandle findStaticVarHandle(MethodHandles.Lookup lookup, Class<?> clazz, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
224+
return lookup.findStaticVarHandle(clazz, name, type);
225+
}
226+
}

substratevm/mx.substratevm/mx_substratevm.py

+14
Original file line numberDiff line numberDiff line change
@@ -1362,6 +1362,20 @@ def _native_image_launcher_extra_jvm_args():
13621362
headers=False,
13631363
home_finder=False,
13641364
),
1365+
mx_sdk_vm.LibraryConfig(
1366+
use_modules='image',
1367+
destination="<lib:native-image-reflection-agent>",
1368+
jvm_library=True,
1369+
jar_distributions=[
1370+
'substratevm:JVMTI_AGENT_BASE',
1371+
'substratevm:SVM_REFLECTION_AGENT',
1372+
],
1373+
build_args=driver_build_args + [
1374+
'--features=com.oracle.svm.reflectionagent.NativeImageReflectionAgent$RegistrationFeature',
1375+
],
1376+
headers=False,
1377+
home_finder=False,
1378+
),
13651379
],
13661380
installable=True,
13671381
stability="earlyadopter",

0 commit comments

Comments
 (0)