3030import java .lang .reflect .Method ;
3131import java .lang .reflect .Modifier ;
3232import java .lang .reflect .Proxy ;
33+ import java .nio .file .Path ;
34+ import java .util .Collection ;
3335import java .util .Comparator ;
3436import java .util .EnumSet ;
3537import java .util .HashMap ;
4951import org .graalvm .nativeimage .ImageSingletons ;
5052import org .graalvm .nativeimage .Platform ;
5153import org .graalvm .nativeimage .Platforms ;
54+ import org .graalvm .nativeimage .c .constant .CConstant ;
55+ import org .graalvm .nativeimage .c .function .CEntryPoint ;
56+ import org .graalvm .nativeimage .c .function .CLibrary ;
5257import org .graalvm .nativeimage .hosted .Feature ;
5358import org .graalvm .word .WordBase ;
5459
113118import com .oracle .svm .core .util .UserError ;
114119import com .oracle .svm .core .util .VMError ;
115120import com .oracle .svm .hosted .analysis .SVMParsingSupport ;
121+ import com .oracle .svm .hosted .c .libc .HostedLibCBase ;
116122import com .oracle .svm .hosted .classinitialization .ClassInitializationFeature ;
117123import com .oracle .svm .hosted .classinitialization .ClassInitializationOptions ;
118124import com .oracle .svm .hosted .classinitialization .ClassInitializationSupport ;
151157import jdk .graal .compiler .debug .GraalError ;
152158import jdk .graal .compiler .debug .MethodFilter ;
153159import jdk .graal .compiler .graph .Node ;
160+ import jdk .graal .compiler .graph .Node .NodeIntrinsic ;
161+ import jdk .graal .compiler .hotspot .word .HotSpotOperation ;
154162import jdk .graal .compiler .java .GraphBuilderPhase .Instance ;
155163import jdk .graal .compiler .nodes .StaticDeoptimizingNode ;
156164import jdk .graal .compiler .nodes .StructuredGraph ;
157165import jdk .graal .compiler .nodes .ValueNode ;
158166import jdk .graal .compiler .nodes .graphbuilderconf .GraphBuilderConfiguration ;
159167import jdk .graal .compiler .nodes .graphbuilderconf .IntrinsicContext ;
168+ import jdk .graal .compiler .nodes .graphbuilderconf .InvocationPlugins ;
160169import jdk .graal .compiler .options .Option ;
161170import jdk .graal .compiler .options .OptionKey ;
162171import jdk .graal .compiler .options .OptionValues ;
163172import jdk .graal .compiler .phases .OptimisticOptimizations ;
164173import jdk .graal .compiler .phases .common .BoxNodeIdentityPhase ;
165174import jdk .graal .compiler .phases .common .CanonicalizerPhase ;
166175import jdk .graal .compiler .virtual .phases .ea .PartialEscapePhase ;
176+ import jdk .graal .compiler .word .Word .Operation ;
167177import jdk .internal .loader .NativeLibraries ;
168178import jdk .internal .vm .annotation .DontInline ;
169179import jdk .internal .vm .annotation .ForceInline ;
174184import jdk .vm .ci .meta .ResolvedJavaField ;
175185import jdk .vm .ci .meta .ResolvedJavaMethod ;
176186import jdk .vm .ci .meta .ResolvedJavaType ;
187+ import jdk .vm .ci .runtime .JVMCI ;
177188
178189public class SVMHost extends HostVM {
179190 private final ConcurrentHashMap <AnalysisType , DynamicHub > typeToHub = new ConcurrentHashMap <>();
@@ -225,6 +236,9 @@ public enum UsageKind {
225236
226237 private final SymbolEncoder encoder = SymbolEncoder .singleton ();
227238
239+ private com .oracle .svm .hosted .c .NativeLibraries nativeLibraries ;
240+ private Collection <Path > allStaticLibNames ;
241+
228242 private final int layerId ;
229243 private final boolean buildingImageLayer = ImageLayerBuildingSupport .buildingImageLayer ();
230244 private final boolean buildingInitialLayer = ImageLayerBuildingSupport .buildingInitialLayer ();
@@ -246,6 +260,12 @@ public enum UsageKind {
246260 private final boolean trackDynamicAccess ;
247261 private DynamicAccessDetectionSupport dynamicAccessDetectionSupport = null ;
248262
263+ /**
264+ * Some modules contain native methods that should never be in the image, as they are either
265+ * hosted only, or currently unsupported in layered images.
266+ */
267+ private final Set <Module > forbiddenModules = new HashSet <>();
268+
249269 @ SuppressWarnings ("this-escape" )
250270 public SVMHost (OptionValues options , ImageClassLoader loader , ClassInitializationSupport classInitializationSupport , AnnotationSubstitutionProcessor annotationSubstitutions ,
251271 MissingRegistrationSupport missingRegistrationSupport ) {
@@ -1082,12 +1102,7 @@ public boolean isSupportedAnalysisMethod(BigBang bb, AnalysisMethod method) {
10821102 if (!platformSupported (method )) {
10831103 return false ;
10841104 }
1085- /*
1086- * Methods annotated with @Fold should not be included in the base image as they are
1087- * replaced by the invocation plugin with a constant. If reachable in an extension image,
1088- * the plugin will replace it again.
1089- */
1090- if (AnnotationAccess .isAnnotationPresent (method , Fold .class )) {
1105+ if (!isSupportedMethod (bb , method )) {
10911106 return false ;
10921107 }
10931108 return super .isSupportedAnalysisMethod (bb , method );
@@ -1113,12 +1128,70 @@ public boolean isSupportedOriginalMethod(BigBang bb, ResolvedJavaMethod method)
11131128
11141129 /* If the method is substituted we need to check the substitution layer for @Fold. */
11151130 ResolvedJavaMethod substitutionMethod = bb .getUniverse ().getSubstitutions ().lookup (method );
1116- if (AnnotationAccess . isAnnotationPresent ( substitutionMethod , Fold . class )) {
1131+ if (! isSupportedMethod ( bb , method ) || ! isSupportedMethod ( bb , substitutionMethod )) {
11171132 return false ;
11181133 }
11191134 return super .isSupportedOriginalMethod (bb , method );
11201135 }
11211136
1137+ private boolean isSupportedMethod (BigBang bb , ResolvedJavaMethod method ) {
1138+ /*
1139+ * Methods annotated with @Fold should not be included in the base image as they are
1140+ * replaced by the invocation plugin with a constant. If reachable in an extension image,
1141+ * the plugin will replace it again.
1142+ */
1143+ if (AnnotationAccess .isAnnotationPresent (method , Fold .class )) {
1144+ return false ;
1145+ }
1146+
1147+ /* Deleted methods should not be included in the image. */
1148+ if (AnnotationAccess .isAnnotationPresent (method , Delete .class )) {
1149+ return false ;
1150+ }
1151+
1152+ /*
1153+ * Methods whose graph cannot be created should not be in the image. Those methods are
1154+ * compiled in a different way and cannot be included in the same way as normal methods.
1155+ */
1156+ if (AnnotationAccess .isAnnotationPresent (method , CConstant .class ) || AnnotationAccess .isAnnotationPresent (method , Operation .class ) ||
1157+ AnnotationAccess .isAnnotationPresent (method , NodeIntrinsic .class ) || AnnotationAccess .isAnnotationPresent (method , HotSpotOperation .class )) {
1158+ return false ;
1159+ }
1160+
1161+ /* Methods that are not provided in the current Libc should not be included. */
1162+ if (OriginalMethodProvider .getJavaMethod (method ) instanceof Method m && !HostedLibCBase .isMethodProvidedInCurrentLibc (m )) {
1163+ return false ;
1164+ }
1165+
1166+ /* Methods that are not in the native libraries configuration should not be included. */
1167+ if (nativeLibraries == null ) {
1168+ nativeLibraries = com .oracle .svm .hosted .c .NativeLibraries .singleton ();
1169+ allStaticLibNames = nativeLibraries .getAllStaticLibNames ();
1170+ }
1171+ if (!nativeLibraries .isMethodInConfiguration (method )) {
1172+ return false ;
1173+ }
1174+
1175+ /*
1176+ * Methods from a CLibrary that is not included in the static libraries of the image should
1177+ * not be included.
1178+ */
1179+ CLibrary cLibrary = nativeLibraries .getCLibrary (method );
1180+ if (cLibrary != null && allStaticLibNames .stream ().noneMatch (lib -> lib .toString ().contains (cLibrary .value ()))) {
1181+ return false ;
1182+ }
1183+
1184+ /* Methods with an invocation plugin should not be included. */
1185+ InvocationPlugins invocationPlugins = getProviders (MultiMethod .ORIGINAL_METHOD ).getGraphBuilderPlugins ().getInvocationPlugins ();
1186+ if (invocationPlugins .lookupInvocation (method , bb .getOptions ()) != null ) {
1187+ return false ;
1188+ }
1189+
1190+ /* CEntryPoint methods should not be included according to their predicate. */
1191+ CEntryPoint cEntryPoint = AnnotationAccess .getAnnotation (method , CEntryPoint .class );
1192+ return cEntryPoint == null || ReflectionUtil .newInstance (cEntryPoint .include ()).getAsBoolean ();
1193+ }
1194+
11221195 /**
11231196 * Check if an {@link AnalysisField} should be included in the image. For checking its
11241197 * annotations we rely on the {@link AnnotationAccess} unwrapping mechanism to include any
@@ -1474,4 +1547,28 @@ public SimulateClassInitializerSupport createSimulateClassInitializerSupport(Ana
14741547 public ConstantExpressionRegistry getConstantExpressionRegistry () {
14751548 return constantExpressionRegistry ;
14761549 }
1550+
1551+ @ Override
1552+ public Set <Module > getForbiddenModules () {
1553+ if (forbiddenModules .isEmpty ()) {
1554+ forbiddenModules .add (JVMCI .class .getModule ());
1555+ Class <?> llvm = ReflectionUtil .lookupClass (true , "com.oracle.svm.shadowed.org.bytedeco.llvm.global.LLVM" );
1556+ if (llvm != null ) {
1557+ forbiddenModules .add (llvm .getModule ());
1558+ }
1559+ Class <?> javacpp = ReflectionUtil .lookupClass (true , "com.oracle.svm.shadowed.org.bytedeco.javacpp.presets.javacpp" );
1560+ if (javacpp != null ) {
1561+ forbiddenModules .add (javacpp .getModule ());
1562+ }
1563+ Class <?> truffle = ReflectionUtil .lookupClass (true , "com.oracle.truffle.polyglot.JDKSupport" );
1564+ if (truffle != null ) {
1565+ forbiddenModules .add (truffle .getModule ());
1566+ }
1567+ Class <?> libGraal = ReflectionUtil .lookupClass (true , "com.oracle.truffle.runtime.hotspot.libgraal.LibGraal" );
1568+ if (libGraal != null ) {
1569+ forbiddenModules .add (libGraal .getModule ());
1570+ }
1571+ }
1572+ return forbiddenModules ;
1573+ }
14771574}
0 commit comments