Skip to content

Commit 07fac34

Browse files
committed
[GR-44573] Do not use marker interfaces.
PullRequest: graal/13946
2 parents b846959 + aa64e24 commit 07fac34

File tree

13 files changed

+277
-171
lines changed

13 files changed

+277
-171
lines changed

substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/TruffleBaseFeature.java

Lines changed: 64 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -725,7 +725,7 @@ public Object apply(Object object) {
725725
}
726726
}
727727

728-
private static final class StaticObjectSupport {
728+
static final class StaticObjectSupport {
729729
private static final Method VALIDATE_CLASSES = ReflectionUtil.lookupMethod(StaticShape.Builder.class, "validateClasses", Class.class, Class.class);
730730

731731
static void duringSetup(DuringSetupAccess access) {
@@ -777,23 +777,26 @@ private static boolean validateClasses(Class<?> storageSuperClass, Class<?> fact
777777
}
778778
}
779779

780-
private static final class StaticObjectArrayBasedSupport {
780+
static final class StaticObjectArrayBasedSupport {
781781
private static final Method STORAGE_CLASS_NAME = ReflectionUtil.lookupMethod(StaticShape.Builder.class, "storageClassName");
782782

783-
private static final Class<?> GENERATOR_CLASS_LOADER_CLASS = loadClass("com.oracle.truffle.api.staticobject.GeneratorClassLoader");
784-
private static final Constructor<?> GENERATOR_CLASS_LOADER_CONSTRUCTOR = ReflectionUtil.lookupConstructor(GENERATOR_CLASS_LOADER_CLASS, Class.class);
783+
private static final Class<?> GENERATOR_CLASS_LOADERS_CLASS = loadClass("com.oracle.truffle.api.staticobject.GeneratorClassLoaders");
784+
private static final Constructor<?> GENERATOR_CLASS_LOADERS_CONSTRUCTOR = ReflectionUtil.lookupConstructor(GENERATOR_CLASS_LOADERS_CLASS, Class.class);
785785

786-
private static final Class<?> ARRAY_BASED_FACTORY = loadClass("com.oracle.truffle.api.staticobject.ArrayBasedStaticShape$ArrayBasedFactory");
786+
private static final Class<?> ARRAY_BASED_STATIC_SHAPE = loadClass("com.oracle.truffle.api.staticobject.ArrayBasedStaticShape");
787787
private static final Class<?> ARRAY_BASED_SHAPE_GENERATOR = loadClass("com.oracle.truffle.api.staticobject.ArrayBasedShapeGenerator");
788788
private static final Method GET_ARRAY_BASED_SHAPE_GENERATOR = ReflectionUtil.lookupMethod(ARRAY_BASED_SHAPE_GENERATOR, "getShapeGenerator", TruffleLanguage.class,
789-
GENERATOR_CLASS_LOADER_CLASS, Class.class, Class.class, String.class);
789+
GENERATOR_CLASS_LOADERS_CLASS, Class.class, Class.class, String.class);
790790

791-
private static final Map<Class<?>, ClassLoader> CLASS_LOADERS = new ConcurrentHashMap<>();
791+
private static final Map<Class<?>, Object> GENERATOR_CLASS_LOADERS_MAP = new ConcurrentHashMap<>();
792792
private static final int ALIGNMENT_CORRECTION;
793793
private static BeforeAnalysisAccess beforeAnalysisAccess;
794794

795795
private static final IdentityHashMap<Object, Object> registeredShapeGenerators = new IdentityHashMap<>();
796796

797+
static volatile ConcurrentHashMap<Object, Object> replacements;
798+
private static final Class<?> FACTORY_CLASS_LOADER;
799+
797800
static {
798801
// ArrayBasedShapeGenerator$ArrayBasedPropertyLayout makes sure that primitives are
799802
// stored in a byte[] at offsets that are long-aligned. When using the Static Object
@@ -804,19 +807,30 @@ private static final class StaticObjectArrayBasedSupport {
804807
int longIndexScale = ConfigurationValues.getObjectLayout().getArrayIndexScale(JavaKind.Long);
805808
int misalignment = ConfigurationValues.getObjectLayout().getArrayBaseOffset(JavaKind.Byte) % longIndexScale;
806809
ALIGNMENT_CORRECTION = misalignment == 0 ? 0 : longIndexScale - misalignment;
810+
811+
if (ALIGNMENT_CORRECTION != 0) {
812+
// Can be an equality-based map because factory classes do not override
813+
// `hashCode()` and `equals()`.
814+
replacements = new ConcurrentHashMap<>();
815+
// `ArrayBasedStaticShape.replacements` must be initialized only when there is
816+
// an alignment correction, else some factories will not be replaced and will
817+
// continue to register replacement candidates.
818+
ReflectionUtil.writeStaticField(ARRAY_BASED_STATIC_SHAPE, "replacements", replacements);
819+
FACTORY_CLASS_LOADER = loadClass("com.oracle.truffle.api.staticobject.GeneratorClassLoaders$FactoryClassLoader");
820+
} else {
821+
replacements = null;
822+
FACTORY_CLASS_LOADER = null;
823+
}
807824
}
808825

809826
static void duringSetup(DuringSetupAccess access) {
810827
if (ALIGNMENT_CORRECTION != 0) {
811-
ConcurrentHashMap<Object, Object> replacements = ReflectionUtil.readField(ARRAY_BASED_FACTORY, "replacements", null);
812828
access.registerObjectReplacer(obj -> {
813829
if (!replacements.isEmpty()) {
814830
boolean isByteArray = obj instanceof byte[];
815-
if (isByteArray || ARRAY_BASED_FACTORY.isInstance(obj)) {
816-
831+
if (isByteArray || FACTORY_CLASS_LOADER.isInstance(obj.getClass().getClassLoader())) {
817832
Object replacement = replacements.get(obj);
818833
if (replacement != null) {
819-
820834
// The `replacements` map is populated by the generated
821835
// factories. The keys of this map are the primitive byte arrays
822836
// and the factory instances that must be replaced, and the
@@ -890,8 +904,8 @@ static void onBuildInvocation(Class<?> storageSuperClass, Class<?> factoryInterf
890904
* ArrayBasedShapeGenerator caches generated classes, there won't be code
891905
* generation at run time.
892906
*/
893-
ClassLoader generatorCL = getGeneratorClassLoader(factoryInterface);
894-
getGetShapeGenerator(generatorCL, storageSuperClass, factoryInterface);
907+
Object gcls = getGeneratorClassLoaders(factoryInterface);
908+
getGetShapeGenerator(gcls, storageSuperClass, factoryInterface);
895909
} catch (ReflectiveOperationException e) {
896910
throw VMError.shouldNotReachHere(e);
897911
}
@@ -929,21 +943,21 @@ static void duringAnalysis(DuringAnalysisAccess access) {
929943
}
930944
}
931945

932-
private static ClassLoader getGeneratorClassLoader(Class<?> factoryInterface) throws ReflectiveOperationException {
933-
ClassLoader cl = CLASS_LOADERS.get(factoryInterface);
934-
if (cl == null) {
935-
ClassLoader newCL = (ClassLoader) GENERATOR_CLASS_LOADER_CONSTRUCTOR.newInstance(factoryInterface);
936-
cl = CLASS_LOADERS.putIfAbsent(factoryInterface, newCL);
937-
if (cl == null) {
938-
cl = newCL;
946+
private static Object getGeneratorClassLoaders(Class<?> factoryInterface) throws ReflectiveOperationException {
947+
Object gcls = GENERATOR_CLASS_LOADERS_MAP.get(factoryInterface);
948+
if (gcls == null) {
949+
Object newGCLs = GENERATOR_CLASS_LOADERS_CONSTRUCTOR.newInstance(factoryInterface);
950+
gcls = GENERATOR_CLASS_LOADERS_MAP.putIfAbsent(factoryInterface, newGCLs);
951+
if (gcls == null) {
952+
gcls = newGCLs;
939953
}
940954
}
941-
return cl;
955+
return gcls;
942956
}
943957

944-
private static void getGetShapeGenerator(ClassLoader generatorCL, Class<?> storageSuperClass, Class<?> factoryInterface) throws ReflectiveOperationException {
958+
private static void getGetShapeGenerator(Object gcls, Class<?> storageSuperClass, Class<?> factoryInterface) throws ReflectiveOperationException {
945959
String storageClassName = (String) STORAGE_CLASS_NAME.invoke(null);
946-
GET_ARRAY_BASED_SHAPE_GENERATOR.invoke(null, null, generatorCL, storageSuperClass, factoryInterface, storageClassName);
960+
GET_ARRAY_BASED_SHAPE_GENERATOR.invoke(null, null, gcls, storageSuperClass, factoryInterface, storageClassName);
947961
}
948962

949963
private static Class<?> loadClass(String name) {
@@ -1090,10 +1104,34 @@ final class Target_com_oracle_truffle_api_staticobject_PodBasedStaticShape<T> {
10901104
static native <T> Target_com_oracle_truffle_api_staticobject_PodBasedStaticShape<T> create(Class<?> generatedStorageClass, T factory, boolean safetyChecks, Object pod);
10911105
}
10921106

1093-
@TargetClass(className = "com.oracle.truffle.api.staticobject.ArrayBasedStaticShape$ArrayBasedFactory", onlyWith = TruffleBaseFeature.IsEnabled.class)
1094-
final class Target_com_oracle_truffle_api_staticobject_ArrayBasedStaticShape_ArrayBasedFactory {
1095-
@Alias @RecomputeFieldValue(kind = Kind.Reset) //
1107+
@TargetClass(className = "com.oracle.truffle.api.staticobject.ArrayBasedStaticShape", onlyWith = TruffleBaseFeature.IsEnabled.class)
1108+
final class Target_com_oracle_truffle_api_staticobject_ArrayBasedStaticShape {
1109+
@Alias @RecomputeFieldValue(kind = Kind.Custom, declClass = MapCleaner.class, isFinal = true) //
10961110
static ConcurrentHashMap<Object, Object> replacements;
1111+
1112+
private static class MapCleaner implements FieldValueTransformerWithAvailability {
1113+
@Override
1114+
public ValueAvailability valueAvailability() {
1115+
return ValueAvailability.AfterCompilation;
1116+
}
1117+
1118+
@Override
1119+
@SuppressWarnings("unchecked")
1120+
public Object transform(Object receiver, Object originalValue) {
1121+
if (originalValue != null) {
1122+
ConcurrentHashMap<Object, Object> originalMap = (ConcurrentHashMap<Object, Object>) originalValue;
1123+
// Copied so that the object replacer can continue replacing references, even after
1124+
// compilation.
1125+
TruffleBaseFeature.StaticObjectSupport.StaticObjectArrayBasedSupport.replacements = new ConcurrentHashMap<>(originalMap);
1126+
// Cleared so that factory instances that hold a reference to it do not leak
1127+
// objects.
1128+
originalMap.clear();
1129+
// Return null so that new factory instances do not register replacements. See
1130+
// `ArrayBasedStaticShape.create()`.
1131+
}
1132+
return null;
1133+
}
1134+
}
10971135
}
10981136

10991137
@TargetClass(className = "com.oracle.truffle.api.staticobject.StaticProperty", onlyWith = TruffleBaseFeature.IsEnabled.class)

substratevm/src/com.oracle.svm.util/src/com/oracle/svm/util/ReflectionUtil.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,4 +162,16 @@ public static <T> T readField(Class<?> declaringClass, String fieldName, Object
162162
public static <T> T readStaticField(Class<?> declaringClass, String fieldName) {
163163
return readField(declaringClass, fieldName, null);
164164
}
165+
166+
public static void writeField(Class<?> declaringClass, String fieldName, Object receiver, Object value) {
167+
try {
168+
lookupField(declaringClass, fieldName).set(receiver, value);
169+
} catch (ReflectiveOperationException ex) {
170+
throw new ReflectionUtilError(ex);
171+
}
172+
}
173+
174+
public static void writeStaticField(Class<?> declaringClass, String fieldName, Object value) {
175+
writeField(declaringClass, fieldName, null, value);
176+
}
165177
}

0 commit comments

Comments
 (0)