Skip to content

Commit ba40f27

Browse files
committed
Add UnsafeAccess.hostUnsafeCast and mark extension arrays as non-null.
Ensure extension arrays are seen as non-null in host compilation. Remove DynamicField annotation from the array fields to avoid marking them as unsafe-accessed.
1 parent 5267639 commit ba40f27

File tree

3 files changed

+91
-6
lines changed

3 files changed

+91
-6
lines changed

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/truffle/substitutions/TruffleInvocationPlugins.java

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
import jdk.graal.compiler.nodes.calc.CompareNode;
5959
import jdk.graal.compiler.nodes.calc.FloatConvertNode;
6060
import jdk.graal.compiler.nodes.calc.LeftShiftNode;
61+
import jdk.graal.compiler.nodes.extended.ValueAnchorNode;
6162
import jdk.graal.compiler.nodes.graphbuilderconf.GraphBuilderContext;
6263
import jdk.graal.compiler.nodes.graphbuilderconf.InvocationPlugin;
6364
import jdk.graal.compiler.nodes.graphbuilderconf.InvocationPlugin.ConditionalInvocationPlugin;
@@ -111,6 +112,7 @@ public static void register(Architecture architecture, InvocationPlugins plugins
111112
registerFramePlugins(plugins);
112113
registerBytecodePlugins(plugins);
113114
registerCompilerDirectivesPlugins(plugins);
115+
registerDynamicObjectPlugins(plugins);
114116
}
115117

116118
private static void registerFramePlugins(InvocationPlugins plugins) {
@@ -830,4 +832,64 @@ public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Rec
830832
}
831833
});
832834
}
835+
836+
private static void registerDynamicObjectPlugins(InvocationPlugins plugins) {
837+
plugins.registerIntrinsificationPredicate(t -> t.getName().equals("Lcom/oracle/truffle/api/object/UnsafeAccess;"));
838+
InvocationPlugins.Registration r = new InvocationPlugins.Registration(plugins, "com.oracle.truffle.api.object.UnsafeAccess");
839+
r.register(new OptionalInlineOnlyInvocationPlugin("hostUnsafeCast", Object.class, Class.class, boolean.class, boolean.class, boolean.class) {
840+
@Override
841+
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode object, ValueNode clazz, ValueNode condition, ValueNode nonNull,
842+
ValueNode isExactType) {
843+
if (!clazz.isConstant() || !nonNull.isConstant() || !isExactType.isConstant()) {
844+
b.push(JavaKind.Object, object);
845+
return true;
846+
}
847+
if (!Options.TruffleTrustedTypeCast.getValue(b.getOptions())) {
848+
b.push(JavaKind.Object, object);
849+
return true;
850+
}
851+
ConstantReflectionProvider constantReflection = b.getConstantReflection();
852+
ResolvedJavaType javaType = constantReflection.asJavaType(clazz.asConstant());
853+
if (javaType == null) {
854+
b.push(JavaKind.Object, object);
855+
return true;
856+
}
857+
858+
TypeReference type;
859+
if (isExactType.asJavaConstant().asInt() != 0) {
860+
assert javaType.isConcrete() || javaType.isArray() : "exact type is not a concrete class: " + javaType;
861+
type = TypeReference.createExactTrusted(javaType);
862+
} else {
863+
type = TypeReference.createTrusted(b.getAssumptions(), javaType);
864+
}
865+
866+
boolean trustedNonNull = nonNull.asJavaConstant().asInt() != 0 && Options.TruffleTrustedNonNullCast.getValue(b.getOptions());
867+
Stamp piStamp = StampFactory.object(type, trustedNonNull);
868+
869+
ValueNode valueAnchorNode;
870+
if (condition.isConstant()) {
871+
if (condition.asJavaConstant().asInt() == 1) {
872+
// Nothing to do.
873+
valueAnchorNode = null;
874+
} else {
875+
valueAnchorNode = b.add(new ValueAnchorNode());
876+
}
877+
} else {
878+
LogicNode compareNode = CompareNode.createCompareNode(CanonicalCondition.EQ, condition, ConstantNode.forBoolean(true), constantReflection, NodeView.DEFAULT);
879+
if (compareNode instanceof LogicConstantNode logicConstantNode) {
880+
if (logicConstantNode.getValue()) {
881+
valueAnchorNode = null;
882+
} else {
883+
valueAnchorNode = b.add(new ValueAnchorNode());
884+
}
885+
} else {
886+
valueAnchorNode = b.add(new ConditionAnchorNode(compareNode));
887+
}
888+
}
889+
890+
b.addPush(JavaKind.Object, PiNode.create(object, piStamp, valueAnchorNode));
891+
return true;
892+
}
893+
});
894+
}
833895
}

truffle/src/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/DynamicObject.java

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
import java.lang.invoke.MethodHandles.Lookup;
5050
import java.lang.reflect.Field;
5151
import java.util.Map;
52+
import java.util.Objects;
5253

5354
import com.oracle.truffle.api.CompilerAsserts;
5455
import com.oracle.truffle.api.CompilerDirectives;
@@ -196,9 +197,9 @@ public abstract class DynamicObject implements TruffleObject {
196197
private Shape shape;
197198

198199
/** Object extension array. */
199-
@DynamicField private Object[] extRef = EMPTY_OBJECT_ARRAY;
200+
private Object[] extRef = EMPTY_OBJECT_ARRAY;
200201
/** Primitive extension array. */
201-
@DynamicField private int[] extVal = EMPTY_INT_ARRAY;
202+
private int[] extVal = EMPTY_INT_ARRAY;
202203

203204
/**
204205
* Constructor for {@link DynamicObject} subclasses. Initializes the object with the provided
@@ -321,19 +322,25 @@ private static CloneNotSupportedException cloneNotSupported() throws CloneNotSup
321322
}
322323

323324
final Object[] getObjectStore() {
325+
if (CompilerDirectives.inInterpreter()) {
326+
return UnsafeAccess.hostUnsafeCast(extRef, Object[].class, false, true, true);
327+
}
324328
return extRef;
325329
}
326330

327331
final void setObjectStore(Object[] newArray) {
328-
extRef = newArray;
332+
extRef = Objects.requireNonNull(newArray);
329333
}
330334

331335
final int[] getPrimitiveStore() {
336+
if (CompilerDirectives.inInterpreter()) {
337+
return UnsafeAccess.hostUnsafeCast(extVal, int[].class, false, true, true);
338+
}
332339
return extVal;
333340
}
334341

335342
final void setPrimitiveStore(int[] newArray) {
336-
extVal = newArray;
343+
extVal = Objects.requireNonNull(newArray);
337344
}
338345

339346
static Class<? extends Annotation> getDynamicFieldAnnotation() {

truffle/src/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/UnsafeAccess.java

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,8 @@ static boolean booleanCast(int value) {
7474
}
7575

7676
/**
77-
* Casts the given value to the value of the given type without any checks. The type, nonNull,
78-
* and exact must evaluate to a constant. The condition parameter gives a hint to the compiler
77+
* Casts the given value to the given type without any checks. The type, nonNull, and exact
78+
* parameters must evaluate to a constant. The condition parameter gives a hint to the compiler
7979
* under which circumstances this cast can be moved to an earlier location in the program.
8080
*
8181
* @param value the value that is known to have the specified type
@@ -90,6 +90,22 @@ static <T> T unsafeCast(Object value, Class<T> type, boolean condition, boolean
9090
return (T) value;
9191
}
9292

93+
/**
94+
* Casts the given value to the given type without any checks during host compilation. The type,
95+
* nonNull, and exact parameters must evaluate to a constant for the cast to have any effect.
96+
*
97+
* @param value the value that is known to have the specified type
98+
* @param type the specified new type of the value
99+
* @param condition the condition that makes this cast safe also at an earlier location
100+
* @param nonNull whether value is known to never be null
101+
* @param exact whether the value is known to be of exactly the specified class
102+
* @return the value to be cast to the new type
103+
*/
104+
@SuppressWarnings("unchecked")
105+
static <T> T hostUnsafeCast(Object value, Class<T> type, boolean condition, boolean nonNull, boolean exact) {
106+
return (T) value;
107+
}
108+
93109
/**
94110
* Like {@link System#arraycopy}, but kills any location.
95111
*/

0 commit comments

Comments
 (0)