Skip to content

Commit 40016b1

Browse files
committed
Include fields that are not backed by a reflection field
1 parent 1cdb5aa commit 40016b1

File tree

7 files changed

+104
-12
lines changed

7 files changed

+104
-12
lines changed

substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/ClassInclusionPolicy.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import org.graalvm.nativeimage.AnnotationAccess;
3333
import org.graalvm.nativeimage.hosted.Feature;
3434

35+
import com.oracle.graal.pointsto.meta.AnalysisField;
3536
import com.oracle.graal.pointsto.meta.AnalysisMethod;
3637
import com.oracle.svm.core.annotate.TargetClass;
3738

@@ -88,6 +89,16 @@ public boolean isFieldIncluded(Field field) {
8889
return bb.getHostVM().isFieldIncluded(bb, field);
8990
}
9091

92+
/**
93+
* Determine if the given field needs to be included in the image according to the policy.
94+
*/
95+
public boolean isFieldIncluded(AnalysisField field) {
96+
if (!bb.getHostVM().platformSupported(field)) {
97+
return false;
98+
}
99+
return bb.getHostVM().isFieldIncluded(bb, field);
100+
}
101+
91102
/**
92103
* Includes the given class in the image.
93104
*/
@@ -121,6 +132,13 @@ public void includeField(Field field) {
121132
bb.postTask(debug -> bb.addRootField(field));
122133
}
123134

135+
/**
136+
* Includes the given field in the image.
137+
*/
138+
public void includeField(AnalysisField field) {
139+
bb.postTask(debug -> bb.addRootField(field));
140+
}
141+
124142
/**
125143
* The analysis for the base layer of a layered image assumes that any method that is reachable
126144
* using the base java access rules can be an entry point. An upper layer does not have access

substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/PointsToAnalysis.java

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -501,12 +501,15 @@ public AnalysisType addRootField(Class<?> clazz, String fieldName) {
501501

502502
@Override
503503
public AnalysisType addRootField(Field field) {
504-
AnalysisField analysisField = getMetaAccess().lookupJavaField(field);
505-
if (analysisField.isStatic()) {
506-
return addRootStaticField(analysisField);
504+
return addRootField(getMetaAccess().lookupJavaField(field));
505+
}
506+
507+
@Override
508+
public AnalysisType addRootField(AnalysisField field) {
509+
if (field.isStatic()) {
510+
return addRootStaticField(field);
507511
} else {
508-
AnalysisType analysisType = getMetaAccess().lookupJavaType(field.getDeclaringClass());
509-
return addRootField(analysisType, analysisField);
512+
return addRootField(field.getDeclaringClass(), field);
510513
}
511514
}
512515

substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/ReachabilityAnalysis.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ public interface ReachabilityAnalysis {
6060

6161
AnalysisType addRootField(Field field);
6262

63+
AnalysisType addRootField(AnalysisField field);
64+
6365
/**
6466
* Registers the method as root. Must be an {@link MultiMethod#ORIGINAL_METHOD}.
6567
*

substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/api/HostVM.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
import com.oracle.graal.pointsto.BigBang;
4343
import com.oracle.graal.pointsto.PointsToAnalysis;
4444
import com.oracle.graal.pointsto.flow.InvokeTypeFlow;
45+
import com.oracle.graal.pointsto.meta.AnalysisField;
4546
import com.oracle.graal.pointsto.meta.AnalysisMethod;
4647
import com.oracle.graal.pointsto.meta.AnalysisType;
4748
import com.oracle.graal.pointsto.meta.AnalysisUniverse;
@@ -330,11 +331,23 @@ public HostedProviders getProviders(MultiMethod.MultiMethodKey key) {
330331
return providers;
331332
}
332333

334+
/**
335+
* This method should only be used by the {@code ClassInclusionPolicy} to determine which fields
336+
* should be included in the shared layer.
337+
*/
333338
@SuppressWarnings("unused")
334339
public boolean isFieldIncluded(BigBang bb, Field field) {
335340
return true;
336341
}
337342

343+
/**
344+
* See {@link HostVM#isFieldIncluded(BigBang, Field)}.
345+
*/
346+
@SuppressWarnings("unused")
347+
public boolean isFieldIncluded(BigBang bb, AnalysisField field) {
348+
return true;
349+
}
350+
338351
public boolean isClosedTypeWorld() {
339352
return true;
340353
}

substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysisEngine.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -143,8 +143,7 @@ public AnalysisType addRootField(Class<?> clazz, String fieldName) {
143143
for (ResolvedJavaField javaField : type.getInstanceFields(true)) {
144144
AnalysisField field = (AnalysisField) javaField;
145145
if (field.getName().equals(fieldName)) {
146-
field.registerAsAccessed("root field");
147-
return field.getType();
146+
return addRootField(field);
148147
}
149148
}
150149
throw AnalysisError.userError("Field not found: " + fieldName);
@@ -153,6 +152,11 @@ public AnalysisType addRootField(Class<?> clazz, String fieldName) {
153152
@Override
154153
public AnalysisType addRootField(Field field) {
155154
AnalysisField analysisField = getMetaAccess().lookupJavaField(field);
155+
return addRootField(analysisField);
156+
}
157+
158+
@Override
159+
public AnalysisType addRootField(AnalysisField analysisField) {
156160
analysisField.registerAsAccessed("root field");
157161
return analysisField.getType();
158162
}

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SVMHost.java

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
import com.oracle.graal.pointsto.constraints.UnsupportedFeatureException;
5959
import com.oracle.graal.pointsto.heap.ImageLayerLoader;
6060
import com.oracle.graal.pointsto.infrastructure.OriginalClassProvider;
61+
import com.oracle.graal.pointsto.infrastructure.OriginalFieldProvider;
6162
import com.oracle.graal.pointsto.meta.AnalysisField;
6263
import com.oracle.graal.pointsto.meta.AnalysisMetaAccess;
6364
import com.oracle.graal.pointsto.meta.AnalysisMethod;
@@ -76,6 +77,7 @@
7677
import com.oracle.svm.core.RuntimeAssertionsSupport;
7778
import com.oracle.svm.core.SubstrateOptions;
7879
import com.oracle.svm.core.SubstrateOptions.OptimizationLevel;
80+
import com.oracle.svm.core.annotate.Delete;
7981
import com.oracle.svm.core.annotate.InjectAccessors;
8082
import com.oracle.svm.core.c.CGlobalData;
8183
import com.oracle.svm.core.graal.meta.SubstrateForeignCallLinkage;
@@ -195,6 +197,8 @@ public enum UsageKind {
195197
private final int layerId;
196198
private final boolean useBaseLayer;
197199
private Set<Field> excludedFields;
200+
private AnalysisType cGlobalData;
201+
private AnalysisType optionKey;
198202

199203
private final Boolean optionAllowUnsafeAllocationOfAllInstantiatedTypes = SubstrateOptions.AllowUnsafeAllocationOfAllInstantiatedTypes.getValue();
200204
private final boolean isClosedTypeWorld = SubstrateOptions.useClosedTypeWorld();
@@ -906,6 +910,10 @@ private void initializeExcludedFields() {
906910
excludedFields.add(ReflectionUtil.lookupField(NativeLibraries.class, "nativeLibraryLockMap"));
907911
}
908912

913+
/**
914+
* This method cannot use an {@link AnalysisField} because it is used before the analysis is set
915+
* up.
916+
*/
909917
@Override
910918
public boolean isFieldIncluded(BigBang bb, Field field) {
911919
/*
@@ -935,7 +943,53 @@ public boolean isFieldIncluded(BigBang bb, Field field) {
935943
/* Fields that are deleted or substituted should not be in the image */
936944
if (bb instanceof NativeImagePointsToAnalysis nativeImagePointsToAnalysis) {
937945
AnnotationSubstitutionProcessor annotationSubstitutionProcessor = nativeImagePointsToAnalysis.getAnnotationSubstitutionProcessor();
938-
return !annotationSubstitutionProcessor.isDeleted(field) && !annotationSubstitutionProcessor.isAnnotationPresent(field, InjectAccessors.class);
946+
boolean included = !annotationSubstitutionProcessor.isDeleted(field) && !annotationSubstitutionProcessor.isAnnotationPresent(field, InjectAccessors.class);
947+
if (!included) {
948+
return false;
949+
}
950+
}
951+
return super.isFieldIncluded(bb, field);
952+
}
953+
954+
/**
955+
* This method needs to be kept in sync with {@link SVMHost#isFieldIncluded(BigBang, Field)}.
956+
*/
957+
@Override
958+
public boolean isFieldIncluded(BigBang bb, AnalysisField field) {
959+
/*
960+
* Fields of type CGlobalData can use a CGlobalDataFactory which must not be reachable at
961+
* run time
962+
*/
963+
if (cGlobalData == null) {
964+
cGlobalData = bb.getMetaAccess().lookupJavaType(CGlobalData.class);
965+
}
966+
if (field.getType().equals(cGlobalData)) {
967+
return false;
968+
}
969+
970+
if (excludedFields.contains(OriginalFieldProvider.getJavaField(field))) {
971+
return false;
972+
}
973+
974+
/* Fields with those names are not allowed in the image */
975+
if (NativeImageGenerator.checkName(field.getType().toJavaName() + "." + field.getName()) != null) {
976+
return false;
977+
}
978+
/* Options should not be in the image */
979+
if (optionKey == null) {
980+
optionKey = bb.getMetaAccess().lookupJavaType(OptionKey.class);
981+
}
982+
if (optionKey.isAssignableFrom(field.getType())) {
983+
return false;
984+
}
985+
/* Fields from this package should not be in the image */
986+
if (field.getDeclaringClass().toJavaName().startsWith("jdk.graal.compiler")) {
987+
return false;
988+
}
989+
/* Fields that are deleted or substituted should not be in the image */
990+
boolean included = field.getAnnotation(Delete.class) == null && field.getAnnotation(InjectAccessors.class) == null;
991+
if (!included) {
992+
return false;
939993
}
940994
return super.isFieldIncluded(bb, field);
941995
}

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/analysis/NativeImagePointsToAnalysis.java

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@
3737
import com.oracle.graal.pointsto.constraints.UnsupportedFeatures;
3838
import com.oracle.graal.pointsto.flow.MethodFlowsGraph;
3939
import com.oracle.graal.pointsto.flow.MethodTypeFlowBuilder;
40-
import com.oracle.graal.pointsto.infrastructure.OriginalFieldProvider;
4140
import com.oracle.graal.pointsto.meta.AnalysisField;
4241
import com.oracle.graal.pointsto.meta.AnalysisMetaAccess;
4342
import com.oracle.graal.pointsto.meta.AnalysisMethod;
@@ -154,9 +153,8 @@ public void onTypeReachable(AnalysisType type) {
154153
*/
155154
Stream.concat(Arrays.stream(getOrDefault(type, t -> t.getInstanceFields(true), new AnalysisField[0])),
156155
Arrays.stream(getOrDefault(type, AnalysisType::getStaticFields, new AnalysisField[0])))
157-
.map(OriginalFieldProvider::getJavaField)
158-
.filter(field -> field != null && classInclusionPolicy.isFieldIncluded(field))
159-
.forEach(classInclusionPolicy::includeField);
156+
.filter(field -> field != null && classInclusionPolicy.isFieldIncluded((AnalysisField) field))
157+
.forEach(field -> classInclusionPolicy.includeField((AnalysisField) field));
160158

161159
/*
162160
* Only the class initializers that are executed at run time should be included in

0 commit comments

Comments
 (0)