Skip to content

Commit c91ec90

Browse files
committed
[GR-71665] [GR-71666] Use JVMCIFieldValueTransformer for implementation
PullRequest: graal/22821
2 parents 8dd85b3 + 60a1fc6 commit c91ec90

23 files changed

+506
-165
lines changed

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/fieldvaluetransformer/ArrayBaseOffsetFieldValueTransformer.java

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,20 +24,21 @@
2424
*/
2525
package com.oracle.svm.core.fieldvaluetransformer;
2626

27-
import org.graalvm.nativeimage.hosted.FieldValueTransformer;
28-
2927
import com.oracle.svm.core.annotate.RecomputeFieldValue.Kind;
3028
import com.oracle.svm.core.config.ConfigurationValues;
29+
import com.oracle.svm.util.JVMCIFieldValueTransformer;
3130

31+
import jdk.vm.ci.meta.JavaConstant;
3232
import jdk.vm.ci.meta.JavaKind;
33+
import jdk.vm.ci.meta.ResolvedJavaType;
3334

3435
/**
3536
* Implements the field value transformation semantics of {@link Kind#ArrayBaseOffset}.
3637
*/
37-
public record ArrayBaseOffsetFieldValueTransformer(Class<?> targetClass, JavaKind returnKind) implements FieldValueTransformer {
38+
public record ArrayBaseOffsetFieldValueTransformer(ResolvedJavaType targetClass, JavaKind returnKind) implements JVMCIFieldValueTransformer {
3839

3940
@Override
40-
public Object transform(Object receiver, Object originalValue) {
41-
return FieldOffsetFieldValueTransformer.box(returnKind, ConfigurationValues.getObjectLayout().getArrayBaseOffset(JavaKind.fromJavaClass(targetClass.getComponentType())));
41+
public JavaConstant transform(JavaConstant receiver, JavaConstant originalValue) {
42+
return FieldOffsetFieldValueTransformer.constant(returnKind, ConfigurationValues.getObjectLayout().getArrayBaseOffset(targetClass.getComponentType().getJavaKind()));
4243
}
4344
}

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/fieldvaluetransformer/ArrayIndexScaleFieldValueTransformer.java

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,20 +24,21 @@
2424
*/
2525
package com.oracle.svm.core.fieldvaluetransformer;
2626

27-
import org.graalvm.nativeimage.hosted.FieldValueTransformer;
28-
2927
import com.oracle.svm.core.annotate.RecomputeFieldValue.Kind;
3028
import com.oracle.svm.core.config.ConfigurationValues;
29+
import com.oracle.svm.util.JVMCIFieldValueTransformer;
3130

31+
import jdk.vm.ci.meta.JavaConstant;
3232
import jdk.vm.ci.meta.JavaKind;
33+
import jdk.vm.ci.meta.ResolvedJavaType;
3334

3435
/**
3536
* Implements the field value transformation semantics of {@link Kind#ArrayIndexScale}.
3637
*/
37-
public record ArrayIndexScaleFieldValueTransformer(Class<?> targetClass, JavaKind returnKind) implements FieldValueTransformer {
38+
public record ArrayIndexScaleFieldValueTransformer(ResolvedJavaType targetClass, JavaKind returnKind) implements JVMCIFieldValueTransformer {
3839

3940
@Override
40-
public Object transform(Object receiver, Object originalValue) {
41-
return FieldOffsetFieldValueTransformer.box(returnKind, ConfigurationValues.getObjectLayout().getArrayIndexScale(JavaKind.fromJavaClass(targetClass.getComponentType())));
41+
public JavaConstant transform(JavaConstant receiver, JavaConstant originalValue) {
42+
return FieldOffsetFieldValueTransformer.constant(returnKind, ConfigurationValues.getObjectLayout().getArrayIndexScale(targetClass.getComponentType().getJavaKind()));
4243
}
4344
}

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/fieldvaluetransformer/ArrayIndexShiftFieldValueTransformer.java

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,20 +24,21 @@
2424
*/
2525
package com.oracle.svm.core.fieldvaluetransformer;
2626

27-
import org.graalvm.nativeimage.hosted.FieldValueTransformer;
28-
2927
import com.oracle.svm.core.annotate.RecomputeFieldValue.Kind;
3028
import com.oracle.svm.core.config.ConfigurationValues;
29+
import com.oracle.svm.util.JVMCIFieldValueTransformer;
3130

31+
import jdk.vm.ci.meta.JavaConstant;
3232
import jdk.vm.ci.meta.JavaKind;
33+
import jdk.vm.ci.meta.ResolvedJavaType;
3334

3435
/**
3536
* Implements the field value transformation semantics of {@link Kind#ArrayIndexShift}.
3637
*/
37-
public record ArrayIndexShiftFieldValueTransformer(Class<?> targetClass, JavaKind returnKind) implements FieldValueTransformer {
38+
public record ArrayIndexShiftFieldValueTransformer(ResolvedJavaType targetClass, JavaKind returnKind) implements JVMCIFieldValueTransformer {
3839

3940
@Override
40-
public Object transform(Object receiver, Object originalValue) {
41-
return FieldOffsetFieldValueTransformer.box(returnKind, ConfigurationValues.getObjectLayout().getArrayIndexShift(JavaKind.fromJavaClass(targetClass.getComponentType())));
41+
public JavaConstant transform(JavaConstant receiver, JavaConstant originalValue) {
42+
return FieldOffsetFieldValueTransformer.constant(returnKind, ConfigurationValues.getObjectLayout().getArrayIndexShift(targetClass.getComponentType().getJavaKind()));
4243
}
4344
}

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/fieldvaluetransformer/ConstantValueFieldValueTransformer.java

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,11 @@
2424
*/
2525
package com.oracle.svm.core.fieldvaluetransformer;
2626

27-
import org.graalvm.nativeimage.hosted.FieldValueTransformer;
28-
2927
import com.oracle.svm.core.annotate.RecomputeFieldValue.Kind;
3028
import com.oracle.svm.core.util.VMError;
29+
import com.oracle.svm.util.JVMCIFieldValueTransformer;
3130

31+
import jdk.vm.ci.meta.JavaConstant;
3232
import jdk.vm.ci.meta.ResolvedJavaField;
3333

3434
/**
@@ -37,25 +37,25 @@
3737
* When that value is the {@link #defaultValueForField default value for the field}, this
3838
* transformer implements the field value transformation semantics of {@link Kind#Reset}.
3939
*/
40-
public record ConstantValueFieldValueTransformer(Object value) implements FieldValueTransformer {
40+
public record ConstantValueFieldValueTransformer(JavaConstant value) implements JVMCIFieldValueTransformer {
4141

42-
public static FieldValueTransformer defaultValueForField(ResolvedJavaField field) {
42+
public static JVMCIFieldValueTransformer defaultValueForField(ResolvedJavaField field) {
4343
return new ConstantValueFieldValueTransformer(switch (field.getType().getJavaKind()) {
44-
case Byte -> Byte.valueOf((byte) 0);
45-
case Boolean -> Boolean.valueOf(false);
46-
case Short -> Short.valueOf((short) 0);
47-
case Char -> Character.valueOf((char) 0);
48-
case Int -> Integer.valueOf(0);
49-
case Long -> Long.valueOf(0);
50-
case Float -> Float.valueOf(0);
51-
case Double -> Double.valueOf(0);
52-
case Object -> null;
44+
case Byte -> JavaConstant.forByte((byte) 0);
45+
case Boolean -> JavaConstant.FALSE;
46+
case Short -> JavaConstant.forShort((short) 0);
47+
case Char -> JavaConstant.forChar((char) 0);
48+
case Int -> JavaConstant.INT_0;
49+
case Long -> JavaConstant.LONG_0;
50+
case Float -> JavaConstant.FLOAT_0;
51+
case Double -> JavaConstant.DOUBLE_0;
52+
case Object -> JavaConstant.NULL_POINTER;
5353
default -> throw VMError.shouldNotReachHere(String.valueOf(field));
5454
});
5555
}
5656

5757
@Override
58-
public Object transform(Object receiver, Object originalValue) {
58+
public JavaConstant transform(JavaConstant receiver, JavaConstant originalValue) {
5959
return value;
6060
}
6161
}

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/fieldvaluetransformer/FieldOffsetFieldValueTransformer.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,14 @@ static Object box(JavaKind returnKind, int value) {
6767
}
6868
}
6969

70+
static JavaConstant constant(JavaKind returnKind, int value) {
71+
return switch (returnKind) {
72+
case Int -> JavaConstant.forInt(value);
73+
case Long -> JavaConstant.forLong(value);
74+
default -> throw VMError.shouldNotReachHere("Unexpected kind: " + returnKind);
75+
};
76+
}
77+
7078
@Override
7179
public ValueNode intrinsify(CoreProviders providers, JavaConstant receiver) {
7280
return FieldOffsetNode.create(returnKind, providers.getMetaAccess().lookupJavaField(targetField));

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/fieldvaluetransformer/FieldValueTransformerWithAvailability.java

Lines changed: 48 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -28,26 +28,65 @@
2828
import org.graalvm.nativeimage.Platforms;
2929
import org.graalvm.nativeimage.hosted.FieldValueTransformer;
3030

31-
import jdk.graal.compiler.nodes.ValueNode;
32-
import jdk.graal.compiler.nodes.spi.CoreProviders;
31+
import com.oracle.svm.core.util.VMError;
32+
import com.oracle.svm.util.GraalAccess;
33+
34+
import jdk.graal.compiler.api.replacements.SnippetReflectionProvider;
3335
import jdk.vm.ci.meta.JavaConstant;
3436

37+
/**
38+
* Temporary implementation of {@link JVMCIFieldValueTransformerWithAvailability}, that falls back
39+
* to {@link FieldValueTransformer}. Usages should be migrated to
40+
* {@link JVMCIFieldValueTransformerWithAvailability} (GR-72015).
41+
*/
3542
@Platforms(Platform.HOSTED_ONLY.class)
36-
public interface FieldValueTransformerWithAvailability extends FieldValueTransformer {
43+
public interface FieldValueTransformerWithAvailability extends FieldValueTransformer, JVMCIFieldValueTransformerWithAvailability {
3744

3845
/**
3946
* Returns true when the value for this custom computation is available.
4047
*/
4148
@Override
4249
boolean isAvailable();
4350

51+
@Override
52+
Object transform(Object receiver, Object originalValue);
53+
54+
@Override
55+
default JavaConstant transform(JavaConstant receiver, JavaConstant originalValue) {
56+
return transformAndConvert(this, receiver, originalValue);
57+
}
58+
4459
/**
45-
* Optionally provide a Graal IR node to intrinsify the field access before the static analysis.
46-
* This allows the compiler to optimize field values that are not available yet, as long as
47-
* there is a dedicated high-level node available.
60+
* Transform a field value using a {@linkplain FieldValueTransformer core reflection based field
61+
* value transformer}. The {@link JavaConstant} inputs are unwrapped, the returned
62+
* {@link Object} is wrapped. This is only a temporary helper. Eventually, core reflection based
63+
* field value transformers will be executed via {@link com.oracle.graal.vmaccess.VMAccess}.
4864
*/
49-
@SuppressWarnings("unused")
50-
default ValueNode intrinsify(CoreProviders providers, JavaConstant receiver) {
51-
return null;
65+
static JavaConstant transformAndConvert(FieldValueTransformer fieldValueTransformer, JavaConstant receiver, JavaConstant originalValue) {
66+
SnippetReflectionProvider originalSnippetReflection = GraalAccess.getOriginalSnippetReflection();
67+
VMError.guarantee(originalValue != null, "Original value should not be `null`. Use `JavaConstant.NULL_POINTER`.");
68+
VMError.guarantee(receiver == null || !receiver.isNull(), "Receiver should not be a boxed `null` (`JavaConstant.isNull()`) for static fields. Use `null`instead");
69+
Object reflectionReceiver = toObject(receiver);
70+
Object reflectionOriginalValue = toObject(originalValue);
71+
Object newObject = fieldValueTransformer.transform(reflectionReceiver, reflectionOriginalValue);
72+
if (newObject == null) {
73+
return JavaConstant.NULL_POINTER;
74+
}
75+
if (newObject instanceof JavaConstantWrapper constantWrapper) {
76+
return constantWrapper.constant();
77+
}
78+
return originalSnippetReflection.forObject(newObject);
5279
}
80+
81+
private static Object toObject(JavaConstant javaConstant) {
82+
if (javaConstant == null || javaConstant.isNull()) {
83+
return null;
84+
}
85+
if (javaConstant.getJavaKind().isObject()) {
86+
SnippetReflectionProvider originalSnippetReflection = GraalAccess.getOriginalSnippetReflection();
87+
return originalSnippetReflection.asObject(Object.class, javaConstant);
88+
}
89+
return javaConstant.asBoxedPrimitive();
90+
}
91+
5392
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/*
2+
* Copyright (c) 2025, 2025, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation. Oracle designates this
8+
* particular file as subject to the "Classpath" exception as provided
9+
* by Oracle in the LICENSE file that accompanied this code.
10+
*
11+
* This code is distributed in the hope that it will be useful, but WITHOUT
12+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
* version 2 for more details (a copy is included in the LICENSE file that
15+
* accompanied this code).
16+
*
17+
* You should have received a copy of the GNU General Public License version
18+
* 2 along with this work; if not, write to the Free Software Foundation,
19+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+
*
21+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+
* or visit www.oracle.com if you need additional information or have any
23+
* questions.
24+
*/
25+
package com.oracle.svm.core.fieldvaluetransformer;
26+
27+
import org.graalvm.nativeimage.Platform;
28+
import org.graalvm.nativeimage.Platforms;
29+
30+
import com.oracle.svm.util.JVMCIFieldValueTransformer;
31+
32+
import jdk.graal.compiler.nodes.ValueNode;
33+
import jdk.graal.compiler.nodes.spi.CoreProviders;
34+
import jdk.vm.ci.meta.JavaConstant;
35+
36+
@Platforms(Platform.HOSTED_ONLY.class)
37+
public interface JVMCIFieldValueTransformerWithAvailability extends JVMCIFieldValueTransformer {
38+
39+
/**
40+
* Returns true when the value for this custom computation is available.
41+
*/
42+
@Override
43+
boolean isAvailable();
44+
45+
// remove this override once GR-72015 is fixed.
46+
@Override
47+
JavaConstant transform(JavaConstant receiver, JavaConstant originalValue);
48+
49+
/**
50+
* Optionally provide a Graal IR node to intrinsify the field access before the static analysis.
51+
* This allows the compiler to optimize field values that are not available yet, as long as
52+
* there is a dedicated high-level node available.
53+
*/
54+
@SuppressWarnings("unused")
55+
default ValueNode intrinsify(CoreProviders providers, JavaConstant receiver) {
56+
return null;
57+
}
58+
}

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/fieldvaluetransformer/NewEmptyArrayFieldValueTransformer.java

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,22 +24,30 @@
2424
*/
2525
package com.oracle.svm.core.fieldvaluetransformer;
2626

27-
import java.lang.reflect.Array;
27+
import com.oracle.svm.core.util.VMError;
28+
import com.oracle.svm.util.GraalAccess;
29+
import com.oracle.svm.util.JVMCIFieldValueTransformer;
30+
import com.oracle.svm.util.JVMCIReflectionUtil;
2831

29-
import org.graalvm.nativeimage.hosted.FieldValueTransformer;
32+
import jdk.graal.compiler.phases.util.Providers;
33+
import jdk.vm.ci.meta.JavaConstant;
34+
import jdk.vm.ci.meta.MetaAccessProvider;
3035

3136
/**
3237
* Reset an array field to a new empty array of the same type and length.
3338
*/
34-
public final class NewEmptyArrayFieldValueTransformer implements FieldValueTransformer {
35-
public static final FieldValueTransformer INSTANCE = new NewEmptyArrayFieldValueTransformer();
39+
public final class NewEmptyArrayFieldValueTransformer implements JVMCIFieldValueTransformer {
40+
public static final JVMCIFieldValueTransformer INSTANCE = new NewEmptyArrayFieldValueTransformer();
3641

3742
@Override
38-
public Object transform(Object receiver, Object originalValue) {
39-
if (originalValue == null) {
40-
return null;
43+
public JavaConstant transform(JavaConstant receiver, JavaConstant originalValue) {
44+
if (originalValue.isNull()) {
45+
return JavaConstant.NULL_POINTER;
4146
}
42-
int originalLength = Array.getLength(originalValue);
43-
return Array.newInstance(originalValue.getClass().getComponentType(), originalLength);
47+
Providers originalProviders = GraalAccess.getOriginalProviders();
48+
MetaAccessProvider metaAccess = originalProviders.getMetaAccess();
49+
Integer originalLength = originalProviders.getConstantReflection().readArrayLength(originalValue);
50+
VMError.guarantee(originalLength != null, "Original value is not an array or the array length is not known");
51+
return JVMCIReflectionUtil.newArrayInstance(metaAccess.lookupJavaType(originalValue).getComponentType(), originalLength);
4452
}
4553
}

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/fieldvaluetransformer/NewInstanceOfFixedClassFieldValueTransformer.java

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,22 +24,24 @@
2424
*/
2525
package com.oracle.svm.core.fieldvaluetransformer;
2626

27-
import org.graalvm.nativeimage.hosted.FieldValueTransformer;
28-
2927
import com.oracle.svm.core.annotate.RecomputeFieldValue.Kind;
30-
import com.oracle.svm.util.ReflectionUtil;
28+
import com.oracle.svm.util.JVMCIFieldValueTransformer;
29+
import com.oracle.svm.util.JVMCIReflectionUtil;
30+
31+
import jdk.vm.ci.meta.JavaConstant;
32+
import jdk.vm.ci.meta.ResolvedJavaType;
3133

3234
/**
3335
* Implements the field value transformation semantics of {@link Kind#NewInstance} and
3436
* {@link Kind#NewInstanceWhenNotNull}.
3537
*/
36-
public record NewInstanceOfFixedClassFieldValueTransformer(Class<?> clazz, boolean onlyIfOriginalNotNull) implements FieldValueTransformer {
38+
public record NewInstanceOfFixedClassFieldValueTransformer(ResolvedJavaType type, boolean onlyIfOriginalNotNull) implements JVMCIFieldValueTransformer {
3739

3840
@Override
39-
public Object transform(Object receiver, Object originalValue) {
40-
if (onlyIfOriginalNotNull && originalValue == null) {
41-
return null;
41+
public JavaConstant transform(JavaConstant receiver, JavaConstant originalValue) {
42+
if (onlyIfOriginalNotNull && originalValue.isNull()) {
43+
return JavaConstant.NULL_POINTER;
4244
}
43-
return ReflectionUtil.newInstance(clazz);
45+
return JVMCIReflectionUtil.newInstance(type);
4446
}
4547
}

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/reflect/target/ReflectionSubstitutionSupport.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@
3333
import com.oracle.svm.core.annotate.Delete;
3434
import com.oracle.svm.core.reflect.SubstrateAccessor;
3535

36+
/**
37+
* Should be migrated to JVMCI (GR-71897).
38+
*/
3639
public interface ReflectionSubstitutionSupport {
3740

3841
static ReflectionSubstitutionSupport singleton() {

0 commit comments

Comments
 (0)