Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions substratevm/mx.substratevm/suite.py
Original file line number Diff line number Diff line change
Expand Up @@ -2421,6 +2421,7 @@
"name" : "org.graalvm.nativeimage.pointsto.standalone",
"exports" : [
"com.oracle.graal.pointsto.standalone",
"com.oracle.graal.pointsto.standalone.plugins",
],
"requires": [
"java.management",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,14 @@

package com.oracle.graal.pointsto.standalone.test;

import org.junit.Test;
import static org.junit.Assert.assertTrue;

import java.io.File;
import java.io.IOException;
import java.nio.file.Path;

import static org.junit.Assert.assertTrue;
import org.junit.Ignore;
import org.junit.Test;

public class StandaloneAnalysisReportTest {
// Take an arbitrary case for this test
Expand All @@ -58,6 +59,8 @@ public void testPrintAnalysisCallTree() throws IOException {
}

@Test
@Ignore // Since there is no class initialization, printing the object tree is not a meaningful
// operation at the moment.
public void testPrintAnalysisObjectTree() throws IOException {
PointstoAnalyzerTester tester = new PointstoAnalyzerTester(TEST_CLASS);
Path testTmpDir = tester.createTestTmpDir();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,16 +120,18 @@ private PointsToAnalyzer(String mainEntryClass, OptionValues options, ClassLoade
SnippetReflectionProvider snippetReflection = originalProviders.getSnippetReflection();
MetaAccessProvider originalMetaAccess = originalProviders.getMetaAccess();
debugContext = new DebugContext.Builder(options, new GraalDebugHandlersFactory(snippetReflection)).build();
StandaloneHost standaloneHost = new StandaloneHost(options);
analysisName = getAnalysisName(mainEntryClass);
StandaloneHost standaloneHost = new StandaloneHost(options, analysisName, false, true);
AnalysisPolicy analysisPolicy = PointstoOptions.AllocationSiteSensitiveHeap.getValue(options) ? new BytecodeSensitiveAnalysisPolicy(options)
: new DefaultAnalysisPolicy(options);

JavaKind wordKind = originalProviders.getWordTypes().getWordKind();
AnalysisUniverse aUniverse = new AnalysisUniverse(standaloneHost, wordKind,
analysisPolicy, SubstitutionProcessor.IDENTITY, originalMetaAccess, new PointsToAnalysisFactory(), new StandaloneAnnotationExtractor());
AnalysisMetaAccess aMetaAccess = new StandaloneAnalysisMetaAccess(aUniverse, originalMetaAccess);
StandaloneConstantReflectionProvider aConstantReflection = new StandaloneConstantReflectionProvider(aUniverse, originalProviders.getConstantReflection());
StandaloneConstantFieldProvider aConstantFieldProvider = new StandaloneConstantFieldProvider(aMetaAccess);
StandaloneConstantReflectionProvider aConstantReflection = new StandaloneConstantReflectionProvider(aMetaAccess, aUniverse, originalProviders.getConstantReflection(),
originalProviders.getSnippetReflection());
StandaloneConstantFieldProvider aConstantFieldProvider = new StandaloneConstantFieldProvider(aMetaAccess, originalProviders.getConstantFieldProvider(), false);
AnalysisMetaAccessExtensionProvider aMetaAccessExtensionProvider = new AnalysisMetaAccessExtensionProvider(aUniverse);
HostedProviders aProviders = new HostedProviders(aMetaAccess, null, aConstantReflection, aConstantFieldProvider,
originalProviders.getForeignCalls(), originalProviders.getLowerer(), null,
Expand All @@ -138,11 +140,9 @@ private PointsToAnalyzer(String mainEntryClass, OptionValues options, ClassLoade
Replacements replacements = new StandaloneReplacementsImpl(aProviders, new ResolvedJavaMethodBytecodeProvider(), originalProviders.getCodeCache().getTarget());
aProviders = aProviders.copyWith(replacements);
standaloneHost.initializeProviders(aProviders);
analysisName = getAnalysisName(mainEntryClass);
ClassInclusionPolicy classInclusionPolicy = new ClassInclusionPolicy.DefaultAllInclusionPolicy("Included in the base image");
bigbang = new StandalonePointsToAnalysis(options, aUniverse, standaloneHost, aMetaAccess, snippetReflection, aConstantReflection, aProviders.getWordTypes(),
debugContext, new TimerCollection(), classInclusionPolicy);
standaloneHost.setImageName(analysisName);
aUniverse.setBigBang(bigbang);
ImageHeap heap = new ImageHeap();
HostedValuesProvider hostedValuesProvider = new HostedValuesProvider(aMetaAccess, aUniverse);
Expand Down Expand Up @@ -323,11 +323,10 @@ public int run() {
registerEntryMethods();
registerFeatures();
int exitCode = 0;
Feature.BeforeAnalysisAccess beforeAnalysisAccess = new StandaloneAnalysisFeatureImpl.BeforeAnalysisAccessImpl(standaloneAnalysisFeatureManager, classLoaderAccess, bigbang, debugContext);
Feature.BeforeAnalysisAccess beforeAnalysisAccess = new StandaloneAnalysisFeatureImpl.BeforeAnalysisAccessImpl(bigbang);
standaloneAnalysisFeatureManager.forEachFeature(feature -> feature.beforeAnalysis(beforeAnalysisAccess));
try (Timer t = new Timer("analysis", analysisName)) {
StandaloneAnalysisFeatureImpl.DuringAnalysisAccessImpl config = new StandaloneAnalysisFeatureImpl.DuringAnalysisAccessImpl(standaloneAnalysisFeatureManager, classLoaderAccess, bigbang,
debugContext);
StandaloneAnalysisFeatureImpl.DuringAnalysisAccessImpl config = new StandaloneAnalysisFeatureImpl.DuringAnalysisAccessImpl(bigbang);
bigbang.getUniverse().setConcurrentAnalysisAccess(config);
bigbang.runAnalysis(debugContext, (analysisUniverse) -> {
bigbang.getHostVM().notifyClassReachabilityListener(analysisUniverse, config);
Expand All @@ -338,7 +337,7 @@ public int run() {
reportException(e);
exitCode = 1;
}
onAnalysisExitAccess = new StandaloneAnalysisFeatureImpl.OnAnalysisExitAccessImpl(standaloneAnalysisFeatureManager, classLoaderAccess, bigbang, debugContext);
onAnalysisExitAccess = new StandaloneAnalysisFeatureImpl.OnAnalysisExitAccessImpl(bigbang);
standaloneAnalysisFeatureManager.forEachFeature(feature -> feature.onAnalysisExit(onAnalysisExitAccess));
AnalysisReporter.printAnalysisReports("pointsto_" + analysisName, options, StandaloneOptions.reportsPath(options, "reports").toString(), bigbang);
bigbang.getUnsupportedFeatures().report(bigbang);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,19 @@
package com.oracle.graal.pointsto.standalone;

import java.util.Comparator;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;

import com.oracle.graal.pointsto.BigBang;
import com.oracle.graal.pointsto.api.HostVM;
import com.oracle.graal.pointsto.meta.AnalysisMethod;
import com.oracle.graal.pointsto.meta.AnalysisType;
import com.oracle.graal.pointsto.meta.HostedProviders;
import com.oracle.graal.pointsto.standalone.plugins.StandaloneGraphBuilderPhase;
import com.oracle.graal.pointsto.util.AnalysisError;

import jdk.graal.compiler.core.common.spi.ForeignCallDescriptor;
import jdk.graal.compiler.core.common.spi.ForeignCallsProvider;
import jdk.graal.compiler.java.GraphBuilderPhase;
import jdk.graal.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
import jdk.graal.compiler.nodes.graphbuilderconf.IntrinsicContext;
Expand All @@ -46,10 +50,21 @@
public class StandaloneHost extends HostVM {
private final ConcurrentHashMap<AnalysisType, Class<?>> typeToClass = new ConcurrentHashMap<>();
private final ConcurrentHashMap<Class<?>, AnalysisType> classToType = new ConcurrentHashMap<>();
private String imageName;
private final String imageName;
/*
* By default, there is no eager class initialization nor delayed class initialization in
* standalone analysis, so we don't need do any actual class initialization work here. Setting
* this field to true changes that behavior and allows class initialization.
*/
private final boolean initializeClasses;

public StandaloneHost(OptionValues options) {
private final boolean isClosedTypeWorld;

public StandaloneHost(OptionValues options, String imageName, boolean initializeClasses, boolean isClosedTypeWorld) {
super(options, /*- ClassLoader not supported. */ null);
this.imageName = imageName;
this.initializeClasses = initializeClasses;
this.isClosedTypeWorld = isClosedTypeWorld;
}

@Override
Expand Down Expand Up @@ -79,13 +94,10 @@ public boolean isInitialized(AnalysisType type) {

@Override
public void onTypeReachable(BigBang bb, AnalysisType type) {
if (!type.isReachable()) {
AnalysisError.shouldNotReachHere("Registering and initializing a type that was not yet marked as reachable: " + type);
AnalysisError.guarantee(type.isReachable(), "Registering and initializing a type that was not yet marked as reachable: %s", type.toJavaName());
if (initializeClasses) {
type.getWrapped().initialize();
}
/*
* There is no eager class initialization nor delayed class initialization in standalone
* analysis, so we don't need do any actual class initialization work here.
*/
}

@Override
Expand All @@ -94,17 +106,23 @@ public GraphBuilderPhase.Instance createGraphBuilderPhase(HostedProviders builde
return new StandaloneGraphBuilderPhase.Instance(builderProviders, graphBuilderConfig, optimisticOpts, initialIntrinsicContext);
}

public void setImageName(String name) {
imageName = name;
}

@Override
public String getImageName() {
return imageName;
}

@Override
public Comparator<? super ResolvedJavaType> getTypeComparator() {
return null;
throw new UnsupportedOperationException();
}

@Override
public Optional<AnalysisMethod> handleForeignCall(ForeignCallDescriptor foreignCallDescriptor, ForeignCallsProvider foreignCallsProvider) {
throw AnalysisError.shouldNotReachHere("StandaloneHost.handleForeignCall");
}

@Override
public boolean isClosedTypeWorld() {
return isClosedTypeWorld;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,23 +48,13 @@
import com.oracle.graal.pointsto.meta.AnalysisMethod;
import com.oracle.graal.pointsto.meta.AnalysisType;
import com.oracle.graal.pointsto.meta.AnalysisUniverse;
import com.oracle.graal.pointsto.standalone.PointsToAnalyzer;
import com.oracle.graal.pointsto.standalone.StandaloneHost;
import com.oracle.graal.pointsto.util.AnalysisError;

import jdk.graal.compiler.debug.DebugContext;

public class StandaloneAnalysisFeatureImpl {
public abstract static class FeatureAccessImpl implements Feature.FeatureAccess {

protected final StandaloneAnalysisFeatureManager featureManager;
protected final PointsToAnalyzer.ClassLoaderAccess classLoaderAccess;
protected final DebugContext debugContext;

FeatureAccessImpl(StandaloneAnalysisFeatureManager featureManager, PointsToAnalyzer.ClassLoaderAccess classLoaderAccess, DebugContext debugContext) {
this.featureManager = featureManager;
this.classLoaderAccess = classLoaderAccess;
this.debugContext = debugContext;
FeatureAccessImpl() {
}

@Deprecated
Expand Down Expand Up @@ -94,8 +84,8 @@ abstract static class AnalysisAccessBase extends FeatureAccessImpl {

protected final BigBang bb;

AnalysisAccessBase(StandaloneAnalysisFeatureManager featureManager, PointsToAnalyzer.ClassLoaderAccess classLoaderAccess, BigBang bb, DebugContext debugContext) {
super(featureManager, classLoaderAccess, debugContext);
AnalysisAccessBase(BigBang bb) {
super();
this.bb = bb;
}

Expand Down Expand Up @@ -161,8 +151,8 @@ Set<AnalysisMethod> reachableMethodOverrides(AnalysisMethod baseMethod) {

public static class BeforeAnalysisAccessImpl extends AnalysisAccessBase implements Feature.BeforeAnalysisAccess {

public BeforeAnalysisAccessImpl(StandaloneAnalysisFeatureManager featureManager, PointsToAnalyzer.ClassLoaderAccess classLoaderAccess, BigBang bb, DebugContext debugContext) {
super(featureManager, classLoaderAccess, bb, debugContext);
public BeforeAnalysisAccessImpl(BigBang bb) {
super(bb);
}

@Override
Expand Down Expand Up @@ -263,8 +253,8 @@ public static class DuringAnalysisAccessImpl extends BeforeAnalysisAccessImpl im

private boolean requireAnalysisIteration;

public DuringAnalysisAccessImpl(StandaloneAnalysisFeatureManager featureManager, PointsToAnalyzer.ClassLoaderAccess classLoaderAccess, BigBang bb, DebugContext debugContext) {
super(featureManager, classLoaderAccess, bb, debugContext);
public DuringAnalysisAccessImpl(BigBang bb) {
super(bb);
}

@Override
Expand All @@ -283,8 +273,8 @@ public static class OnAnalysisExitAccessImpl extends AnalysisAccessBase implemen

private final Map<Class<? extends Feature>, Object> analysisResults = new HashMap<>();

public OnAnalysisExitAccessImpl(StandaloneAnalysisFeatureManager featureManager, PointsToAnalyzer.ClassLoaderAccess classLoaderAccess, BigBang bb, DebugContext debugContext) {
super(featureManager, classLoaderAccess, bb, debugContext);
public OnAnalysisExitAccessImpl(BigBang bb) {
super(bb);
}

public void setAnalysisResult(Class<? extends Feature> feature, Object result) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,23 +26,56 @@

package com.oracle.graal.pointsto.standalone.meta;

import com.oracle.graal.pointsto.meta.AnalysisField;

import jdk.graal.compiler.core.common.spi.ConstantFieldProvider;
import jdk.graal.compiler.core.common.spi.JavaConstantFieldProvider;
import jdk.graal.compiler.nodes.spi.CanonicalizerTool;
import jdk.vm.ci.meta.MetaAccessProvider;
import jdk.vm.ci.meta.ResolvedJavaField;
import jdk.graal.compiler.core.common.spi.JavaConstantFieldProvider;

public class StandaloneConstantFieldProvider extends JavaConstantFieldProvider {

public StandaloneConstantFieldProvider(MetaAccessProvider metaAccess) {
private final ConstantFieldProvider originalConstantFieldProvider;
/**
* In the default standalone mode configuration, this field is set to false and all classes are
* runtime initialized. We take all fields as not final, so that it doesn't read field value
* from current environment. Test com.oracle.graal.pointsto.test.ConstantFieldTest verifies this
* method.
**/
private final boolean foldFinalFields;

public StandaloneConstantFieldProvider(MetaAccessProvider metaAccess, ConstantFieldProvider originalConstantFieldProvider, boolean foldFinalFields) {
super(metaAccess);
this.originalConstantFieldProvider = originalConstantFieldProvider;
this.foldFinalFields = foldFinalFields;
}

@Override
public <T> T readConstantField(ResolvedJavaField f, ConstantFieldTool<T> tool) {
AnalysisField field = (AnalysisField) f;

/*
* Ideally, we would mark the type as reachable only when the field is final or stable,
* i.e., there is an actual chance of constant folding it. But for the purpose of the
* analysis tests, it does not matter if we mark a few types too many as reachable.
*/
field.getDeclaringClass().registerAsReachable(field);

T foldedValue = originalConstantFieldProvider.readConstantField(field.wrapped, tool);
if (foldedValue != null) {
field.registerAsFolded(tool.getReason());
}
return foldedValue;
}

@Override
public boolean isTrustedFinal(CanonicalizerTool tool, ResolvedJavaField field) {
return foldFinalFields && originalConstantFieldProvider.isTrustedFinal(tool, field);
}

/**
* In standalone mode, all classes are runtime initialized. We take all fields as not final, so
* that it doesn't read field value from current environment. Test
* com.oracle.graal.pointsto.test.ConstantFieldTest verifies this method.
**/
@Override
public boolean isFinalField(ResolvedJavaField field, ConstantFieldTool<?> tool) {
return false;
return foldFinalFields && super.isFinalField(field, tool);
}
}
Loading