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
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,27 @@

package com.oracle.graal.pointsto.standalone;

import java.io.File;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ForkJoinPool;

import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.debug.Indent;
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins;
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.phases.util.Providers;
import org.graalvm.compiler.printer.GraalDebugHandlersFactory;
import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
import org.graalvm.compiler.word.WordTypes;
import org.graalvm.nativeimage.hosted.Feature;

import com.oracle.graal.pointsto.AnalysisObjectScanningObserver;
import com.oracle.graal.pointsto.AnalysisPolicy;
import com.oracle.graal.pointsto.PointsToAnalysis;
Expand Down Expand Up @@ -53,30 +74,11 @@
import com.oracle.graal.pointsto.util.TimerCollection;
import com.oracle.svm.util.ModuleSupport;
import com.oracle.svm.util.ReflectionUtil;

import jdk.vm.ci.amd64.AMD64Kind;
import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime;
import jdk.vm.ci.meta.JavaKind;
import jdk.vm.ci.meta.MetaAccessProvider;
import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.debug.Indent;
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins;
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.phases.util.Providers;
import org.graalvm.compiler.printer.GraalDebugHandlersFactory;
import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
import org.graalvm.compiler.word.WordTypes;
import org.graalvm.nativeimage.hosted.Feature;

import java.io.File;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ForkJoinPool;

public final class PointsToAnalyzer {

Expand Down Expand Up @@ -169,14 +171,14 @@ private PointsToAnalyzer(String mainEntryClass, OptionValues options) {
* good example.
*/
try (Indent ignored = debugContext.logAndIndent("add initial classes/fields/methods")) {
bigbang.addRootClass(Object.class, false, false).registerAsInHeap();
bigbang.addRootClass(String.class, false, false).registerAsInHeap();
bigbang.addRootClass(String[].class, false, false).registerAsInHeap();
bigbang.addRootField(String.class, "value").registerAsInHeap();
bigbang.addRootClass(long[].class, false, false).registerAsInHeap();
bigbang.addRootClass(byte[].class, false, false).registerAsInHeap();
bigbang.addRootClass(byte[][].class, false, false).registerAsInHeap();
bigbang.addRootClass(Object[].class, false, false).registerAsInHeap();
bigbang.addRootClass(Object.class, false, false).registerAsInHeap("Root class.");
bigbang.addRootClass(String.class, false, false).registerAsInHeap("Root class.");
bigbang.addRootClass(String[].class, false, false).registerAsInHeap("Root class.");
bigbang.addRootField(String.class, "value").registerAsInHeap("Root class.");
bigbang.addRootClass(long[].class, false, false).registerAsInHeap("Root class.");
bigbang.addRootClass(byte[].class, false, false).registerAsInHeap("Root class.");
bigbang.addRootClass(byte[][].class, false, false).registerAsInHeap("Root class.");
bigbang.addRootClass(Object[].class, false, false).registerAsInHeap("Root class.");

bigbang.addRootMethod(ReflectionUtil.lookupMethod(Object.class, "getClass"), true);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,18 +26,6 @@

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

import com.oracle.graal.pointsto.BigBang;
import com.oracle.graal.pointsto.meta.AnalysisField;
import com.oracle.graal.pointsto.meta.AnalysisMetaAccess;
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.StandaloneHost;
import com.oracle.svm.util.UnsafePartitionKind;
import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.nativeimage.hosted.Feature;
import org.graalvm.nativeimage.hosted.FieldValueTransformer;

import java.lang.reflect.Executable;
import java.lang.reflect.Field;
import java.nio.file.Path;
Expand All @@ -50,6 +38,19 @@
import java.util.function.Consumer;
import java.util.stream.Collectors;

import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.nativeimage.hosted.Feature;
import org.graalvm.nativeimage.hosted.FieldValueTransformer;

import com.oracle.graal.pointsto.BigBang;
import com.oracle.graal.pointsto.meta.AnalysisField;
import com.oracle.graal.pointsto.meta.AnalysisMetaAccess;
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.StandaloneHost;
import com.oracle.svm.util.UnsafePartitionKind;

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

Expand Down Expand Up @@ -175,11 +176,11 @@ public void registerAsUsed(AnalysisType aType) {

@Override
public void registerAsInHeap(Class<?> clazz) {
registerAsInHeap(getMetaAccess().lookupJavaType(clazz));
registerAsInHeap(getMetaAccess().lookupJavaType(clazz), "Registered from Feature API.");
}

public void registerAsInHeap(AnalysisType aType) {
aType.registerAsInHeap();
public void registerAsInHeap(AnalysisType aType, Object reason) {
aType.registerAsInHeap(reason);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ public void forScannedConstant(JavaConstant value, ScanReason reason) {
Object valueObj = analysis.getSnippetReflectionProvider().asObject(Object.class, value);
AnalysisType type = bb.getMetaAccess().lookupJavaType(valueObj.getClass());

type.registerAsInHeap();
type.registerAsInHeap(reason);
}

private PointsToAnalysis getAnalysis() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ public final void scanConstant(JavaConstant value, ScanReason reason) {
return;
}
if (!bb.scanningPolicy().scanConstant(bb, value)) {
bb.markTypeInHeap(bb.getMetaAccess().lookupJavaType(value));
bb.registerTypeAsInHeap(bb.getMetaAccess().lookupJavaType(value), reason);
return;
}
Object valueObj = (value instanceof ImageHeapConstant) ? value : constantAsObject(bb, value);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,16 +93,16 @@ default boolean registerAsUnsafeAccessed(AnalysisField field, UnsafePartitionKin
return false;
}

default boolean markTypeReachable(AnalysisType type) {
default boolean markTypeAsReachable(AnalysisType type) {
return type.registerAsReachable();
}

default boolean markTypeInstantiated(AnalysisType type) {
return type.registerAsAllocated(null);
default boolean registerTypeAsAllocated(AnalysisType type, Object reason) {
return type.registerAsAllocated(reason);
}

default boolean markTypeInHeap(AnalysisType type) {
return type.registerAsInHeap();
default boolean registerTypeAsInHeap(AnalysisType type, Object reason) {
return type.registerAsInHeap(reason);
}

default void markFieldAccessed(AnalysisField field) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -237,12 +237,12 @@ public void registerUsedElements(boolean registerEmbeddedRoots) {
} else if (n instanceof NewInstanceNode) {
NewInstanceNode node = (NewInstanceNode) n;
AnalysisType type = (AnalysisType) node.instanceClass();
type.registerAsAllocated(node);
type.registerAsAllocated(AbstractAnalysisEngine.sourcePosition(node));

} else if (n instanceof VirtualObjectNode) {
VirtualObjectNode node = (VirtualObjectNode) n;
AnalysisType type = (AnalysisType) node.type();
type.registerAsAllocated(node);
type.registerAsAllocated(AbstractAnalysisEngine.sourcePosition(node));

} else if (n instanceof CommitAllocationNode) {
CommitAllocationNode node = (CommitAllocationNode) n;
Expand All @@ -265,20 +265,20 @@ public void registerUsedElements(boolean registerEmbeddedRoots) {
} else if (n instanceof NewArrayNode) {
NewArrayNode node = (NewArrayNode) n;
AnalysisType type = ((AnalysisType) node.elementType()).getArrayClass();
type.registerAsAllocated(node);
type.registerAsAllocated(AbstractAnalysisEngine.sourcePosition(node));

} else if (n instanceof NewMultiArrayNode) {
NewMultiArrayNode node = (NewMultiArrayNode) n;
AnalysisType type = ((AnalysisType) node.type());
for (int i = 0; i < node.dimensionCount(); i++) {
type.registerAsAllocated(node);
type.registerAsAllocated(AbstractAnalysisEngine.sourcePosition(node));
type = type.getComponentType();
}

} else if (n instanceof BoxNode) {
BoxNode node = (BoxNode) n;
AnalysisType type = (AnalysisType) StampTool.typeOrNull(node);
type.registerAsAllocated(node);
type.registerAsAllocated(AbstractAnalysisEngine.sourcePosition(node));

} else if (n instanceof LoadFieldNode) {
LoadFieldNode node = (LoadFieldNode) n;
Expand All @@ -295,7 +295,7 @@ public void registerUsedElements(boolean registerEmbeddedRoots) {
if (cn.hasUsages() && cn.isJavaConstant() && cn.asJavaConstant().getJavaKind() == JavaKind.Object && cn.asJavaConstant().isNonNull()) {
assert StampTool.isExactType(cn);
AnalysisType type = (AnalysisType) StampTool.typeOrNull(cn);
type.registerAsInHeap();
type.registerAsInHeap(AbstractAnalysisEngine.sourcePosition(cn));
if (registerEmbeddedRoots && !ignoreConstant(cn)) {
registerEmbeddedRoot(cn);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -167,11 +167,11 @@ public TypeData computeTypeData(AnalysisType type) {
return data;
}

void markTypeInstantiated(AnalysisType type) {
void markTypeInstantiated(AnalysisType type, ScanReason reason) {
if (universe.sealed() && !type.isReachable()) {
throw AnalysisError.shouldNotReachHere("Universe is sealed. New type reachable: " + type.toJavaName());
}
universe.getBigbang().markTypeInHeap(type);
universe.getBigbang().registerTypeAsInHeap(type, reason);
}

JavaConstant markConstantReachable(JavaConstant constant, ScanReason reason, Consumer<ScanReason> onAnalysisModified) {
Expand Down Expand Up @@ -249,11 +249,11 @@ protected void scanImageHeapObject(ImageHeapConstant object, ScanReason reason,
onArrayElementReachable(array, type, elementValue, idx, arrayReason, onAnalysisModified);
}
}
markTypeInstantiated(type);
markTypeInstantiated(type, reason);
} else {
ImageHeapInstance instance = (ImageHeapInstance) object;
/* We are about to query the type's fields, the type must be marked as reachable. */
markTypeInstantiated(type);
markTypeInstantiated(type, reason);
for (AnalysisField field : type.getInstanceFields(true)) {
if (field.isRead() && isValueAvailable(field)) {
final JavaConstant fieldValue = instance.readFieldValue(field);
Expand Down Expand Up @@ -351,15 +351,15 @@ protected ImageHeapConstant createImageHeapObject(JavaConstant constant, ScanRea
array.setElement(idx, arrayElement);
}
}
markTypeInstantiated(type);
markTypeInstantiated(type, reason);
} else {
/*
* We need to have the new ImageHeapInstance early so that we can reference it in the
* lambda when the field value gets reachable. But it must not be published to any other
* thread before all instanceFieldValues are filled in.
*/
/* We are about to query the type's fields, the type must be marked as reachable. */
markTypeInstantiated(type);
markTypeInstantiated(type, reason);
AnalysisField[] instanceFields = type.getInstanceFields(true);
newImageHeapConstant = new ImageHeapInstance(type, constant, instanceFields.length);
for (AnalysisField field : instanceFields) {
Expand All @@ -383,7 +383,7 @@ protected ImageHeapConstant createImageHeapObject(JavaConstant constant, ScanRea
/*
* Following all the array elements and reachable field values can be done asynchronously.
*/
postTask(() -> onObjectReachable(newImageHeapConstant));
postTask(() -> onObjectReachable(newImageHeapConstant, reason));
return newImageHeapConstant;
}

Expand Down Expand Up @@ -510,11 +510,11 @@ private boolean notifyAnalysis(JavaConstant array, AnalysisType arrayType, JavaC
return analysisModified;
}

protected void onObjectReachable(ImageHeapConstant imageHeapConstant) {
protected void onObjectReachable(ImageHeapConstant imageHeapConstant, ScanReason reason) {
AnalysisType objectType = metaAccess.lookupJavaType(imageHeapConstant);
imageHeap.add(objectType, imageHeapConstant);

markTypeInstantiated(objectType);
markTypeInstantiated(objectType, reason);

if (imageHeapConstant instanceof ImageHeapInstance) {
ImageHeapInstance imageHeapInstance = (ImageHeapInstance) imageHeapConstant;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@
import java.util.function.Function;

import org.graalvm.compiler.debug.GraalError;
import org.graalvm.compiler.graph.Node;
import org.graalvm.nativeimage.hosted.Feature.DuringAnalysisAccess;
import org.graalvm.word.WordBase;

Expand All @@ -64,6 +63,7 @@
import com.oracle.graal.pointsto.util.ConcurrentLightHashSet;
import com.oracle.svm.util.UnsafePartitionKind;

import jdk.vm.ci.code.BytecodePosition;
import jdk.vm.ci.meta.Assumptions.AssumptionResult;
import jdk.vm.ci.meta.JavaConstant;
import jdk.vm.ci.meta.JavaKind;
Expand Down Expand Up @@ -95,11 +95,11 @@ public abstract class AnalysisType extends AnalysisElement implements WrappedJav
private static final AtomicReferenceFieldUpdater<AnalysisType, Object> instantiatedNotificationsUpdater = AtomicReferenceFieldUpdater
.newUpdater(AnalysisType.class, Object.class, "typeInstantiatedNotifications");

private static final AtomicIntegerFieldUpdater<AnalysisType> isInHeapUpdater = AtomicIntegerFieldUpdater
.newUpdater(AnalysisType.class, "isInHeap");
private static final AtomicReferenceFieldUpdater<AnalysisType, Object> isAllocatedUpdater = AtomicReferenceFieldUpdater
.newUpdater(AnalysisType.class, Object.class, "isAllocated");

private static final AtomicIntegerFieldUpdater<AnalysisType> isAllocatedUpdater = AtomicIntegerFieldUpdater
.newUpdater(AnalysisType.class, "isAllocated");
private static final AtomicReferenceFieldUpdater<AnalysisType, Object> isInHeapUpdater = AtomicReferenceFieldUpdater
.newUpdater(AnalysisType.class, Object.class, "isInHeap");

private static final AtomicIntegerFieldUpdater<AnalysisType> isReachableUpdater = AtomicIntegerFieldUpdater
.newUpdater(AnalysisType.class, "isReachable");
Expand All @@ -110,8 +110,8 @@ public abstract class AnalysisType extends AnalysisElement implements WrappedJav
protected final AnalysisUniverse universe;
private final ResolvedJavaType wrapped;

@SuppressWarnings("unused") private volatile int isInHeap;
@SuppressWarnings("unused") private volatile int isAllocated;
@SuppressWarnings("unused") private volatile Object isInHeap;
@SuppressWarnings("unused") private volatile Object isAllocated;
@SuppressWarnings("unused") private volatile int isReachable;
@SuppressWarnings("unused") private volatile int isAnySubtypeInstantiated;
private boolean reachabilityListenerNotified;
Expand Down Expand Up @@ -455,21 +455,30 @@ public static boolean verifyAssignableTypes(BigBang bb) {
return true;
}

public boolean registerAsInHeap() {
/**
* @param reason the {@link BytecodePosition} where this type is marked as in-heap, or a
* {@link com.oracle.graal.pointsto.ObjectScanner.ScanReason}, or a {@link String}
* describing why this type was manually marked as in-heap
*/
public boolean registerAsInHeap(Object reason) {
assert reason != null && (!(reason instanceof String) || !reason.equals("")) : "Registering a type as in-heap needs to provide a non-empty reason.";
registerAsReachable();
if (AtomicUtils.atomicMark(this, isInHeapUpdater)) {
if (AtomicUtils.atomicSet(this, reason, isInHeapUpdater)) {
onInstantiated(UsageKind.InHeap);
return true;
}
return false;
}

/**
* @param node For future use and debugging
* @param reason the {@link BytecodePosition} where this type is marked as allocated, or a
* {@link com.oracle.graal.pointsto.ObjectScanner.ScanReason}, or a {@link String}
* describing why this type was manually marked as allocated
*/
public boolean registerAsAllocated(Node node) {
public boolean registerAsAllocated(Object reason) {
assert reason != null && (!(reason instanceof String) || !reason.equals("")) : "Registering a type as allocated needs to provide a non-empty reason.";
registerAsReachable();
if (AtomicUtils.atomicMark(this, isAllocatedUpdater)) {
if (AtomicUtils.atomicSet(this, reason, isAllocatedUpdater)) {
onInstantiated(UsageKind.Allocated);
return true;
}
Expand Down Expand Up @@ -551,7 +560,7 @@ protected void onReachable() {
* types as instantiated too allows more usages of Arrays.newInstance without the need
* of explicit registration of types for reflection.
*/
registerAsAllocated(null);
registerAsAllocated("All array types are marked as instantiated eagerly.");
}
ensureInitialized();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
*/
package com.oracle.graal.pointsto.util;

import java.util.Objects;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
import java.util.concurrent.atomic.AtomicReference;
Expand All @@ -34,6 +35,7 @@
public class AtomicUtils {

public static <T, V> boolean atomicSet(T holder, V value, AtomicReferenceFieldUpdater<T, V> updater) {
Objects.requireNonNull(value, "The value parameter of AtomicUtils.atomicSet() should not be null.");
return updater.compareAndSet(holder, null, value);
}

Expand Down
Loading