@@ -93,7 +93,13 @@ public boolean isInConfiguration(IsInConfigurationAccess access) {
9393 }
9494
9595 @ Override
96- public void beforeAnalysis (BeforeAnalysisAccess access ) {
96+ public void duringSetup (DuringSetupAccess access ) {
97+ access .registerObjectReplacer (VectorAPIFeature ::eagerlyInitializeValueLayout );
98+ }
99+
100+ @ Override
101+ public void beforeAnalysis (BeforeAnalysisAccess a ) {
102+ var access = (FeatureImpl .BeforeAnalysisAccessImpl ) a ;
97103 /*
98104 * We will initialize all classes in the Vector API package at build time. This is necessary
99105 * to avoid class initialization checks in hot paths, and generally because we need to see
@@ -152,6 +158,12 @@ public void beforeAnalysis(BeforeAnalysisAccess access) {
152158
153159 Class <?> laneTypeClass = ReflectionUtil .lookupClass (VECTOR_API_PACKAGE_NAME + ".LaneType" );
154160 UNSAFE .ensureClassInitialized (laneTypeClass );
161+ access .allowStableFieldFoldingBeforeAnalysis (ReflectionUtil .lookupField (laneTypeClass , "asIntegral" ));
162+ access .allowStableFieldFoldingBeforeAnalysis (ReflectionUtil .lookupField (laneTypeClass , "asFloating" ));
163+ access .allowStableFieldFoldingBeforeAnalysis (ReflectionUtil .lookupField (laneTypeClass , "ENUM_VALUES" ));
164+ access .allowStableFieldFoldingBeforeAnalysis (ReflectionUtil .lookupField (laneTypeClass , "ENUM_FROM_SK" ));
165+ access .allowStableFieldFoldingBeforeAnalysis (ReflectionUtil .lookupField (laneTypeClass , "ENUM_FROM_C0" ));
166+ access .allowStableFieldFoldingBeforeAnalysis (ReflectionUtil .lookupField (laneTypeClass , "ENUM_FROM_BT" ));
155167
156168 Class <?> speciesClass = ReflectionUtil .lookupClass (VECTOR_API_PACKAGE_NAME + ".AbstractSpecies" );
157169 Object speciesCache = Array .newInstance (speciesClass , ReflectionUtil .readStaticField (laneTypeClass , "SK_LIMIT" ), ReflectionUtil .readStaticField (vectorShapeClass , "SK_LIMIT" ));
@@ -174,15 +186,11 @@ public void beforeAnalysis(BeforeAnalysisAccess access) {
174186 (receiver , originalValue ) -> makeIotaVector (maxVectorClass , laneType .elementClass (), laneCount ));
175187 }
176188
177- Class <?> valueLayoutClass = ReflectionUtil .lookupClass ("java.lang.foreign.ValueLayout" );
178- Method valueLayoutVarHandle = ReflectionUtil .lookupMethod (valueLayoutClass , "varHandle" );
179-
180189 for (LaneType laneType : laneTypes ) {
181190 // Ensure VarHandle used by memorySegmentGet/Set is initialized.
182191 // Java 22+: ValueLayout valueLayout = (...); valueLayout.varHandle();
183192 Object valueLayout = ReflectionUtil .readStaticField (laneType .vectorClass (), "ELEMENT_LAYOUT" );
184- VarHandle varHandle = ReflectionUtil .invokeMethod (valueLayoutVarHandle , valueLayout );
185- VarHandleFeature .eagerlyInitializeVarHandle (varHandle );
193+ eagerlyInitializeValueLayout (valueLayout );
186194
187195 for (Shape shape : shapes ) {
188196 String fieldName = "SPECIES_" + shape .shapeName ().toUpperCase (Locale .ROOT );
@@ -197,17 +205,34 @@ public void beforeAnalysis(BeforeAnalysisAccess access) {
197205 Object laneTypeObject = ReflectionUtil .readStaticField (laneTypeClass , laneType .elementName ().toUpperCase (Locale .ROOT ));
198206 speciesStableFields .put (species , new AbstractSpeciesStableFields (laneCount , laneCountLog2P1 , vectorBitSize , vectorByteSize , dummyVector , laneTypeObject ));
199207
208+ // Initialize @Stable fields indexSpecies and swapBytesShuffle to allow folding
209+ Method indexSpecies = ReflectionUtil .lookupMethod (speciesClass , "indexSpecies" );
210+ ReflectionUtil .invokeMethod (indexSpecies , species );
211+ Method swapBytesShuffle = ReflectionUtil .lookupMethod (speciesClass , "swapBytesShuffle" );
212+ ReflectionUtil .invokeMethod (swapBytesShuffle , species );
213+
200214 Array .set (Array .get (speciesCache , laneType .switchKey ()), shape .switchKey (), species );
201215 }
202216 }
203217
218+ Field dummyVectorField = ReflectionUtil .lookupField (speciesClass , "dummyVector" );
219+ Field cachesField = ReflectionUtil .lookupField (speciesClass , "CACHES" );
220+
204221 access .registerFieldValueTransformer (ReflectionUtil .lookupField (speciesClass , "laneCount" ), new OverrideFromMap <>(speciesStableFields , AbstractSpeciesStableFields ::laneCount ));
205222 access .registerFieldValueTransformer (ReflectionUtil .lookupField (speciesClass , "laneCountLog2P1" ), new OverrideFromMap <>(speciesStableFields , AbstractSpeciesStableFields ::laneCountLog2P1 ));
206223 access .registerFieldValueTransformer (ReflectionUtil .lookupField (speciesClass , "vectorBitSize" ), new OverrideFromMap <>(speciesStableFields , AbstractSpeciesStableFields ::vectorBitSize ));
207224 access .registerFieldValueTransformer (ReflectionUtil .lookupField (speciesClass , "vectorByteSize" ), new OverrideFromMap <>(speciesStableFields , AbstractSpeciesStableFields ::vectorByteSize ));
208- access .registerFieldValueTransformer (ReflectionUtil . lookupField ( speciesClass , "dummyVector" ) , new OverrideFromMap <>(speciesStableFields , AbstractSpeciesStableFields ::dummyVector ));
225+ access .registerFieldValueTransformer (dummyVectorField , new OverrideFromMap <>(speciesStableFields , AbstractSpeciesStableFields ::dummyVector ));
209226 access .registerFieldValueTransformer (ReflectionUtil .lookupField (speciesClass , "laneType" ), new OverrideFromMap <>(speciesStableFields , AbstractSpeciesStableFields ::laneType ));
210- access .registerFieldValueTransformer (ReflectionUtil .lookupField (speciesClass , "CACHES" ), (receiver , originalValue ) -> speciesCache );
227+ access .registerFieldValueTransformer (cachesField , (receiver , originalValue ) -> speciesCache );
228+
229+ access .allowStableFieldFoldingBeforeAnalysis (dummyVectorField );
230+ access .allowStableFieldFoldingBeforeAnalysis (ReflectionUtil .lookupField (speciesClass , "indexSpecies" ));
231+ access .allowStableFieldFoldingBeforeAnalysis (ReflectionUtil .lookupField (speciesClass , "swapBytesShuffle" ));
232+ access .allowStableFieldFoldingBeforeAnalysis (cachesField );
233+
234+ // We can fold AbstractValueLayout.handle because we eagerly initialize all ValueLayouts.
235+ access .allowStableFieldFoldingBeforeAnalysis (ReflectionUtil .lookupField (ReflectionUtil .lookupClass ("jdk.internal.foreign.layout.ValueLayouts$AbstractValueLayout" ), "handle" ));
211236
212237 /*
213238 * Manually initialize some inner classes and mark them as reachable. Due to the way we
@@ -248,6 +273,8 @@ public void beforeAnalysis(BeforeAnalysisAccess access) {
248273 }
249274 }
250275
276+ access .allowStableFieldFoldingBeforeAnalysis (warmupData .implCacheField );
277+
251278 /* Warm up caches for mapping between lane types, used by shuffles. */
252279 Method asIntegral = ReflectionUtil .lookupMethod (speciesClass , "asIntegral" );
253280 Method asFloating = ReflectionUtil .lookupMethod (speciesClass , "asFloating" );
@@ -269,6 +296,7 @@ public void beforeAnalysis(BeforeAnalysisAccess access) {
269296 Class <?> conversionImplClass = ReflectionUtil .lookupClass (VECTOR_API_PACKAGE_NAME + ".VectorOperators$ConversionImpl" );
270297 UNSAFE .ensureClassInitialized (conversionImplClass );
271298 makeConversionOperations (conversionImplClass , warmupData );
299+ access .allowStableFieldFoldingBeforeAnalysis (ReflectionUtil .lookupField (conversionImplClass , "CACHES" ));
272300
273301 if (DeoptimizationSupport .enabled ()) {
274302 /* Build a table of payload type descriptors for deoptimization. */
@@ -294,6 +322,17 @@ public void beforeAnalysis(BeforeAnalysisAccess access) {
294322 }
295323 }
296324
325+ private static final Class <?> valueLayoutClass = ReflectionUtil .lookupClass ("java.lang.foreign.ValueLayout" );
326+ private static final Method valueLayoutVarHandle = ReflectionUtil .lookupMethod (valueLayoutClass , "varHandle" );
327+
328+ private static Object eagerlyInitializeValueLayout (Object valueLayout ) {
329+ if (valueLayoutClass .isInstance (valueLayout )) {
330+ VarHandle varHandle = ReflectionUtil .invokeMethod (valueLayoutVarHandle , valueLayout );
331+ VarHandleFeature .eagerlyInitializeVarHandle (varHandle );
332+ }
333+ return valueLayout ;
334+ }
335+
297336 private static Class <?> vectorClass (LaneType laneType , Shape shape ) {
298337 String baseName = laneType .elementName () + shape .shapeName ();
299338 String vectorClassName = VECTOR_API_PACKAGE_NAME + "." + baseName + "Vector" ;
0 commit comments