Skip to content

Commit 0e1efbf

Browse files
committed
do not intrinsify boxing if box type is uninitialized (GR-44739)
1 parent 33609eb commit 0e1efbf

File tree

3 files changed

+53
-15
lines changed

3 files changed

+53
-15
lines changed

compiler/src/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/spi/JavaConstantFieldProvider.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -132,8 +132,11 @@ protected boolean isPrimitiveBoxingCacheField(ResolvedJavaField field) {
132132
if (isArray(field) && field.isFinal() && field.getName().equals("cache")) {
133133
ResolvedJavaType type = field.getDeclaringClass();
134134
String typeName = type.getName();
135-
if (typeName.equals("Ljava/lang/Character$CharacterCache;") || typeName.equals("Ljava/lang/Byte$ByteCache;") || typeName.equals("Ljava/lang/Short$ShortCache;") ||
136-
typeName.equals("Ljava/lang/Integer$IntegerCache;") || typeName.equals("Ljava/lang/Long$LongCache;")) {
135+
if (typeName.equals("Ljava/lang/Character$CharacterCache;") ||
136+
typeName.equals("Ljava/lang/Byte$ByteCache;") ||
137+
typeName.equals("Ljava/lang/Short$ShortCache;") ||
138+
typeName.equals("Ljava/lang/Integer$IntegerCache;") ||
139+
typeName.equals("Ljava/lang/Long$LongCache;")) {
137140
return true;
138141
}
139142
}

compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/BoxingSnippets.java

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -230,19 +230,24 @@ public Templates(OptionValues options, Group.Factory factory, Providers provider
230230
valueCounter = new SnippetCounter(group, "<kind>Value", "unbox intrinsification");
231231
}
232232

233-
private static LocationIdentity getCacheLocation(CoreProviders providers, JavaKind kind) {
233+
static Class<?> getCacheClass(JavaKind kind) {
234234
Class<?>[] innerClasses = null;
235-
try {
236-
innerClasses = kind.toBoxedJavaClass().getDeclaredClasses();
237-
if (innerClasses == null || innerClasses.length == 0) {
238-
throw GraalError.shouldNotReachHere("Inner classes must exist"); // ExcludeFromJacocoGeneratedReport
235+
innerClasses = kind.toBoxedJavaClass().getDeclaredClasses();
236+
for (Class<?> innerClass : innerClasses) {
237+
if (innerClass.getSimpleName().equals(kind.toBoxedJavaClass().getSimpleName() + "Cache")) {
238+
return innerClass;
239239
}
240-
for (Class<?> innerClass : innerClasses) {
241-
if (innerClass.getName().endsWith("Cache")) {
242-
return new FieldLocationIdentity(providers.getMetaAccess().lookupJavaField(innerClass.getDeclaredField("cache")));
243-
}
244-
}
245-
throw GraalError.shouldNotReachHere("No cache inner class found"); // ExcludeFromJacocoGeneratedReport
240+
}
241+
return null;
242+
}
243+
244+
private static LocationIdentity getCacheLocation(CoreProviders providers, JavaKind kind) {
245+
Class<?> cacheClass = getCacheClass(kind);
246+
if (cacheClass == null) {
247+
throw GraalError.shouldNotReachHere(String.format("Cache class for %s not found", kind)); // ExcludeFromJacocoGeneratedReport
248+
}
249+
try {
250+
return new FieldLocationIdentity(providers.getMetaAccess().lookupJavaField(cacheClass.getDeclaredField("cache")));
246251
} catch (Throwable e) {
247252
throw GraalError.shouldNotReachHere(e); // ExcludeFromJacocoGeneratedReport
248253
}

compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/StandardGraphBuilderPlugins.java

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import static org.graalvm.compiler.core.common.memory.MemoryOrderMode.RELEASE;
3434
import static org.graalvm.compiler.core.common.memory.MemoryOrderMode.VOLATILE;
3535
import static org.graalvm.compiler.nodes.NamedLocationIdentity.OFF_HEAP_LOCATION;
36+
import static org.graalvm.compiler.replacements.BoxingSnippets.Templates.getCacheClass;
3637
import static org.graalvm.compiler.replacements.nodes.AESNode.CryptMode.DECRYPT;
3738
import static org.graalvm.compiler.replacements.nodes.AESNode.CryptMode.ENCRYPT;
3839

@@ -41,6 +42,8 @@
4142
import java.lang.reflect.Type;
4243
import java.math.BigInteger;
4344
import java.util.Arrays;
45+
import java.util.EnumMap;
46+
import java.util.Map;
4447
import java.util.Objects;
4548
import java.util.function.BiFunction;
4649

@@ -1310,17 +1313,44 @@ public static class BoxPlugin extends InvocationPlugin {
13101313
this.kind = kind;
13111314
}
13121315

1316+
static final Map<JavaKind, Class<?>> boxClassToCacheClass = new EnumMap<>(Map.of(
1317+
JavaKind.Boolean, Boolean.class,
1318+
JavaKind.Char, getCacheClass(JavaKind.Char),
1319+
JavaKind.Byte, getCacheClass(JavaKind.Byte),
1320+
JavaKind.Short, getCacheClass(JavaKind.Short),
1321+
JavaKind.Int, getCacheClass(JavaKind.Int),
1322+
JavaKind.Long, getCacheClass(JavaKind.Long)));
1323+
1324+
private boolean isCacheTypeInitialized(MetaAccessProvider metaAccess) {
1325+
Class<?> cacheClass = boxClassToCacheClass.get(kind);
1326+
if (cacheClass != null) {
1327+
ResolvedJavaType cacheType = metaAccess.lookupJavaType(cacheClass);
1328+
if (!cacheType.isInitialized()) {
1329+
return false;
1330+
}
1331+
}
1332+
return true;
1333+
}
1334+
13131335
@Override
13141336
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode value) {
1337+
MetaAccessProvider metaAccess = b.getMetaAccess();
13151338
if (b.parsingIntrinsic()) {
13161339
ResolvedJavaMethod rootMethod = b.getGraph().method();
1317-
if (b.getMetaAccess().lookupJavaType(BoxingSnippets.class).isAssignableFrom(rootMethod.getDeclaringClass())) {
1340+
if (metaAccess.lookupJavaType(BoxingSnippets.class).isAssignableFrom(rootMethod.getDeclaringClass())) {
13181341
// Disable invocation plugins for boxing snippets so that the
13191342
// original JDK methods are inlined
13201343
return false;
13211344
}
13221345
}
1323-
ResolvedJavaType resultType = b.getMetaAccess().lookupJavaType(kind.toBoxedJavaClass());
1346+
ResolvedJavaType resultType = metaAccess.lookupJavaType(kind.toBoxedJavaClass());
1347+
1348+
// Cannot perform boxing if the box type or its cache (if any) is not initialized
1349+
// or failed during initialization (e.g. StackOverflowError in LongCache.<clinit>).
1350+
if (!resultType.isInitialized() || !isCacheTypeInitialized(metaAccess)) {
1351+
return false;
1352+
}
1353+
13241354
b.addPush(JavaKind.Object, BoxNode.create(value, resultType, kind));
13251355
return true;
13261356
}

0 commit comments

Comments
 (0)