Skip to content

Commit 5aa1be7

Browse files
committed
Allow folding of @stable Vector API fields during analysis
1 parent d8ab154 commit 5aa1be7

File tree

1 file changed

+47
-8
lines changed

1 file changed

+47
-8
lines changed

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

Lines changed: 47 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)