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 @@ -109,7 +109,7 @@ public void scanBootImageHeapRoots(Comparator<AnalysisField> fieldComparator, Co
}
for (AnalysisField field : fields) {
if (Modifier.isStatic(field.getModifiers()) && field.isRead()) {
execute(() -> scanRootField(field));
execute(() -> scanStaticFieldRoot(field));
}
}

Expand Down Expand Up @@ -155,9 +155,9 @@ protected void scanEmbeddedRoot(JavaConstant root, Object position) {
*
* @param field the scanned root field
*/
protected final void scanRootField(AnalysisField field) {
if (field.isInBaseLayer()) {
// skip base layer roots
protected final void scanStaticFieldRoot(AnalysisField field) {
if (!field.installableInLayer()) {
// skip fields not installable in this layer
return;
}
scanField(field, null, null);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,20 @@ public boolean enableReachableInCurrentLayer() {
return false;
}

public boolean buildingImageLayer() {
return false;
}

@SuppressWarnings("unused")
public boolean installableInLayer(AnalysisField aField) {
return true;
}

@SuppressWarnings("unused")
public boolean preventConstantFolding(AnalysisField aField) {
return false;
}

/**
* Helpers to determine what analysis actions should be taken for a given Multi-Method version.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,4 +77,9 @@ public JavaConstant uncompress() {
public ImageHeapConstant forObjectClone() {
throw AnalysisError.shouldNotReachHere("Unsupported in ImageHeapRelocatableConstant");
}

@Override
public String toString() {
return "(ImageHeapRelocatableConstant) " + super.toString();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -133,10 +133,10 @@ public void onFieldRead(AnalysisField field) {
AnalysisType declaringClass = field.getDeclaringClass();
if (field.isStatic()) {
FieldScan reason = new FieldScan(field);
if (field.isInBaseLayer()) {
if (!field.installableInLayer()) {
/*
* For base layer static fields we don't want to scan the constant value, but
* instead inject its type state in the field flow. This will be propagated to any
* For non-installable static fields we do not scan the constant value, but instead
* inject its type state in the field flow. This will be propagated to any
* corresponding field loads.
*
* GR-52421: the field state needs to be serialized from the base layer analysis
Expand All @@ -146,9 +146,7 @@ public void onFieldRead(AnalysisField field) {
} else if (bb.trackPrimitiveValues() && field.getStorageKind().isPrimitive()) {
((PointsToAnalysisField) field).saturatePrimitiveField();
}
return;
}
if (isValueAvailable(field)) {
} else if (isValueAvailable(field)) {
JavaConstant fieldValue = readStaticFieldValue(field);
if (fieldValue instanceof ImageHeapConstant imageHeapConstant && field.isFinal()) {
AnalysisError.guarantee(imageHeapConstant.getOrigin() != null, "The origin of the constant %s should have been registered before", imageHeapConstant);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,13 @@ public abstract class AnalysisField extends AnalysisElement implements WrappedJa
*/
protected Object fieldValueInterceptor;

/**
* When building layered images, for static fields we must keep track of what layer's static
* fields array the field is assigned in. This also impacts when the underlying value can be
* read and/or constant folded.
*/
private final boolean isLayeredStaticField;

@SuppressWarnings("this-escape")
public AnalysisField(AnalysisUniverse universe, ResolvedJavaField wrappedField) {
super(universe.hostVM.enableTrackAcrossLayers());
Expand Down Expand Up @@ -152,6 +159,7 @@ public AnalysisField(AnalysisUniverse universe, ResolvedJavaField wrappedField)
id = universe.computeNextFieldId();
isInBaseLayer = false;
}
isLayeredStaticField = isStatic() && universe.hostVM.buildingImageLayer();
}

@Override
Expand Down Expand Up @@ -188,6 +196,22 @@ public boolean isInBaseLayer() {
return isInBaseLayer;
}

public boolean installableInLayer() {
if (isLayeredStaticField) {
return getUniverse().hostVM.installableInLayer(this);
} else {
return true;
}
}

public boolean preventConstantFolding() {
if (isLayeredStaticField) {
return getUniverse().hostVM.preventConstantFolding(this);
} else {
return false;
}
}

@Override
public int hashCode() {
return id;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
import jdk.graal.compiler.graph.NodeClass;
import jdk.graal.compiler.nodeinfo.NodeInfo;
import jdk.graal.compiler.nodes.ConstantNode;
import jdk.graal.compiler.nodes.StructuredGraph;
import jdk.graal.compiler.nodes.ValueNode;
import jdk.graal.compiler.nodes.calc.FloatingNode;
import jdk.graal.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins;
Expand Down Expand Up @@ -99,9 +100,9 @@ static HostedStaticFieldSupport singleton() {
return ImageSingletons.lookup(HostedStaticFieldSupport.class);
}

JavaConstant getStaticPrimitiveFieldsConstant(int layerNum, Function<Object, JavaConstant> toConstant);
JavaConstant getStaticFieldsBaseConstant(int layerNum, boolean primitive, Function<Object, JavaConstant> toConstant);

JavaConstant getStaticObjectFieldsConstant(int layerNum, Function<Object, JavaConstant> toConstant);
FloatingNode getStaticFieldsBaseReplacement(int layerNum, boolean primitive, LoweringTool tool, StructuredGraph graph);

boolean isPrimitive(ResolvedJavaField field);

Expand Down Expand Up @@ -137,7 +138,7 @@ public static JavaConstant getStaticFieldsConstant(ResolvedJavaField field, Func
var hostedSupport = HostedStaticFieldSupport.singleton();
boolean primitive = hostedSupport.isPrimitive(field);
int layerNum = getInstalledLayerNum(field);
return primitive ? hostedSupport.getStaticPrimitiveFieldsConstant(layerNum, toConstant) : hostedSupport.getStaticObjectFieldsConstant(layerNum, toConstant);
return hostedSupport.getStaticFieldsBaseConstant(layerNum, primitive, toConstant);
}

public static int getInstalledLayerNum(ResolvedJavaField field) {
Expand Down Expand Up @@ -249,25 +250,22 @@ public void lower(LoweringTool tool) {
*/
return;
}
JavaConstant constant;
FloatingNode replacement;
if (SubstrateUtil.HOSTED) {
/*
* Build-time version of lowering.
*/
Function<Object, JavaConstant> toConstantFunction = (obj) -> tool.getSnippetReflection().forObject(obj);

HostedStaticFieldSupport hostedSupport = HostedStaticFieldSupport.singleton();
constant = primitive ? hostedSupport.getStaticPrimitiveFieldsConstant(layerNum, toConstantFunction)
: hostedSupport.getStaticObjectFieldsConstant(layerNum, toConstantFunction);
replacement = hostedSupport.getStaticFieldsBaseReplacement(layerNum, primitive, tool, graph());
} else {
/*
* JIT version of lowering.
*/
constant = tool.getSnippetReflection()
JavaConstant constant = tool.getSnippetReflection()
.forObject(primitive ? StaticFieldsSupport.getStaticPrimitiveFieldsAtRuntime(layerNum) : StaticFieldsSupport.getStaticObjectFieldsAtRuntime(layerNum));
replacement = ConstantNode.forConstant(constant, tool.getMetaAccess(), graph());
}
assert constant.isNonNull() : constant;
replaceAndDelete(ConstantNode.forConstant(constant, tool.getMetaAccess(), graph()));
replaceAndDelete(graph().addOrUniqueWithInputs(replacement));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,10 @@ protected void onValueUpdate(EconomicMap<OptionKey<?>, Object> values, Boolean o
@Option(help = "Mark singleton as application layer only")//
public static final HostedOptionKey<AccumulatingLocatableMultiOptionValue.Strings> ApplicationLayerOnlySingletons = new HostedOptionKey<>(AccumulatingLocatableMultiOptionValue.Strings.build());

@Option(help = "Register class as being initialized in the app layer.")//
public static final HostedOptionKey<AccumulatingLocatableMultiOptionValue.Strings> ApplicationLayerInitializedClasses = new HostedOptionKey<>(
AccumulatingLocatableMultiOptionValue.Strings.build());

@APIOption(name = "libc")//
@Option(help = "Selects the libc implementation to use. Available implementations: glibc, musl, bionic")//
public static final HostedOptionKey<String> UseLibC = new HostedOptionKey<>(null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
* {@link Target_jdk_internal_reflect_ConstantPool}.
*/
public class ConstantPoolProvider implements MultiLayeredImageSingleton, UnsavedSingleton {
private final Target_jdk_internal_reflect_ConstantPool constantPool = new Target_jdk_internal_reflect_ConstantPool(DynamicImageLayerInfo.singleton().layerNumber);
private final Target_jdk_internal_reflect_ConstantPool constantPool = new Target_jdk_internal_reflect_ConstantPool(DynamicImageLayerInfo.getCurrentLayerNumber());

public static ConstantPoolProvider[] singletons() {
return MultiLayeredImageSingleton.getAllLayers(ConstantPoolProvider.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,14 @@
import org.graalvm.nativeimage.Platforms;

import com.oracle.svm.core.graal.code.CGlobalDataInfo;
import com.oracle.svm.core.layeredimagesingleton.MultiLayeredImageSingleton;
import com.oracle.svm.core.meta.SharedMethod;

@Platforms(Platform.HOSTED_ONLY.class)
public abstract class DynamicImageLayerInfo {
public static final int CREMA_LAYER_ID = Byte.MAX_VALUE;

public final int layerNumber;
private final int layerNumber;
public final int nextLayerNumber;
public final int numLayers;

Expand All @@ -56,4 +57,12 @@ public record PriorLayerMethodLocation(CGlobalDataInfo base, int offset) {
* Returns a (Base, Offset) pair which can be used to call a method defined in a prior layer.
*/
public abstract PriorLayerMethodLocation getPriorLayerMethodLocation(SharedMethod method);

public static int getCurrentLayerNumber() {
if (!ImageLayerBuildingSupport.buildingImageLayer()) {
return MultiLayeredImageSingleton.UNUSED_LAYER_NUMBER;
} else {
return singleton().layerNumber;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ struct PersistedAnalysisField {
declaringTypeId @2 :TypeId;
typeId @3 :TypeId;
position @4 :Int32;
location @5 :Int32;
location @5 :Int32; # note currently we only read information about static fields' location
modifiers @6 :Int32;
isInternal @7 :Bool;
isAccessed @8 :Bool;
Expand All @@ -139,6 +139,8 @@ struct PersistedAnalysisField {
isSynthetic @13 :Bool;
annotationList @14 :List(Annotation);
name @15 :Text;
priorInstalledLayerNum @16 :Int32;
assignmentStatus @17 :Int32;
}

struct CEntryPointLiteralReference {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,42 +34,74 @@
import com.oracle.svm.core.layeredimagesingleton.MultiLayeredImageSingleton;
import com.oracle.svm.core.meta.SharedField;
import com.oracle.svm.hosted.imagelayer.HostedImageLayerBuildingSupport;
import com.oracle.svm.hosted.imagelayer.LayeredStaticFieldSupport;
import com.oracle.svm.hosted.meta.HostedField;

import jdk.graal.compiler.nodes.ConstantNode;
import jdk.graal.compiler.nodes.StructuredGraph;
import jdk.graal.compiler.nodes.calc.FloatingNode;
import jdk.graal.compiler.nodes.spi.LoweringTool;
import jdk.vm.ci.meta.JavaConstant;
import jdk.vm.ci.meta.ResolvedJavaField;

@AutomaticallyRegisteredImageSingleton(StaticFieldsSupport.HostedStaticFieldSupport.class)
public class HostedStaticFieldSupportImpl implements StaticFieldsSupport.HostedStaticFieldSupport {

@Override
public JavaConstant getStaticPrimitiveFieldsConstant(int layerNum, Function<Object, JavaConstant> toConstant) {
private enum State {
UNUSED,
CURRENT_LAYER,
PRIOR_LAYER,
FUTURE_APP_LAYER,
}

private State determineState(int layerNum) {
if (layerNum == MultiLayeredImageSingleton.UNUSED_LAYER_NUMBER) {
return toConstant.apply(StaticFieldsSupport.getCurrentLayerStaticPrimitiveFields());
return State.UNUSED;
} else {
int currentLayerNum = DynamicImageLayerInfo.singleton().layerNumber;
int currentLayerNum = getCurrentLayerNumber();
if (currentLayerNum == layerNum) {
return toConstant.apply(StaticFieldsSupport.getCurrentLayerStaticPrimitiveFields());
} else {
return State.CURRENT_LAYER;
} else if (layerNum < currentLayerNum) {
assert layerNum == 0 && currentLayerNum == 1;
return HostedImageLayerBuildingSupport.singleton().getLoader().getBaseLayerStaticPrimitiveFields();
return State.PRIOR_LAYER;
} else {
assert layerNum == LayeredStaticFieldSupport.getAppLayerNumber() && currentLayerNum == 0;
return State.FUTURE_APP_LAYER;
}
}
}

@Override
public JavaConstant getStaticObjectFieldsConstant(int layerNum, Function<Object, JavaConstant> toConstant) {
if (layerNum == MultiLayeredImageSingleton.UNUSED_LAYER_NUMBER) {
return toConstant.apply(StaticFieldsSupport.getCurrentLayerStaticObjectFields());
} else {
int currentLayerNum = DynamicImageLayerInfo.singleton().layerNumber;
if (currentLayerNum == layerNum) {
return toConstant.apply(StaticFieldsSupport.getCurrentLayerStaticObjectFields());
} else {
assert layerNum == 0 && currentLayerNum == 1;
return HostedImageLayerBuildingSupport.singleton().getLoader().getBaseLayerStaticObjectFields();
public JavaConstant getStaticFieldsBaseConstant(int layerNum, boolean primitive, Function<Object, JavaConstant> toConstant) {
return switch (determineState(layerNum)) {
case UNUSED, CURRENT_LAYER -> {
Object hostedObject = primitive ? StaticFieldsSupport.getCurrentLayerStaticPrimitiveFields() : StaticFieldsSupport.getCurrentLayerStaticObjectFields();
yield toConstant.apply(hostedObject);
}
}
case PRIOR_LAYER ->
primitive ? HostedImageLayerBuildingSupport.singleton().getLoader().getBaseLayerStaticPrimitiveFields()
: HostedImageLayerBuildingSupport.singleton().getLoader().getBaseLayerStaticObjectFields();
case FUTURE_APP_LAYER ->
LayeredStaticFieldSupport.singleton().getAppLayerStaticFieldBaseConstant(primitive);
};
}

@Override
public FloatingNode getStaticFieldsBaseReplacement(int layerNum, boolean primitive, LoweringTool tool, StructuredGraph graph) {
return switch (determineState(layerNum)) {
case UNUSED, CURRENT_LAYER -> {
Object hostedObject = primitive ? StaticFieldsSupport.getCurrentLayerStaticPrimitiveFields() : StaticFieldsSupport.getCurrentLayerStaticObjectFields();
JavaConstant constant = tool.getSnippetReflection().forObject(hostedObject);
yield ConstantNode.forConstant(constant, tool.getMetaAccess(), graph);
}
case PRIOR_LAYER -> {
var constant = primitive ? HostedImageLayerBuildingSupport.singleton().getLoader().getBaseLayerStaticPrimitiveFields()
: HostedImageLayerBuildingSupport.singleton().getLoader().getBaseLayerStaticObjectFields();
yield ConstantNode.forConstant(constant, tool.getMetaAccess(), graph);
}
case FUTURE_APP_LAYER ->
LayeredStaticFieldSupport.singleton().getAppLayerStaticFieldsBaseReplacement(primitive, tool, graph);
};
}

@Override
Expand All @@ -80,14 +112,29 @@ public boolean isPrimitive(ResolvedJavaField field) {
return ((HostedField) field).getStorageKind().isPrimitive();
}

private int currentLayerCache = MultiLayeredImageSingleton.LAYER_NUM_UNINSTALLED;

private int getCurrentLayerNumber() {
if (currentLayerCache == MultiLayeredImageSingleton.LAYER_NUM_UNINSTALLED) {
int newLayerNumber = DynamicImageLayerInfo.getCurrentLayerNumber();
assert newLayerNumber != MultiLayeredImageSingleton.LAYER_NUM_UNINSTALLED;
currentLayerCache = newLayerNumber;
}
return currentLayerCache;
}

@Override
public int getInstalledLayerNum(ResolvedJavaField field) {
assert ImageLayerBuildingSupport.buildingImageLayer();
if (field instanceof SharedField sField) {
return sField.getInstalledLayerNum();
} else {
AnalysisField aField = (AnalysisField) field;
return (ImageLayerBuildingSupport.buildingInitialLayer() || aField.isInBaseLayer()) ? 0 : 1;
return switch (LayeredStaticFieldSupport.singleton().getAssignmentStatus(aField)) {
case UNDECIDED -> getCurrentLayerNumber();
case PRIOR_LAYER -> LayeredStaticFieldSupport.singleton().getPriorInstalledLayerNum(aField);
case APP_LAYER_REQUESTED, APP_LAYER_DEFERRED -> LayeredStaticFieldSupport.getAppLayerNumber();
};
}
}
}
Loading
Loading