Skip to content

Refactor Native Image heap scanning. #3926

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 23 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
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 sdk/src/org.graalvm.nativeimage/snapshot.sigtest
Original file line number Diff line number Diff line change
Expand Up @@ -893,6 +893,7 @@ CLSS public abstract interface static org.graalvm.nativeimage.hosted.Feature$Dur
intf org.graalvm.nativeimage.hosted.Feature$BeforeAnalysisAccess
intf org.graalvm.nativeimage.hosted.Feature$QueryReachabilityAccess
meth public abstract void requireAnalysisIteration()
meth public abstract void rescanObject(java.lang.Object)

CLSS public abstract interface static org.graalvm.nativeimage.hosted.Feature$DuringSetupAccess
outer org.graalvm.nativeimage.hosted.Feature
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,13 @@ interface DuringAnalysisAccess extends BeforeAnalysisAccess, QueryReachabilityAc
* @since 19.0
*/
void requireAnalysisIteration();

/**
* Rescan an object to be included in the image heap.
*
* @since 22.0
*/
void rescanObject(Object obj);
}

/**
Expand Down
1 change: 1 addition & 0 deletions substratevm/ci_includes/gate.hocon
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ builds += [
}
${labsjdk-ce-17} ${svm-common-gate} ${svm-common-windows-jdk17} ${svmUnittest} {
name: "gate-svm-windows-basics"
timelimit: "1:30:00"
run: [
${svm-cmd-gate} ["build,helloworld,test,svmjunit"]
]
Expand Down
4 changes: 4 additions & 0 deletions substratevm/mx.substratevm/suite.py
Original file line number Diff line number Diff line change
Expand Up @@ -1155,7 +1155,9 @@
"sun.reflect.generics.reflectiveObjects",
"sun.reflect.generics.repository",
"sun.reflect.generics.tree",
"sun.reflect.generics.scope",
"sun.util.calendar",
"sun.util.locale",
"sun.security.jca",
"sun.security.util",
"sun.security.provider",
Expand Down Expand Up @@ -1457,6 +1459,8 @@
"exports" : [
"com.oracle.graal.pointsto",
"com.oracle.graal.pointsto.api",
"com.oracle.graal.pointsto.heap",
"com.oracle.graal.pointsto.heap.value",
"com.oracle.graal.pointsto.reports",
"com.oracle.graal.pointsto.constraints",
"com.oracle.graal.pointsto.util",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
*/
package com.oracle.graal.pointsto;

import com.oracle.graal.pointsto.ObjectScanner.ScanReason;
import com.oracle.graal.pointsto.flow.ArrayElementsTypeFlow;
import com.oracle.graal.pointsto.flow.FieldTypeFlow;
import com.oracle.graal.pointsto.flow.context.object.AnalysisObject;
Expand All @@ -42,23 +43,25 @@ public AnalysisObjectScanningObserver(BigBang bb) {
}

@Override
public void forRelocatedPointerFieldValue(JavaConstant receiver, AnalysisField field, JavaConstant fieldValue) {
public boolean forRelocatedPointerFieldValue(JavaConstant receiver, AnalysisField field, JavaConstant fieldValue, ScanReason reason) {
if (!field.isWritten()) {
field.registerAsWritten(null);
return field.registerAsWritten(null);
}
return false;
}

@Override
public void forNullFieldValue(JavaConstant receiver, AnalysisField field) {
public boolean forNullFieldValue(JavaConstant receiver, AnalysisField field, ScanReason reason) {
FieldTypeFlow fieldTypeFlow = getFieldTypeFlow(field, receiver);
if (!fieldTypeFlow.getState().canBeNull()) {
/* Signal that the field can contain null. */
fieldTypeFlow.addState(getAnalysis(), TypeState.forNull());
return fieldTypeFlow.addState(getAnalysis(), TypeState.forNull());
}
return false;
}

@Override
public void forNonNullFieldValue(JavaConstant receiver, AnalysisField field, JavaConstant fieldValue) {
public boolean forNonNullFieldValue(JavaConstant receiver, AnalysisField field, JavaConstant fieldValue, ScanReason reason) {
PointsToAnalysis analysis = getAnalysis();
AnalysisType fieldType = analysis.getMetaAccess().lookupJavaType(analysis.getSnippetReflectionProvider().asObject(Object.class, fieldValue).getClass());
assert fieldType.isInstantiated() : fieldType;
Expand All @@ -69,8 +72,9 @@ public void forNonNullFieldValue(JavaConstant receiver, AnalysisField field, Jav
if (!fieldTypeFlow.getState().containsObject(constantObject)) {
/* Add the new constant to the field's flow state. */
TypeState constantTypeState = TypeState.forNonNullObject(analysis, constantObject);
fieldTypeFlow.addState(analysis, constantTypeState);
return fieldTypeFlow.addState(analysis, constantTypeState);
}
return false;
}

/**
Expand All @@ -94,25 +98,27 @@ private FieldTypeFlow getFieldTypeFlow(AnalysisField field, JavaConstant receive
}

@Override
public void forNullArrayElement(JavaConstant array, AnalysisType arrayType, int elementIndex) {
public boolean forNullArrayElement(JavaConstant array, AnalysisType arrayType, int elementIndex, ScanReason reason) {
ArrayElementsTypeFlow arrayObjElementsFlow = getArrayElementsFlow(array, arrayType);
if (!arrayObjElementsFlow.getState().canBeNull()) {
/* Signal that the constant array can contain null. */
arrayObjElementsFlow.addState(getAnalysis(), TypeState.forNull());
return arrayObjElementsFlow.addState(getAnalysis(), TypeState.forNull());
}
return false;
}

@Override
public void forNonNullArrayElement(JavaConstant array, AnalysisType arrayType, JavaConstant elementConstant, AnalysisType elementType, int elementIndex) {
public boolean forNonNullArrayElement(JavaConstant array, AnalysisType arrayType, JavaConstant elementConstant, AnalysisType elementType, int elementIndex, ScanReason reason) {
assert elementType.isInstantiated() : elementType;
ArrayElementsTypeFlow arrayObjElementsFlow = getArrayElementsFlow(array, arrayType);
PointsToAnalysis analysis = getAnalysis();
AnalysisObject constantObject = bb.analysisPolicy().createConstantObject(analysis, elementConstant, elementType);
if (!arrayObjElementsFlow.getState().containsObject(constantObject)) {
/* Add the constant element to the constant's array type flow. */
TypeState elementTypeState = TypeState.forNonNullObject(analysis, constantObject);
arrayObjElementsFlow.addState(analysis, elementTypeState);
return arrayObjElementsFlow.addState(analysis, elementTypeState);
}
return false;
}

/**
Expand All @@ -125,7 +131,7 @@ private ArrayElementsTypeFlow getArrayElementsFlow(JavaConstant array, AnalysisT
}

@Override
public void forScannedConstant(JavaConstant value, ObjectScanner.ScanReason reason) {
public void forScannedConstant(JavaConstant value, ScanReason reason) {
PointsToAnalysis analysis = getAnalysis();
Object valueObj = analysis.getSnippetReflectionProvider().asObject(Object.class, value);
AnalysisType type = bb.getMetaAccess().lookupJavaType(valueObj.getClass());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,22 +24,27 @@
*/
package com.oracle.graal.pointsto;

import java.io.PrintWriter;
import java.util.List;
import java.util.function.Function;

import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.debug.DebugHandlersFactory;
import org.graalvm.compiler.graph.NodeSourcePosition;
import org.graalvm.compiler.options.OptionValues;

import com.oracle.graal.pointsto.api.HostVM;
import com.oracle.graal.pointsto.constraints.UnsupportedFeatures;
import com.oracle.graal.pointsto.meta.AnalysisField;
import com.oracle.graal.pointsto.meta.AnalysisMethod;
import com.oracle.graal.pointsto.meta.AnalysisType;
import com.oracle.graal.pointsto.meta.AnalysisType.UsageKind;
import com.oracle.graal.pointsto.meta.AnalysisUniverse;
import com.oracle.graal.pointsto.meta.HostedProviders;
import com.oracle.graal.pointsto.util.Timer;
import jdk.vm.ci.meta.ConstantReflectionProvider;
import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.debug.DebugHandlersFactory;
import org.graalvm.compiler.graph.NodeSourcePosition;
import org.graalvm.compiler.options.OptionValues;

import java.io.PrintWriter;
import java.util.List;
import java.util.function.Function;
import jdk.vm.ci.meta.ConstantReflectionProvider;

/**
* Central static analysis interface that groups together the functionality of reachability analysis
Expand Down Expand Up @@ -104,4 +109,20 @@ public interface BigBang extends ReachabilityAnalysis, HeapScanning {
default boolean isCallAllowed(PointsToAnalysis bb, AnalysisMethod caller, AnalysisMethod target, NodeSourcePosition srcPosition) {
return true;
}

/**
* Callback for when a field is marked as read, written, or unsafe accessed. See
* {@link AnalysisField#isAccessed()} for field accessibility definition.
*/
@SuppressWarnings("unused")
default void onFieldAccessed(AnalysisField field) {
}

@SuppressWarnings("unused")
default void onTypeInstantiated(AnalysisType type, UsageKind usageKind) {
}

@SuppressWarnings("unused")
default void onTypeScanned(AnalysisType type) {
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@
import java.util.Collections;
import java.util.List;

import com.oracle.graal.pointsto.meta.PointsToAnalysisMethod;
import org.graalvm.compiler.options.OptionValues;

import com.oracle.graal.pointsto.constraints.UnsupportedFeatureException;
import com.oracle.graal.pointsto.flow.AbstractSpecialInvokeTypeFlow;
import com.oracle.graal.pointsto.flow.AbstractVirtualInvokeTypeFlow;
import com.oracle.graal.pointsto.flow.ActualReturnTypeFlow;
Expand All @@ -47,6 +47,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.graal.pointsto.meta.PointsToAnalysisMethod;
import com.oracle.graal.pointsto.typestate.TypeState;
import com.oracle.graal.pointsto.typestore.ArrayElementsTypeStore;
import com.oracle.graal.pointsto.typestore.FieldTypeStore;
Expand Down Expand Up @@ -208,7 +209,14 @@ public void onObservedUpdate(PointsToAnalysis bb) {
continue;
}

AnalysisMethod method = type.resolveConcreteMethod(getTargetMethod());
AnalysisMethod method = null;
try {
method = type.resolveConcreteMethod(targetMethod);
} catch (UnsupportedFeatureException ex) {
/* Register the ex with UnsupportedFeatures and allow analysis to continue. */
bb.getUnsupportedFeatures().addMessage("resolve_" + targetMethod.format("%H.%n(%p)"), targetMethod, ex.getMessage());
}

if (method == null || Modifier.isAbstract(method.getModifiers())) {
/*
* Type states can be conservative, i.e., we can have receiver types that do not
Expand Down
Loading