@@ -93,7 +93,13 @@ public boolean isInConfiguration(IsInConfigurationAccess access) {
93
93
}
94
94
95
95
@ 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 ;
97
103
/*
98
104
* We will initialize all classes in the Vector API package at build time. This is necessary
99
105
* to avoid class initialization checks in hot paths, and generally because we need to see
@@ -152,6 +158,12 @@ public void beforeAnalysis(BeforeAnalysisAccess access) {
152
158
153
159
Class <?> laneTypeClass = ReflectionUtil .lookupClass (VECTOR_API_PACKAGE_NAME + ".LaneType" );
154
160
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" ));
155
167
156
168
Class <?> speciesClass = ReflectionUtil .lookupClass (VECTOR_API_PACKAGE_NAME + ".AbstractSpecies" );
157
169
Object speciesCache = Array .newInstance (speciesClass , ReflectionUtil .readStaticField (laneTypeClass , "SK_LIMIT" ), ReflectionUtil .readStaticField (vectorShapeClass , "SK_LIMIT" ));
@@ -174,15 +186,11 @@ public void beforeAnalysis(BeforeAnalysisAccess access) {
174
186
(receiver , originalValue ) -> makeIotaVector (maxVectorClass , laneType .elementClass (), laneCount ));
175
187
}
176
188
177
- Class <?> valueLayoutClass = ReflectionUtil .lookupClass ("java.lang.foreign.ValueLayout" );
178
- Method valueLayoutVarHandle = ReflectionUtil .lookupMethod (valueLayoutClass , "varHandle" );
179
-
180
189
for (LaneType laneType : laneTypes ) {
181
190
// Ensure VarHandle used by memorySegmentGet/Set is initialized.
182
191
// Java 22+: ValueLayout valueLayout = (...); valueLayout.varHandle();
183
192
Object valueLayout = ReflectionUtil .readStaticField (laneType .vectorClass (), "ELEMENT_LAYOUT" );
184
- VarHandle varHandle = ReflectionUtil .invokeMethod (valueLayoutVarHandle , valueLayout );
185
- VarHandleFeature .eagerlyInitializeVarHandle (varHandle );
193
+ eagerlyInitializeValueLayout (valueLayout );
186
194
187
195
for (Shape shape : shapes ) {
188
196
String fieldName = "SPECIES_" + shape .shapeName ().toUpperCase (Locale .ROOT );
@@ -197,17 +205,34 @@ public void beforeAnalysis(BeforeAnalysisAccess access) {
197
205
Object laneTypeObject = ReflectionUtil .readStaticField (laneTypeClass , laneType .elementName ().toUpperCase (Locale .ROOT ));
198
206
speciesStableFields .put (species , new AbstractSpeciesStableFields (laneCount , laneCountLog2P1 , vectorBitSize , vectorByteSize , dummyVector , laneTypeObject ));
199
207
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
+
200
214
Array .set (Array .get (speciesCache , laneType .switchKey ()), shape .switchKey (), species );
201
215
}
202
216
}
203
217
218
+ Field dummyVectorField = ReflectionUtil .lookupField (speciesClass , "dummyVector" );
219
+ Field cachesField = ReflectionUtil .lookupField (speciesClass , "CACHES" );
220
+
204
221
access .registerFieldValueTransformer (ReflectionUtil .lookupField (speciesClass , "laneCount" ), new OverrideFromMap <>(speciesStableFields , AbstractSpeciesStableFields ::laneCount ));
205
222
access .registerFieldValueTransformer (ReflectionUtil .lookupField (speciesClass , "laneCountLog2P1" ), new OverrideFromMap <>(speciesStableFields , AbstractSpeciesStableFields ::laneCountLog2P1 ));
206
223
access .registerFieldValueTransformer (ReflectionUtil .lookupField (speciesClass , "vectorBitSize" ), new OverrideFromMap <>(speciesStableFields , AbstractSpeciesStableFields ::vectorBitSize ));
207
224
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 ));
209
226
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" ));
211
236
212
237
/*
213
238
* Manually initialize some inner classes and mark them as reachable. Due to the way we
@@ -248,6 +273,8 @@ public void beforeAnalysis(BeforeAnalysisAccess access) {
248
273
}
249
274
}
250
275
276
+ access .allowStableFieldFoldingBeforeAnalysis (warmupData .implCacheField );
277
+
251
278
/* Warm up caches for mapping between lane types, used by shuffles. */
252
279
Method asIntegral = ReflectionUtil .lookupMethod (speciesClass , "asIntegral" );
253
280
Method asFloating = ReflectionUtil .lookupMethod (speciesClass , "asFloating" );
@@ -269,6 +296,7 @@ public void beforeAnalysis(BeforeAnalysisAccess access) {
269
296
Class <?> conversionImplClass = ReflectionUtil .lookupClass (VECTOR_API_PACKAGE_NAME + ".VectorOperators$ConversionImpl" );
270
297
UNSAFE .ensureClassInitialized (conversionImplClass );
271
298
makeConversionOperations (conversionImplClass , warmupData );
299
+ access .allowStableFieldFoldingBeforeAnalysis (ReflectionUtil .lookupField (conversionImplClass , "CACHES" ));
272
300
273
301
if (DeoptimizationSupport .enabled ()) {
274
302
/* Build a table of payload type descriptors for deoptimization. */
@@ -294,6 +322,17 @@ public void beforeAnalysis(BeforeAnalysisAccess access) {
294
322
}
295
323
}
296
324
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
+
297
336
private static Class <?> vectorClass (LaneType laneType , Shape shape ) {
298
337
String baseName = laneType .elementName () + shape .shapeName ();
299
338
String vectorClassName = VECTOR_API_PACKAGE_NAME + "." + baseName + "Vector" ;
0 commit comments