use of org.graalvm.nativeimage.hosted.Feature in project graal by oracle.
the class FeatureHandler method registerFeatures.
@SuppressWarnings("unchecked")
public void registerFeatures(ImageClassLoader loader, DebugContext debug) {
IsInConfigurationAccessImpl access = new IsInConfigurationAccessImpl(this, loader, debug);
LinkedHashSet<Class<?>> automaticFeatures = new LinkedHashSet<>(loader.findAnnotatedClasses(AutomaticFeature.class, true));
Map<Class<?>, Class<?>> specificAutomaticFeatures = new HashMap<>();
for (Class<?> automaticFeature : automaticFeatures) {
Class<Feature> mostSpecific = (Class<Feature>) automaticFeature;
boolean foundMostSpecific = false;
do {
List<Class<? extends Feature>> featureSubclasses = loader.findSubclasses(mostSpecific, true);
featureSubclasses.remove(mostSpecific);
featureSubclasses.removeIf(o -> !automaticFeatures.contains(o));
if (featureSubclasses.isEmpty()) {
foundMostSpecific = true;
} else {
if (featureSubclasses.size() > 1) {
String candidates = featureSubclasses.stream().map(Class::getName).collect(Collectors.joining(" "));
VMError.shouldNotReachHere("Ambiguous @AutomaticFeature extension. Conflicting candidates: " + candidates);
}
mostSpecific = (Class<Feature>) featureSubclasses.get(0);
}
} while (!foundMostSpecific);
if (mostSpecific != automaticFeature) {
specificAutomaticFeatures.put(automaticFeature, mostSpecific);
}
}
/* Remove specific since they get registered via their base */
for (Class<?> specific : specificAutomaticFeatures.values()) {
automaticFeatures.remove(specific);
}
Function<Class<?>, Class<?>> specificClassProvider = specificAutomaticFeatures::get;
for (Class<?> featureClass : automaticFeatures) {
registerFeature(featureClass, specificClassProvider, access);
}
for (String featureName : OptionUtils.flatten(",", Options.Features.getValue())) {
try {
registerFeature(Class.forName(featureName, true, loader.getClassLoader()), specificClassProvider, access);
} catch (ClassNotFoundException e) {
throw UserError.abort("Feature %s class not found on the classpath. Ensure that the name is correct and that the class is on the classpath.", featureName);
}
}
if (NativeImageOptions.PrintFeatures.getValue()) {
ReportUtils.report("feature information", SubstrateOptions.reportsPath(), "feature_info", "csv", out -> {
out.println("Feature, Required Features");
for (Feature featureInstance : featureInstances) {
out.print(featureInstance.getClass().getTypeName());
String requiredFeaturesString = featureInstance.getRequiredFeatures().stream().map(Class::getTypeName).collect(Collectors.joining(" ", "[", "]"));
out.print(", ");
out.println(requiredFeaturesString);
}
});
}
}
use of org.graalvm.nativeimage.hosted.Feature in project graal by oracle.
the class NativeImageGenerator method doRun.
@SuppressWarnings("try")
private void doRun(Map<Method, CEntryPointData> entryPoints, JavaMainSupport javaMainSupport, String imageName, NativeImageKind k, SubstitutionProcessor harnessSubstitutions, ForkJoinPool compilationExecutor, ForkJoinPool analysisExecutor) {
List<HostedMethod> hostedEntryPoints = new ArrayList<>();
OptionValues options = HostedOptionValues.singleton();
SnippetReflectionProvider originalSnippetReflection = GraalAccess.getOriginalSnippetReflection();
try (DebugContext debug = new Builder(options, new GraalDebugHandlersFactory(originalSnippetReflection)).build();
DebugCloseable featureCleanup = () -> featureHandler.forEachFeature(Feature::cleanup)) {
setupNativeImage(imageName, options, entryPoints, javaMainSupport, harnessSubstitutions, analysisExecutor, originalSnippetReflection, debug);
reporter.printFeatures(featureHandler.getUserFeatureNames());
boolean returnAfterAnalysis = runPointsToAnalysis(imageName, options, debug);
if (returnAfterAnalysis) {
return;
}
NativeImageHeap heap;
HostedMetaAccess hMetaAccess;
SharedRuntimeConfigurationBuilder runtime;
try (ReporterClosable c = reporter.printUniverse()) {
bb.getHeartbeatCallback().run();
hUniverse = new HostedUniverse(bb);
hMetaAccess = new HostedMetaAccess(hUniverse, bb.getMetaAccess());
((SVMImageHeapScanner) aUniverse.getHeapScanner()).setHostedMetaAccess(hMetaAccess);
BeforeUniverseBuildingAccessImpl beforeUniverseBuildingConfig = new BeforeUniverseBuildingAccessImpl(featureHandler, loader, debug, hMetaAccess);
featureHandler.forEachFeature(feature -> feature.beforeUniverseBuilding(beforeUniverseBuildingConfig));
new UniverseBuilder(aUniverse, bb.getMetaAccess(), hUniverse, hMetaAccess, HostedConfiguration.instance().createStaticAnalysisResultsBuilder(bb, hUniverse), bb.getUnsupportedFeatures()).build(debug);
BuildPhaseProvider.markHostedUniverseBuilt();
ClassInitializationSupport classInitializationSupport = bb.getHostVM().getClassInitializationSupport();
runtime = new HostedRuntimeConfigurationBuilder(options, bb.getHostVM(), hUniverse, hMetaAccess, bb.getProviders(), nativeLibraries, classInitializationSupport, GraalAccess.getOriginalProviders().getLoopsDataProvider()).build();
registerGraphBuilderPlugins(featureHandler, runtime.getRuntimeConfig(), (HostedProviders) runtime.getRuntimeConfig().getProviders(), bb.getMetaAccess(), aUniverse, hMetaAccess, hUniverse, nativeLibraries, loader, ParsingReason.AOTCompilation, bb.getAnnotationSubstitutionProcessor(), new SubstrateClassInitializationPlugin((SVMHost) aUniverse.hostVM()), classInitializationSupport, ConfigurationValues.getTarget());
if (NativeImageOptions.PrintUniverse.getValue()) {
printTypes();
}
/* Find the entry point methods in the hosted world. */
for (AnalysisMethod m : aUniverse.getMethods()) {
if (m.isEntryPoint()) {
HostedMethod found = hUniverse.lookup(m);
assert found != null;
hostedEntryPoints.add(found);
}
}
if (hostedEntryPoints.size() == 0) {
throw UserError.abort("Warning: no entry points found, i.e., no method annotated with @%s", CEntryPoint.class.getSimpleName());
}
bb.getUnsupportedFeatures().report(bb);
recordRestrictHeapAccessCallees(aUniverse.getMethods());
/*
* After this point, all TypeFlow (and therefore also TypeState) objects are
* unreachable and can be garbage collected. This is important to keep the overall
* memory footprint low. However, this also means we no longer have complete call
* chain information. Only the summarized information stored in the
* StaticAnalysisResult objects is available after this point.
*/
bb.cleanupAfterAnalysis();
} catch (UnsupportedFeatureException ufe) {
throw FallbackFeature.reportAsFallback(ufe);
}
heap = new NativeImageHeap(aUniverse, hUniverse, hMetaAccess, ImageSingletons.lookup(ImageHeapLayouter.class));
BeforeCompilationAccessImpl beforeCompilationConfig = new BeforeCompilationAccessImpl(featureHandler, loader, aUniverse, hUniverse, heap, debug, runtime);
featureHandler.forEachFeature(feature -> feature.beforeCompilation(beforeCompilationConfig));
runtime.updateLazyState(hMetaAccess);
NativeImageCodeCache codeCache;
CompileQueue compileQueue;
try (StopTimer t = TimerCollection.createTimerAndStart(TimerCollection.Registry.COMPILE_TOTAL)) {
compileQueue = HostedConfiguration.instance().createCompileQueue(debug, featureHandler, hUniverse, runtime, DeoptTester.enabled(), bb.getProviders().getSnippetReflection(), compilationExecutor);
compileQueue.finish(debug);
/* release memory taken by graphs for the image writing */
hUniverse.getMethods().forEach(HostedMethod::clear);
codeCache = NativeImageCodeCacheFactory.get().newCodeCache(compileQueue, heap, loader.platform, ImageSingletons.lookup(TemporaryBuildDirectoryProvider.class).getTemporaryBuildDirectory());
codeCache.layoutConstants();
codeCache.layoutMethods(debug, imageName, bb, compilationExecutor);
AfterCompilationAccessImpl config = new AfterCompilationAccessImpl(featureHandler, loader, aUniverse, hUniverse, compileQueue.getCompilationTasks(), heap, debug, runtime);
featureHandler.forEachFeature(feature -> feature.afterCompilation(config));
}
CodeCacheProvider codeCacheProvider = runtime.getRuntimeConfig().getBackendForNormalMethod().getProviders().getCodeCache();
reporter.printCreationStart();
try (Indent indent = debug.logAndIndent("create native image")) {
try (DebugContext.Scope buildScope = debug.scope("CreateImage", codeCacheProvider)) {
try (StopTimer t = TimerCollection.createTimerAndStart(TimerCollection.Registry.IMAGE)) {
bb.getHeartbeatCallback().run();
// Start building the model of the native image heap.
heap.addInitialObjects();
// Then build the model of the code cache, which can
// add objects to the native image heap.
codeCache.addConstantsToHeap();
// Finish building the model of the native image heap.
heap.addTrailingObjects();
AfterHeapLayoutAccessImpl config = new AfterHeapLayoutAccessImpl(featureHandler, loader, heap, hMetaAccess, debug);
featureHandler.forEachFeature(feature -> feature.afterHeapLayout(config));
this.image = AbstractImage.create(k, hUniverse, hMetaAccess, nativeLibraries, heap, codeCache, hostedEntryPoints, loader.getClassLoader());
image.build(imageName, debug);
if (NativeImageOptions.PrintUniverse.getValue()) {
/*
* This debug output must be printed _after_ and not _during_ image
* building, because it adds some PrintStream objects to static fields,
* which disrupts the heap.
*/
codeCache.printCompilationResults();
}
}
} catch (Throwable e) {
throw VMError.shouldNotReachHere(e);
}
}
try (StopTimer t = TimerCollection.createTimerAndStart(TimerCollection.Registry.WRITE)) {
bb.getHeartbeatCallback().run();
BeforeImageWriteAccessImpl beforeConfig = new BeforeImageWriteAccessImpl(featureHandler, loader, imageName, image, runtime.getRuntimeConfig(), aUniverse, hUniverse, optionProvider, hMetaAccess, debug);
featureHandler.forEachFeature(feature -> feature.beforeImageWrite(beforeConfig));
/*
* This will write the debug info too -- i.e. we may be writing more than one file,
* if the debug info is in a separate file. We need to push writing the file to the
* image implementation, because whether the debug info and image share a file or
* not is an implementation detail of the image.
*/
Path tmpDir = ImageSingletons.lookup(TemporaryBuildDirectoryProvider.class).getTemporaryBuildDirectory();
LinkerInvocation inv = image.write(debug, generatedFiles(HostedOptionValues.singleton()), tmpDir, imageName, beforeConfig);
if (NativeImageOptions.ExitAfterRelocatableImageWrite.getValue()) {
return;
}
AfterImageWriteAccessImpl afterConfig = new AfterImageWriteAccessImpl(featureHandler, loader, hUniverse, inv, tmpDir, image.getImageKind(), debug);
featureHandler.forEachFeature(feature -> feature.afterImageWrite(afterConfig));
}
reporter.printCreationEnd(image.getImageSize(), bb.getUniverse(), heap.getObjectCount(), image.getImageHeapSize(), codeCache.getCodeCacheSize(), codeCache.getCompilations().size(), image.getDebugInfoSize());
if (SubstrateOptions.BuildOutputBreakdowns.getValue()) {
ProgressReporter.singleton().printBreakdowns(compileQueue.getCompilationTasks(), image.getHeap().getObjects());
}
}
}
use of org.graalvm.nativeimage.hosted.Feature in project graal by oracle.
the class FeatureHandler method registerFeature.
/**
* Instantiates the given feature class and (recursively) all feature classes it requires.
*
* @param access
*/
@SuppressWarnings("unchecked")
private void registerFeature(Class<?> baseFeatureClass, Function<Class<?>, Class<?>> specificClassProvider, IsInConfigurationAccessImpl access) {
if (!Feature.class.isAssignableFrom(baseFeatureClass)) {
throw UserError.abort("Class does not implement %s: %s", Feature.class.getName(), baseFeatureClass.getName());
}
if (registeredFeatures.contains(baseFeatureClass)) {
return;
}
/*
* Immediately add to the registeredFeatures to avoid infinite recursion in case of cyclic
* dependencies.
*/
registeredFeatures.add(baseFeatureClass);
Class<?> specificClass = specificClassProvider.apply(baseFeatureClass);
Class<?> featureClass = specificClass != null ? specificClass : baseFeatureClass;
Feature feature;
try {
feature = (Feature) ReflectionUtil.newInstance(featureClass);
} catch (ReflectionUtilError ex) {
throw UserError.abort(ex.getCause(), "Error instantiating Feature class %s. Ensure the class is not abstract and has a no-argument constructor.", featureClass.getTypeName());
}
if (!feature.isInConfiguration(access)) {
return;
}
/*
* All features are automatically added to the VMConfiguration, to allow convenient
* configuration checks.
*/
ImageSingletons.add((Class<Feature>) baseFeatureClass, feature);
/*
* First add dependent features so that initializers are executed in order of dependencies.
*/
for (Class<? extends Feature> requiredFeatureClass : feature.getRequiredFeatures()) {
registerFeature(requiredFeatureClass, specificClassProvider, access);
}
featureInstances.add(feature);
}
Aggregations