3333import org .graalvm .nativeimage .Platforms ;
3434import org .graalvm .word .WordBase ;
3535
36+ import com .oracle .graal .pointsto .heap .value .ValueSupplier ;
3637import com .oracle .graal .pointsto .meta .AnalysisField ;
3738import com .oracle .graal .pointsto .meta .AnalysisType ;
3839import com .oracle .graal .pointsto .meta .AnalysisUniverse ;
4647import com .oracle .svm .core .util .VMError ;
4748import com .oracle .svm .hosted .SVMHost ;
4849import com .oracle .svm .hosted .classinitialization .ClassInitializationSupport ;
50+ import com .oracle .svm .hosted .meta .HostedMetaAccess ;
4951
5052import jdk .vm .ci .meta .Constant ;
5153import jdk .vm .ci .meta .ConstantReflectionProvider ;
@@ -102,6 +104,42 @@ public JavaConstant readValue(MetaAccessProvider suppliedMetaAccess, AnalysisFie
102104 return interceptValue (field , value );
103105 }
104106
107+ /** Read the field value and wrap it in a value supplier. */
108+ public ValueSupplier <JavaConstant > readHostedFieldValue (AnalysisField field , HostedMetaAccess hMetaAccess , JavaConstant receiver ) {
109+ if (classInitializationSupport .shouldInitializeAtRuntime (field .getDeclaringClass ())) {
110+ if (field .isStatic ()) {
111+ return ValueSupplier .eagerValue (readUninitializedStaticValue (field ));
112+ } else {
113+ /*
114+ * Classes that are initialized at run time must not have instances in the image
115+ * heap. Invoking instance methods would miss the class initialization checks. Image
116+ * generation should have been aborted earlier with a user-friendly message, this is
117+ * just a safeguard.
118+ */
119+ throw VMError .shouldNotReachHere ("Cannot read instance field of a class that is initialized at run time: " + field .format ("%H.%n" ));
120+ }
121+ }
122+
123+ if (field .wrapped instanceof ReadableJavaField ) {
124+ ReadableJavaField readableField = (ReadableJavaField ) field .wrapped ;
125+ if (readableField .isValueAvailableBeforeAnalysis ()) {
126+ /* Materialize and return the value. */
127+ return ValueSupplier .eagerValue (universe .lookup (readableField .readValue (metaAccess , receiver )));
128+ } else {
129+ /*
130+ * Return a lazy value. This applies to RecomputeFieldValue.Kind.FieldOffset and
131+ * RecomputeFieldValue.Kind.Custom. The value becomes available during hosted
132+ * universe building and is installed by calling
133+ * ComputedValueField.processSubstrate() or by ComputedValueField.readValue().
134+ * Attempts to materialize the value earlier will result in an error.
135+ */
136+ return ValueSupplier .lazyValue (() -> universe .lookup (readableField .readValue (hMetaAccess , receiver )),
137+ readableField ::isValueAvailable );
138+ }
139+ }
140+ return ValueSupplier .eagerValue (universe .lookup (originalConstantReflection .readFieldValue (field .wrapped , receiver )));
141+ }
142+
105143 /*
106144 * Static fields of classes that are initialized at run time have the default (uninitialized)
107145 * value in the image heap. But there is one important exception:
@@ -126,7 +164,8 @@ public JavaConstant readValue(MetaAccessProvider suppliedMetaAccess, AnalysisFie
126164 * pretty likely (although not guaranteed) that we are not returning an unintended value for a
127165 * class that is re-initialized at run time.
128166 */
129- public static JavaConstant readUninitializedStaticValue (AnalysisField field ) {
167+ public JavaConstant readUninitializedStaticValue (AnalysisField field ) {
168+ assert classInitializationSupport .shouldInitializeAtRuntime (field .getDeclaringClass ());
130169 JavaKind kind = field .getJavaKind ();
131170
132171 boolean canHaveConstantValueAttribute = kind .isPrimitive () || field .getType ().getName ().equals ("Ljava/lang/String;" );
0 commit comments