Skip to content

Commit e67b819

Browse files
Zeaveeteshull
authored andcommitted
[GR-57637] Build Layered Image with external libraries
PullRequest: graal/18676
2 parents 5d8ff09 + 85d850e commit e67b819

File tree

28 files changed

+405
-63
lines changed

28 files changed

+405
-63
lines changed

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/util/ObjectCopier.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -468,7 +468,7 @@ public Decoder(ClassLoader loader) {
468468
this.loader = loader;
469469
}
470470

471-
Class<?> loadClass(String className) {
471+
public Class<?> loadClass(String className) {
472472
try {
473473
return Class.forName(className, false, loader);
474474
} catch (ClassNotFoundException e) {

substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/AbstractAnalysisEngine.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,13 @@ public void registerTypeForBaseImage(Class<?> cls) {
364364
}
365365
}
366366

367+
@Override
368+
public void registerMethodForBaseImage(AnalysisMethod method) {
369+
if (classInclusionPolicy.isMethodIncluded(method)) {
370+
classInclusionPolicy.includeMethod(method);
371+
}
372+
}
373+
367374
public static <T, U> U getOrDefault(T cls, Function<T, U> getMembers, U backup) {
368375
try {
369376
return getMembers.apply(cls);

substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/BigBang.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,4 +142,9 @@ default AnalysisMethod fallbackResolveConcreteMethod(AnalysisType resolvingType,
142142
default void registerTypeForBaseImage(Class<?> cls) {
143143

144144
}
145+
146+
@SuppressWarnings("unused")
147+
default void registerMethodForBaseImage(AnalysisMethod method) {
148+
149+
}
145150
}

substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/ClassInclusionPolicy.java

Lines changed: 40 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -66,12 +66,16 @@ public boolean isClassIncluded(Class<?> cls) {
6666
* Determine if the given method needs to be included in the image according to the policy.
6767
*/
6868
public boolean isMethodIncluded(Executable method) {
69+
return isMethodIncluded(bb.getMetaAccess().lookupJavaMethod(method));
70+
}
71+
72+
public boolean isMethodIncluded(AnalysisMethod method) {
6973
/*
7074
* Methods annotated with @Fold should not be included in the base image as they must be
7175
* inlined. An extension image would inline the method as well and would not use the method
7276
* from the base image.
7377
*/
74-
return !AnnotationAccess.isAnnotationPresent(bb.getMetaAccess().lookupJavaMethod(method), Fold.class);
78+
return !AnnotationAccess.isAnnotationPresent(method, Fold.class);
7579
}
7680

7781
/**
@@ -105,6 +109,11 @@ public void includeClass(Class<?> cls) {
105109
*/
106110
public abstract void includeMethod(Executable method);
107111

112+
/**
113+
* Includes the given method in the image.
114+
*/
115+
public abstract void includeMethod(AnalysisMethod method);
116+
108117
/**
109118
* Includes the given field in the image.
110119
*/
@@ -151,23 +160,35 @@ public boolean isMethodIncluded(Executable method) {
151160
@Override
152161
public void includeMethod(Executable method) {
153162
bb.postTask(debug -> {
154-
/*
155-
* Non-abstract methods from an abstract class or default methods from an interface
156-
* are not registered as implementation invoked by the analysis because their
157-
* declaring class cannot be marked as instantiated and AnalysisType.getTypeFlow
158-
* only includes instantiated types (see TypeFlow.addObserver). For now, to ensure
159-
* those methods are included in the image, they are manually registered as
160-
* implementation invoked.
161-
*/
162163
Class<?> declaringClass = method.getDeclaringClass();
163-
if (!Modifier.isAbstract(method.getModifiers()) && (declaringClass.isInterface() || Modifier.isAbstract(declaringClass.getModifiers()))) {
164-
AnalysisMethod analysisMethod = bb.getMetaAccess().lookupJavaMethod(method);
165-
analysisMethod.registerAsDirectRootMethod(reason);
166-
analysisMethod.registerAsImplementationInvoked(reason);
167-
}
164+
AnalysisMethod analysisMethod = bb.getMetaAccess().lookupJavaMethod(method);
165+
registerMethod(method.getModifiers(), declaringClass, analysisMethod);
166+
bb.forcedAddRootMethod(analysisMethod, false, reason);
167+
});
168+
}
169+
170+
@Override
171+
public void includeMethod(AnalysisMethod method) {
172+
bb.postTask(debug -> {
173+
Class<?> declaringClass = method.getDeclaringClass().getJavaClass();
174+
registerMethod(method.getModifiers(), declaringClass, method);
168175
bb.forcedAddRootMethod(method, false, reason);
169176
});
170177
}
178+
179+
private void registerMethod(int methodModifiers, Class<?> declaringClass, AnalysisMethod analysisMethod) {
180+
/*
181+
* Non-abstract methods from an abstract class or default methods from an interface are
182+
* not registered as implementation invoked by the analysis because their declaring
183+
* class cannot be marked as instantiated and AnalysisType.getTypeFlow only includes
184+
* instantiated types (see TypeFlow.addObserver). For now, to ensure those methods are
185+
* included in the image, they are manually registered as implementation invoked.
186+
*/
187+
if (!Modifier.isAbstract(methodModifiers) && (declaringClass.isInterface() || Modifier.isAbstract(declaringClass.getModifiers()))) {
188+
analysisMethod.registerAsDirectRootMethod(reason);
189+
analysisMethod.registerAsImplementationInvoked(reason);
190+
}
191+
}
171192
}
172193

173194
/**
@@ -184,6 +205,11 @@ public DefaultAllInclusionPolicy(Object reason) {
184205
public void includeMethod(Executable method) {
185206
bb.postTask(debug -> bb.addRootMethod(method, false, reason));
186207
}
208+
209+
@Override
210+
public void includeMethod(AnalysisMethod method) {
211+
bb.postTask(debug -> bb.addRootMethod(method, false, reason));
212+
}
187213
}
188214

189215
protected boolean isAccessible(Member member) {

substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/PointsToAnalysis.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -298,9 +298,9 @@ public AnalysisMethod addRootMethod(Executable method, boolean invokeSpecial, Ob
298298
}
299299

300300
@Override
301-
public AnalysisMethod forcedAddRootMethod(Executable method, boolean invokeSpecial, Object reason, MultiMethod.MultiMethodKey... otherRoots) {
301+
public AnalysisMethod forcedAddRootMethod(AnalysisMethod method, boolean invokeSpecial, Object reason, MultiMethod.MultiMethodKey... otherRoots) {
302302
AnalysisError.guarantee(isBaseLayerAnalysisEnabled());
303-
PointsToAnalysisMethod analysisMethod = assertPointsToAnalysisMethod(metaAccess.lookupJavaMethod(method));
303+
PointsToAnalysisMethod analysisMethod = assertPointsToAnalysisMethod(method);
304304
postTask(ignore -> {
305305
MethodTypeFlow typeFlow = analysisMethod.getTypeFlow();
306306
/*

substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/ReachabilityAnalysis.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ public interface ReachabilityAnalysis {
9797
* @see ReachabilityAnalysis#addRootMethod(AnalysisMethod, boolean, Object,
9898
* MultiMethod.MultiMethodKey...)
9999
*/
100-
AnalysisMethod forcedAddRootMethod(Executable method, boolean invokeSpecial, Object reason, MultiMethod.MultiMethodKey... otherRoots);
100+
AnalysisMethod forcedAddRootMethod(AnalysisMethod method, boolean invokeSpecial, Object reason, MultiMethod.MultiMethodKey... otherRoots);
101101

102102
/**
103103
* Waits until the analysis is done.

substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/heap/ImageLayerLoader.java

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -304,11 +304,11 @@ public class ImageLayerLoader {
304304
protected final Map<Integer, ImageHeapConstant> constants = new ConcurrentHashMap<>();
305305
private final List<Path> loadPaths;
306306
private final Map<Integer, BaseLayerType> baseLayerTypes = new ConcurrentHashMap<>();
307-
private final Map<Integer, Integer> typeToHubIdentityHashCode = new HashMap<>();
307+
private final Map<Integer, Integer> typeToHubIdentityHashCode = new ConcurrentHashMap<>();
308308
private final Map<Integer, BaseLayerMethod> baseLayerMethods = new ConcurrentHashMap<>();
309309

310310
/** Map from the type id to its identifier in the jsonMap. */
311-
private final Map<Integer, String> typeIdToIdentifier = new HashMap<>();
311+
protected final Map<Integer, String> typeIdToIdentifier = new HashMap<>();
312312

313313
/** Map from the method id to its identifier in the jsonMap. */
314314
private final Map<Integer, String> methodIdToIdentifier = new HashMap<>();
@@ -348,6 +348,10 @@ public List<Path> getLoadPaths() {
348348
return loadPaths;
349349
}
350350

351+
public AnalysisUniverse getUniverse() {
352+
return universe;
353+
}
354+
351355
public void setUniverse(AnalysisUniverse newUniverse) {
352356
this.universe = newUniverse;
353357
}
@@ -449,6 +453,10 @@ protected void prepareConstantRelinking(EconomicMap<String, Object> constantData
449453
private void loadType(EconomicMap<String, Object> typeData) {
450454
int tid = get(typeData, ID_TAG);
451455

456+
if (imageLayerLoaderHelper.loadType(typeData, tid)) {
457+
return;
458+
}
459+
452460
String name = get(typeData, CLASS_JAVA_NAME_TAG);
453461
Class<?> clazz = lookupBaseLayerTypeInHostVM(name);
454462

@@ -581,7 +589,7 @@ public void initializeBaseLayerType(AnalysisType type) {
581589
* Tries to look up the base layer type in the current VM. Some types cannot be looked up by
582590
* name (for example $$Lambda types), so this method can return null.
583591
*/
584-
public static Class<?> lookupBaseLayerTypeInHostVM(String type) {
592+
public Class<?> lookupBaseLayerTypeInHostVM(String type) {
585593
int arrayType = 0;
586594
String componentType = type;
587595
/*
@@ -594,7 +602,7 @@ public static Class<?> lookupBaseLayerTypeInHostVM(String type) {
594602
}
595603
Class<?> clazz = lookupPrimitiveClass(componentType);
596604
if (clazz == null) {
597-
clazz = ReflectionUtil.lookupClass(true, componentType);
605+
clazz = lookupClass(true, componentType);
598606
}
599607
if (clazz == null) {
600608
return null;
@@ -637,7 +645,7 @@ private void loadMethod(EconomicMap<String, Object> methodData) {
637645
Executable method = null;
638646
Class<?> clazz = lookupBaseLayerTypeInHostVM(className);
639647
if (clazz != null) {
640-
Class<?>[] argumentClasses = arguments.stream().map(ImageLayerLoader::lookupBaseLayerTypeInHostVM).toList().toArray(new Class<?>[0]);
648+
Class<?>[] argumentClasses = arguments.stream().map(this::lookupBaseLayerTypeInHostVM).toList().toArray(new Class<?>[0]);
641649
method = lookupMethodByReflection(name, clazz, argumentClasses);
642650
}
643651

@@ -680,13 +688,17 @@ private void loadMethod(EconomicMap<String, Object> methodData) {
680688
}
681689

682690
private static Executable lookupMethodByReflection(String name, Class<?> clazz, Class<?>[] argumentClasses) {
683-
Executable method;
684-
if (name.equals(CONSTRUCTOR_NAME)) {
685-
method = ReflectionUtil.lookupConstructor(true, clazz, argumentClasses);
686-
} else {
687-
method = ReflectionUtil.lookupMethod(true, clazz, name, argumentClasses);
691+
try {
692+
Executable method;
693+
if (name.equals(CONSTRUCTOR_NAME)) {
694+
method = ReflectionUtil.lookupConstructor(true, clazz, argumentClasses);
695+
} else {
696+
method = ReflectionUtil.lookupMethod(true, clazz, name, argumentClasses);
697+
}
698+
return method;
699+
} catch (NoClassDefFoundError e) {
700+
return null;
688701
}
689-
return method;
690702
}
691703

692704
private void createBaseLayerMethod(EconomicMap<String, Object> methodData, int mid, String name) {
@@ -1277,14 +1289,18 @@ private EconomicMap<String, Object> getElementData(String registry, String eleme
12771289
}
12781290

12791291
@SuppressWarnings("unchecked")
1280-
protected static Enum<?> getEnumValue(EconomicMap<String, Object> enumData) {
1292+
protected Enum<?> getEnumValue(EconomicMap<String, Object> enumData) {
12811293
String className = get(enumData, ENUM_CLASS_TAG);
1282-
Class<?> enumClass = ReflectionUtil.lookupClass(false, className);
1294+
Class<?> enumClass = lookupClass(false, className);
12831295
String name = get(enumData, ENUM_NAME_TAG);
12841296
/* asSubclass produces an "unchecked" warning */
12851297
return Enum.valueOf(enumClass.asSubclass(Enum.class), name);
12861298
}
12871299

1300+
public Class<?> lookupClass(boolean optional, String className) {
1301+
return ReflectionUtil.lookupClass(optional, className);
1302+
}
1303+
12881304
public static <T> T get(EconomicMap<String, Object> innerMap, String elementIdentifier) {
12891305
return cast(innerMap.get(elementIdentifier));
12901306
}

substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/heap/ImageLayerLoaderHelper.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,11 @@ public ImageLayerLoaderHelper(ImageLayerLoader imageLayerLoader) {
3333
this.imageLayerLoader = imageLayerLoader;
3434
}
3535

36+
@SuppressWarnings("unused")
37+
protected boolean loadType(EconomicMap<String, Object> typeData, int tid) {
38+
return false;
39+
}
40+
3641
@SuppressWarnings("unused")
3742
protected boolean loadMethod(EconomicMap<String, Object> methodData, int mid) {
3843
return false;

substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/heap/ImageLayerSnapshotUtil.java

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,10 @@ public class ImageLayerSnapshotUtil {
102102
public static final String COMPONENT_TYPE_TAG = "component type";
103103
public static final String SUPER_CLASS_TAG = "super class";
104104
public static final String INTERFACES_TAG = "interfaces";
105+
public static final String WRAPPED_TYPE_TAG = "wrapped type";
106+
public static final String GENERATED_SERIALIZATION_TAG = "generated serialization";
107+
public static final String RAW_DECLARING_CLASS_TAG = "raw declaring class";
108+
public static final String RAW_TARGET_CONSTRUCTOR_CLASS_TAG = "raw target constructor class";
105109
public static final String CONSTANTS_TAG = "constants";
106110
public static final String CONSTANTS_TO_RELINK_TAG = "constants to relink";
107111
public static final String TID_TAG = "tid";
@@ -110,7 +114,7 @@ public class ImageLayerSnapshotUtil {
110114
public static final String ARGUMENT_IDS_TAG = "argument ids";
111115
public static final String RETURN_TYPE_TAG = "return type";
112116
public static final String IS_VAR_ARGS_TAG = "is varArg";
113-
public static final String METHOD_TYPE_TAG = "method type";
117+
public static final String WRAPPED_METHOD_TAG = "wrapped method";
114118
public static final String METHOD_TYPE_PARAMETERS_TAG = "method type parameters";
115119
public static final String METHOD_TYPE_RETURN_TAG = "method type return";
116120
public static final String FACTORY_TAG = "factory";
@@ -120,6 +124,16 @@ public class ImageLayerSnapshotUtil {
120124
public static final String IDENTITY_HASH_CODE_TAG = "identityHashCode";
121125
public static final String HUB_IDENTITY_HASH_CODE_TAG = "hub identityHashCode";
122126
public static final String IS_INITIALIZED_AT_BUILD_TIME_TAG = "is initialized at build time";
127+
public static final String IS_NO_INITIALIZER_NO_TRACKING_TAG = "in no initializer no tracking";
128+
public static final String IS_INITIALIZED_NO_TRACKING_TAG = "is initialized no tracking";
129+
public static final String IS_FAILED_NO_TRACKING_TAG = "is failed no tracking";
130+
public static final String INFO_IS_INITIALIZED_TAG = "info is initialized";
131+
public static final String INFO_IS_IN_ERROR_STATE_TAG = "info is in error state";
132+
public static final String INFO_IS_LINKED_TAG = "info is linked";
133+
public static final String INFO_HAS_INITIALIZER_TAG = "info has initializer";
134+
public static final String INFO_IS_BUILD_TIME_INITIALIZED_TAG = "info is build time initialized";
135+
public static final String INFO_IS_TRACKED_TAG = "info is tracked";
136+
public static final String INFO_CLASS_INITIALIZER_TAG = "info class initializer";
123137
public static final String ID_TAG = "id";
124138
public static final String ANALYSIS_PARSED_GRAPH_TAG = "analysis parsed graph";
125139
public static final String STRENGTHENED_GRAPH_TAG = "strengthened graph";
@@ -234,9 +248,12 @@ public GraphEncoder(List<Field> externalValues, ImageLayerWriter imageLayerWrite
234248
}
235249

236250
public static class GraphDecoder extends ObjectCopier.Decoder {
251+
private final ImageLayerLoader imageLayerLoader;
252+
237253
@SuppressWarnings("this-escape")
238254
public GraphDecoder(ClassLoader classLoader, ImageLayerLoader imageLayerLoader, AnalysisMethod analysisMethod) {
239255
super(classLoader);
256+
this.imageLayerLoader = imageLayerLoader;
240257
addBuiltin(new NodeClassBuiltIn());
241258
addBuiltin(new ImageHeapConstantBuiltIn(null, imageLayerLoader));
242259
addBuiltin(new AnalysisTypeBuiltIn(null, imageLayerLoader));
@@ -245,6 +262,11 @@ public GraphDecoder(ClassLoader classLoader, ImageLayerLoader imageLayerLoader,
245262
addBuiltin(new FieldLocationIdentityBuiltIn(null, imageLayerLoader));
246263
addBuiltin(new NamedLocationIdentityArrayBuiltIn());
247264
}
265+
266+
@Override
267+
public Class<?> loadClass(String className) {
268+
return imageLayerLoader.lookupClass(false, className);
269+
}
248270
}
249271

250272
public static class NodeClassBuiltIn extends ObjectCopier.Builtin {

substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/heap/ImageLayerWriter.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,8 @@ protected void persistType(AnalysisType type, EconomicMap<String, Object> typeMa
314314
typeMap.put(IS_INSTANTIATED, type.isInstantiated());
315315
typeMap.put(IS_UNSAFE_ALLOCATED, type.isUnsafeAllocated());
316316
typeMap.put(IS_REACHABLE, type.isReachable());
317+
318+
imageLayerWriterHelper.persistType(type, typeMap);
317319
}
318320

319321
/**

0 commit comments

Comments
 (0)