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
2 changes: 1 addition & 1 deletion substratevm/mx.substratevm/suite.py
Original file line number Diff line number Diff line change
Expand Up @@ -1646,7 +1646,7 @@
"name" : "org.graalvm.nativeimage.base",
"exports" : [
"com.oracle.svm.util to org.graalvm.nativeimage.pointsto,org.graalvm.nativeimage.builder,org.graalvm.nativeimage.librarysupport,org.graalvm.nativeimage.driver,org.graalvm.nativeimage.llvm,org.graalvm.nativeimage.agent.jvmtibase,org.graalvm.nativeimage.agent.tracing,org.graalvm.nativeimage.agent.diagnostics,org.graalvm.nativeimage.junitsupport,com.oracle.svm.svm_enterprise,com.oracle.svm_enterprise.ml_dataset,org.graalvm.extraimage.builder,com.oracle.svm.extraimage_enterprise,org.graalvm.extraimage.librarysupport",
"com.oracle.svm.common.meta to org.graalvm.nativeimage.pointsto,org.graalvm.nativeimage.builder",
"com.oracle.svm.common.meta to org.graalvm.nativeimage.pointsto,org.graalvm.nativeimage.builder,org.graalvm.nativeimage.llvm,org.graalvm.extraimage.builder",
"com.oracle.svm.common.option to org.graalvm.nativeimage.pointsto,org.graalvm.nativeimage.builder,org.graalvm.nativeimage.driver",
],
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
import java.util.concurrent.ForkJoinWorkerThread;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicLongArray;
import java.util.function.Consumer;
import java.util.stream.StreamSupport;

import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
Expand Down Expand Up @@ -79,6 +80,7 @@
import com.oracle.graal.pointsto.util.Timer;
import com.oracle.graal.pointsto.util.Timer.StopTimer;
import com.oracle.graal.pointsto.util.TimerCollection;
import com.oracle.svm.common.meta.MultiMethod;
import com.oracle.svm.util.ClassUtil;
import com.oracle.svm.util.ImageGeneratorThreadMarker;

Expand Down Expand Up @@ -288,42 +290,50 @@ public Iterable<AnalysisType> getAllSynchronizedTypes() {
}

@Override
public AnalysisMethod addRootMethod(Executable method, boolean invokeSpecial) {
return addRootMethod(metaAccess.lookupJavaMethod(method), invokeSpecial);
public AnalysisMethod addRootMethod(Executable method, boolean invokeSpecial, MultiMethod.MultiMethodKey... otherRoots) {
return addRootMethod(metaAccess.lookupJavaMethod(method), invokeSpecial, otherRoots);
}

@Override
@SuppressWarnings("try")
public AnalysisMethod addRootMethod(AnalysisMethod aMethod, boolean invokeSpecial) {
assert aMethod.isOriginalMethod();
public AnalysisMethod addRootMethod(AnalysisMethod aMethod, boolean invokeSpecial, MultiMethod.MultiMethodKey... otherRoots) {
assert !universe.sealed() : "Cannot register root methods after analysis universe is sealed.";
AnalysisError.guarantee(aMethod.isOriginalMethod());
AnalysisType declaringClass = aMethod.getDeclaringClass();
boolean isStatic = aMethod.isStatic();
WrappedSignature signature = aMethod.getSignature();
int paramCount = signature.getParameterCount(!isStatic);
PointsToAnalysisMethod pointsToMethod = assertPointsToAnalysisMethod(aMethod);
PointsToAnalysisMethod originalPTAMethod = assertPointsToAnalysisMethod(aMethod);

if (isStatic) {
/*
* For static methods trigger analysis in the empty context. This will trigger parsing
* and return the method flows graph. Then the method parameter type flows are
* initialized with the corresponding parameter declared type.
*/
postTask(() -> {
pointsToMethod.registerAsDirectRootMethod();
pointsToMethod.registerAsImplementationInvoked("root method");
MethodFlowsGraphInfo flowInfo = analysisPolicy.staticRootMethodGraph(this, pointsToMethod);
for (int idx = 0; idx < paramCount; idx++) {
AnalysisType declaredParamType = (AnalysisType) signature.getParameterType(idx, declaringClass);
FormalParamTypeFlow parameter = flowInfo.getParameter(idx);
if (declaredParamType.getJavaKind() == JavaKind.Object && parameter != null) {
TypeFlow<?> initialParameterFlow = declaredParamType.getTypeFlow(this, true);
initialParameterFlow.addUse(this, parameter);
Consumer<PointsToAnalysisMethod> triggerStaticMethodFlow = (pointsToMethod) -> {
postTask(() -> {
pointsToMethod.registerAsDirectRootMethod();
pointsToMethod.registerAsImplementationInvoked("root method");
MethodFlowsGraphInfo flowInfo = analysisPolicy.staticRootMethodGraph(this, pointsToMethod);
for (int idx = 0; idx < paramCount; idx++) {
AnalysisType declaredParamType = (AnalysisType) signature.getParameterType(idx, declaringClass);
FormalParamTypeFlow parameter = flowInfo.getParameter(idx);
if (declaredParamType.getJavaKind() == JavaKind.Object && parameter != null) {
TypeFlow<?> initialParameterFlow = declaredParamType.getTypeFlow(this, true);
initialParameterFlow.addUse(this, parameter);
}
}
}
});
});
};
triggerStaticMethodFlow.accept(originalPTAMethod);
for (MultiMethod.MultiMethodKey key : otherRoots) {
assert key != MultiMethod.ORIGINAL_METHOD;
PointsToAnalysisMethod ptaMethod = assertPointsToAnalysisMethod(originalPTAMethod.getMultiMethod(key));
triggerStaticMethodFlow.accept(ptaMethod);
}
} else {
if (invokeSpecial && pointsToMethod.isAbstract()) {
if (invokeSpecial && originalPTAMethod.isAbstract()) {
throw AnalysisError.userError("Abstract methods cannot be registered as special invoke entry point.");
}
/*
Expand All @@ -340,14 +350,20 @@ public AnalysisMethod addRootMethod(AnalysisMethod aMethod, boolean invokeSpecia
* corresponding declared type state. When a callee is resolved the method is parsed and
* the actual parameter type state is propagated to the formal parameters. Then the
* callee is linked and registered as implementation-invoked.
*
* Note for virtual and special methods no action is needed when there are otherRoots.
* This is due to two factors: First, the callee methods are only resolved once types
* flow into the context insensitive invoke typeflow. Second, otherRoots is only
* (currently) used for runtime compilation; in this use case, all necessary linking
* will be done during callee resolution.
*/
postTask(() -> {
if (invokeSpecial) {
pointsToMethod.registerAsDirectRootMethod();
originalPTAMethod.registerAsDirectRootMethod();
} else {
pointsToMethod.registerAsVirtualRootMethod();
originalPTAMethod.registerAsVirtualRootMethod();
}
InvokeTypeFlow invoke = pointsToMethod.initAndGetContextInsensitiveInvoke(PointsToAnalysis.this, null, invokeSpecial, pointsToMethod.getMultiMethodKey());
InvokeTypeFlow invoke = originalPTAMethod.initAndGetContextInsensitiveInvoke(PointsToAnalysis.this, null, invokeSpecial, MultiMethod.ORIGINAL_METHOD);
/*
* Initialize the type flow of the invoke's actual parameters with the corresponding
* parameter declared type. Thus, when the invoke links callees it will propagate
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import com.oracle.graal.pointsto.meta.AnalysisMethod;
import com.oracle.graal.pointsto.meta.AnalysisType;
import com.oracle.graal.pointsto.meta.AnalysisUniverse;
import com.oracle.svm.common.meta.MultiMethod;
import com.oracle.svm.util.UnsafePartitionKind;

/**
Expand Down Expand Up @@ -58,7 +59,7 @@ public interface ReachabilityAnalysis {
AnalysisType addRootField(Class<?> clazz, String fieldName);

/**
* Registers the method as root.
* Registers the method as root. Must be an {@link MultiMethod#ORIGINAL_METHOD}.
*
* Static methods are immediately analyzed and marked as implementation-invoked which will also
* trigger their compilation.
Expand All @@ -70,16 +71,21 @@ public interface ReachabilityAnalysis {
* is instantiated will actually be linked. Trying to register an abstract method as a special
* invoked root will result in an error.
*
* If {@code otherRoots} are specified, these versions of the method will also be registered as
* root methods.
*
* @param aMethod the method to register as root
* @param invokeSpecial if true only the target method is analyzed, even if it has overrides, or
* it is itself an override. If the method is static this flag is ignored.
* @param otherRoots other versions of this method to also register as roots.
*/
AnalysisMethod addRootMethod(AnalysisMethod aMethod, boolean invokeSpecial);
AnalysisMethod addRootMethod(AnalysisMethod aMethod, boolean invokeSpecial, MultiMethod.MultiMethodKey... otherRoots);

/**
* @see ReachabilityAnalysis#addRootMethod(AnalysisMethod, boolean)
* @see ReachabilityAnalysis#addRootMethod(AnalysisMethod, boolean,
* MultiMethod.MultiMethodKey...)
*/
AnalysisMethod addRootMethod(Executable method, boolean invokeSpecial);
AnalysisMethod addRootMethod(Executable method, boolean invokeSpecial, MultiMethod.MultiMethodKey... otherRoots);

default void registerAsFrozenUnsafeAccessed(AnalysisField field) {
field.setUnsafeFrozenTypeState(true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,14 @@ public Function<AnalysisType, ResolvedJavaType> getStrengthenGraphsToTargetFunct
return (t) -> t;
}

public boolean allowConstantFolding(AnalysisMethod method) {
/*
* Currently constant folding is only enabled for original methods. More work is needed to
* support it within deoptimization targets and runtime-compiled methods.
*/
return method.isOriginalMethod();
}

public FieldValueComputer createFieldValueComputer(@SuppressWarnings("unused") AnalysisField field) {
return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -242,8 +242,11 @@ public boolean isImplementationInvokable() {
} else {
/*
* If only a stub is ever created for this method, then it will not be invoked.
*
* However, for deopt targets it is possible for a root to temporarily be a stub before
* a full flow graph is created.
*/
return !getTypeFlow().getMethodFlowsGraphInfo().isStub();
return !getTypeFlow().getMethodFlowsGraphInfo().isStub() || (isDirectRootMethod() && isDeoptTarget());
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -296,11 +296,7 @@ class StrengthenSimplifier implements CustomSimplification {
nodeFlows.put(node, cursor.getValue());
}

/*
* Currently constant folding is only enabled for original methods. More work is needed
* to support it within deoptimization targets and runtime-compiled methods.
*/
this.allowConstantFolding = method.isOriginalMethod() && strengthenGraphWithConstants;
this.allowConstantFolding = strengthenGraphWithConstants && bb.getHostVM().allowConstantFolding(method);

/*
* In deoptimization target methods optimizing the return parameter can make new values
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
import com.oracle.graal.pointsto.util.CompletionExecutor;
import com.oracle.graal.pointsto.util.Timer;
import com.oracle.graal.pointsto.util.TimerCollection;
import com.oracle.svm.common.meta.MultiMethod;

import jdk.vm.ci.code.BytecodePosition;
import jdk.vm.ci.meta.ConstantReflectionProvider;
Expand Down Expand Up @@ -106,8 +107,8 @@ public AnalysisType addRootClass(Class<?> clazz, boolean addFields, boolean addA
}

@Override
public AnalysisMethod addRootMethod(Executable method, boolean invokeSpecial) {
return addRootMethod(metaAccess.lookupJavaMethod(method), invokeSpecial);
public AnalysisMethod addRootMethod(Executable method, boolean invokeSpecial, MultiMethod.MultiMethodKey... otherRoots) {
return addRootMethod(metaAccess.lookupJavaMethod(method), invokeSpecial, otherRoots);
}

@SuppressWarnings("try")
Expand Down Expand Up @@ -145,7 +146,8 @@ public AnalysisType addRootField(Class<?> clazz, String fieldName) {
}

@Override
public AnalysisMethod addRootMethod(AnalysisMethod m, boolean invokeSpecial) {
public AnalysisMethod addRootMethod(AnalysisMethod m, boolean invokeSpecial, MultiMethod.MultiMethodKey... otherRoots) {
assert otherRoots.length == 0;
ReachabilityAnalysisMethod method = (ReachabilityAnalysisMethod) m;
if (m.isStatic()) {
postTask(() -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@
import com.oracle.svm.common.meta.MultiMethod;
import com.oracle.svm.core.SubstrateOptions;
import com.oracle.svm.core.meta.SharedMethod;
import com.oracle.svm.core.util.VMError;

import jdk.vm.ci.meta.DeoptimizationAction;
import jdk.vm.ci.meta.DeoptimizationReason;
Expand All @@ -61,7 +60,13 @@ public Node canonical(CanonicalizerTool tool) {
ResolvedJavaMethod method = graph().method();

if (SubstrateOptions.parseOnce()) {
throw VMError.unimplemented("Deopt Testing does not yet work.");
if (MultiMethod.isDeoptTarget(method)) {
/* no-op for deoptimization target methods. */
return null;
} else {
/* deoptimization for all other methods. */
return new DeoptimizeNode(DeoptimizationAction.None, DeoptimizationReason.TransferToInterpreter);
}
} else {
if (method instanceof SharedMethod) {
if (MultiMethod.isDeoptTarget(method)) {
Expand Down
Loading