3535import java .util .Collection ;
3636import java .util .EnumSet ;
3737import java .util .List ;
38+ import java .util .Map ;
3839import java .util .Optional ;
3940
4041import org .graalvm .collections .EconomicMap ;
4344import jdk .graal .compiler .debug .GraalError ;
4445import jdk .graal .compiler .hotspot .Platform ;
4546import jdk .graal .compiler .hotspot .replaycomp .proxy .CompilationProxy ;
46- import jdk .graal .compiler .hotspot . stubs . IllegalArgumentExceptionArgumentIsNotAnArrayStub ;
47+ import jdk .graal .compiler .util . EconomicHashMap ;
4748import jdk .graal .compiler .util .json .JsonBuilder ;
4849import jdk .graal .compiler .util .json .JsonParser ;
4950import jdk .graal .compiler .util .json .JsonWriter ;
5758import jdk .vm .ci .common .JVMCIError ;
5859import jdk .vm .ci .hotspot .HotSpotCompilationRequest ;
5960import jdk .vm .ci .hotspot .HotSpotCompressedNullConstant ;
61+ import jdk .vm .ci .hotspot .HotSpotResolvedJavaField ;
6062import jdk .vm .ci .hotspot .HotSpotResolvedJavaMethod ;
63+ import jdk .vm .ci .hotspot .HotSpotResolvedObjectType ;
6164import jdk .vm .ci .hotspot .HotSpotSpeculationLog ;
6265import jdk .vm .ci .hotspot .VMField ;
6366import jdk .vm .ci .hotspot .aarch64 .AArch64HotSpotRegisterConfig ;
6467import jdk .vm .ci .hotspot .amd64 .AMD64HotSpotRegisterConfig ;
6568import jdk .vm .ci .hotspot .riscv64 .RISCV64HotSpotRegisterConfig ;
69+ import jdk .vm .ci .meta .AllocatableValue ;
6670import jdk .vm .ci .meta .Assumptions ;
71+ import jdk .vm .ci .meta .DeoptimizationReason ;
6772import jdk .vm .ci .meta .EncodedSpeculationReason ;
6873import jdk .vm .ci .meta .ExceptionHandler ;
6974import jdk .vm .ci .meta .JavaConstant ;
7075import jdk .vm .ci .meta .JavaKind ;
7176import jdk .vm .ci .meta .JavaType ;
7277import jdk .vm .ci .meta .JavaTypeProfile ;
78+ import jdk .vm .ci .meta .MethodHandleAccessProvider ;
7379import jdk .vm .ci .meta .PrimitiveConstant ;
7480import jdk .vm .ci .meta .ResolvedJavaMethod ;
7581import jdk .vm .ci .meta .ResolvedJavaType ;
@@ -187,8 +193,41 @@ private DeserializationException(ObjectSerializer serializer, EconomicMap<String
187193 }
188194
189195 private static final class ClassSerializer implements ObjectSerializer {
190- private static final Class <?>[] knownClasses = new Class <?>[]{String .class , System .class , Object [].class ,
191- ExceptionHandler .class , IllegalArgumentExceptionArgumentIsNotAnArrayStub .class };
196+ /**
197+ * Class constants mapped by name used during deserialization. Classes not present in this
198+ * map are deserialized as {@link ClassSurrogate}.
199+ */
200+ private static final Map <String , Class <?>> knownClasses = createKnownClasses ();
201+
202+ private static Map <String , Class <?>> createKnownClasses () {
203+ Class <?>[] classes = {
204+ // Needed to deserialize enum constants
205+ AMD64 .CPUFeature .class , AArch64 .CPUFeature .class , RISCV64 .CPUFeature .class ,
206+ DeoptimizationReason .class , JavaKind .class , MethodHandleAccessProvider .IntrinsicMethod .class ,
207+ // Needed to deserialize array component types
208+ HotSpotResolvedJavaMethod .class , HotSpotResolvedJavaField .class , HotSpotResolvedObjectType .class ,
209+ Object .class , ExceptionHandler .class , TriState .class , AllocatableValue .class , Value .class ,
210+ // Needed to deserialize Field objects
211+ String .class ,
212+ };
213+ Map <String , Class <?>> map = new EconomicHashMap <>();
214+ for (Class <?> clazz : classes ) {
215+ map .put (clazz .getName (), clazz );
216+ }
217+ return map ;
218+ }
219+
220+ /**
221+ * Casts a deserialized object to a {@link Class}, providing an actionable error message if
222+ * the class was deserialized as a {@link ClassSurrogate}.
223+ */
224+ @ SuppressWarnings ("unchecked" )
225+ public static <C > Class <C > classCast (Object clazz ) {
226+ if (clazz instanceof ClassSurrogate (String name )) {
227+ throw new GraalError (String .format ("Failed to find a Class object for %s. This can be fixed by adding %s.class to ClassSerializer#knownClasses." , name , name ));
228+ }
229+ return (Class <C >) clazz ;
230+ }
192231
193232 @ Override
194233 public Class <?> clazz () {
@@ -206,22 +245,17 @@ public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder,
206245 }
207246
208247 @ Override
209- public Class <?> deserialize (EconomicMap <String , Object > json , RecursiveDeserializer deserializer , ProxyFactory proxyFactory ) throws DeserializationException {
248+ public Object deserialize (EconomicMap <String , Object > json , RecursiveDeserializer deserializer , ProxyFactory proxyFactory ) {
210249 String name = (String ) json .get ("name" );
211250 Class <?> primitiveClass = Class .forPrimitiveName (name );
212251 if (primitiveClass != null ) {
213252 return primitiveClass ;
214253 }
215- for (Class <?> knownClass : knownClasses ) {
216- if (knownClass .getName ().equals (name )) {
217- return knownClass ;
218- }
219- }
220- try {
221- return Class .forName (name );
222- } catch (ClassNotFoundException e ) {
223- throw new DeserializationException (this , json , e );
254+ Class <?> knownClass = knownClasses .get (name );
255+ if (knownClass != null ) {
256+ return knownClass ;
224257 }
258+ return new ClassSurrogate (name );
225259 }
226260 }
227261
@@ -404,7 +438,7 @@ public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder,
404438 }
405439
406440 @ Override
407- public Object deserialize (EconomicMap <String , Object > json , RecursiveDeserializer deserializer , ProxyFactory proxyFactory ) throws DeserializationException {
441+ public Object deserialize (EconomicMap <String , Object > json , RecursiveDeserializer deserializer , ProxyFactory proxyFactory ) {
408442 String loader = (String ) json .get ("loader" );
409443 String module = (String ) json .get ("module" );
410444 String moduleVer = (String ) json .get ("moduleVer" );
@@ -434,7 +468,7 @@ public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder,
434468 }
435469
436470 @ Override
437- public Object deserialize (EconomicMap <String , Object > json , RecursiveDeserializer deserializer , ProxyFactory proxyFactory ) throws DeserializationException {
471+ public Object deserialize (EconomicMap <String , Object > json , RecursiveDeserializer deserializer , ProxyFactory proxyFactory ) {
438472 return json .get ("content" );
439473 }
440474 }
@@ -457,7 +491,7 @@ public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder,
457491 }
458492
459493 @ Override
460- public Object deserialize (EconomicMap <String , Object > json , RecursiveDeserializer deserializer , ProxyFactory proxyFactory ) throws DeserializationException {
494+ public Object deserialize (EconomicMap <String , Object > json , RecursiveDeserializer deserializer , ProxyFactory proxyFactory ) {
461495 return json .get ("value" );
462496 }
463497 }
@@ -513,7 +547,7 @@ public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder,
513547 }
514548
515549 @ Override
516- public Object deserialize (EconomicMap <String , Object > json , RecursiveDeserializer deserializer , ProxyFactory proxyFactory ) throws DeserializationException {
550+ public Object deserialize (EconomicMap <String , Object > json , RecursiveDeserializer deserializer , ProxyFactory proxyFactory ) {
517551 String className = (String ) json .get ("class" );
518552 String value = (String ) json .get ("value" );
519553 switch (className ) {
@@ -609,22 +643,15 @@ public String tag() {
609643 @ Override
610644 public void serialize (Object instance , JsonBuilder .ObjectBuilder objectBuilder , RecursiveSerializer serializer ) throws IOException {
611645 Enum <?> en = (Enum <?>) instance ;
612- objectBuilder . append ( "holder" , en .getClass (). getName ( ));
646+ serializer . serialize ( en .getClass (), objectBuilder . append ( "holder" ));
613647 objectBuilder .append ("constant" , en .name ());
614648 }
615649
616650 @ SuppressWarnings ("unchecked" )
617651 @ Override
618652 public Object deserialize (EconomicMap <String , Object > json , RecursiveDeserializer deserializer , ProxyFactory proxyFactory ) throws DeserializationException {
619- String holderName = (String ) json .get ("holder" );
653+ Class <? extends Enum <?>> enumClass = (Class <? extends Enum <?>>) deserializer . deserialize ( json .get ("holder" ), proxyFactory );
620654 String constantName = (String ) json .get ("constant" );
621- Class <? extends Enum <?>> enumClass ;
622- try {
623- enumClass = (Class <? extends Enum <?>>) Class .forName (holderName );
624- } catch (ClassNotFoundException e ) {
625- throw new DeserializationException (this , json , e );
626- }
627- // TODO This could be more efficient.
628655 for (Enum <?> constant : enumClass .getEnumConstants ()) {
629656 if (constant .name ().equals (constantName )) {
630657 return constant ;
@@ -676,7 +703,7 @@ public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder,
676703 @ SuppressWarnings ("unchecked" )
677704 @ Override
678705 public Object deserialize (EconomicMap <String , Object > json , RecursiveDeserializer deserializer , ProxyFactory proxyFactory ) throws DeserializationException {
679- Class <?> component = ( Class <?>) deserializer .deserialize (json .get ("component" ), proxyFactory );
706+ Class <?> component = ClassSerializer . classCast ( deserializer .deserialize (json .get ("component" ), proxyFactory ) );
680707 List <Object > elements = (List <Object >) json .get ("elements" );
681708 Object [] array = (Object []) Array .newInstance (component , elements .size ());
682709 for (int i = 0 ; i < elements .size (); i ++) {
@@ -813,7 +840,7 @@ public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder,
813840 }
814841
815842 @ Override
816- public Object deserialize (EconomicMap <String , Object > json , RecursiveDeserializer deserializer , ProxyFactory proxyFactory ) throws DeserializationException {
843+ public Object deserialize (EconomicMap <String , Object > json , RecursiveDeserializer deserializer , ProxyFactory proxyFactory ) {
817844 return singleton ;
818845 }
819846 }
@@ -868,7 +895,7 @@ public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder,
868895
869896 @ Override
870897 public Object deserialize (EconomicMap <String , Object > json , RecursiveDeserializer deserializer , ProxyFactory proxyFactory ) throws DeserializationException {
871- Class <?> holder = ( Class <?>) deserializer .deserialize (json .get ("holder" ), proxyFactory );
898+ Class <?> holder = ClassSerializer . classCast ( deserializer .deserialize (json .get ("holder" ), proxyFactory ) );
872899 String name = (String ) json .get ("name" );
873900 try {
874901 if (holder == String .class ) {
@@ -1077,7 +1104,7 @@ public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder,
10771104 }
10781105
10791106 @ Override
1080- public Object deserialize (EconomicMap <String , Object > json , RecursiveDeserializer deserializer , ProxyFactory proxyFactory ) throws DeserializationException {
1107+ public Object deserialize (EconomicMap <String , Object > json , RecursiveDeserializer deserializer , ProxyFactory proxyFactory ) {
10811108 String name = (String ) json .get ("name" );
10821109 return UnresolvedJavaType .create (name );
10831110 }
@@ -1190,11 +1217,11 @@ public String tag() {
11901217 }
11911218
11921219 @ Override
1193- public void serialize (Object instance , JsonBuilder .ObjectBuilder objectBuilder , RecursiveSerializer serializer ) throws IOException {
1220+ public void serialize (Object instance , JsonBuilder .ObjectBuilder objectBuilder , RecursiveSerializer serializer ) {
11941221 }
11951222
11961223 @ Override
1197- public Object deserialize (EconomicMap <String , Object > json , RecursiveDeserializer deserializer , ProxyFactory proxyFactory ) throws DeserializationException {
1224+ public Object deserialize (EconomicMap <String , Object > json , RecursiveDeserializer deserializer , ProxyFactory proxyFactory ) {
11981225 return new ForeignCallDescriptorSurrogate ();
11991226 }
12001227 }
@@ -1621,7 +1648,7 @@ public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder,
16211648 @ Override
16221649 @ SuppressWarnings ("unchecked" )
16231650 public Object deserialize (EconomicMap <String , Object > json , RecursiveDeserializer deserializer , ProxyFactory proxyFactory ) throws DeserializationException {
1624- Class <UnknownEnum > elementType = ( Class < UnknownEnum >) deserializer .deserialize (json .get ("enum" ), proxyFactory );
1651+ Class <UnknownEnum > elementType = ClassSerializer . classCast ( deserializer .deserialize (json .get ("enum" ), proxyFactory ) );
16251652 return asEnumSet (elementType , (List <Object >) json .get ("ordinals" ));
16261653 }
16271654
@@ -1790,19 +1817,19 @@ public String tag() {
17901817 @ Override
17911818 public void serialize (Object instance , JsonBuilder .ObjectBuilder objectBuilder , RecursiveSerializer serializer ) throws IOException {
17921819 Throwable throwable = (Throwable ) instance ;
1793- serializer . serialize ( throwable .getClass (), objectBuilder . append ( "class" ));
1820+ objectBuilder . append ( "class" , throwable .getClass (). getName ( ));
17941821 objectBuilder .append ("message" , throwable .getMessage ());
17951822 }
17961823
17971824 @ Override
1798- public Object deserialize (EconomicMap <String , Object > json , RecursiveDeserializer deserializer , ProxyFactory proxyFactory ) throws DeserializationException {
1799- Class <?> clazz = (Class <?>) deserializer . deserialize ( json .get ("class" ), proxyFactory );
1825+ public Object deserialize (EconomicMap <String , Object > json , RecursiveDeserializer deserializer , ProxyFactory proxyFactory ) {
1826+ String clazz = (String ) json .get ("class" );
18001827 String message = (String ) json .get ("message" );
1801- if (clazz == JVMCIError .class ) {
1828+ if (clazz . equals ( JVMCIError .class . getName ()) ) {
18021829 return new JVMCIError (message );
1803- } else if (clazz == GraalError .class ) {
1830+ } else if (clazz . equals ( GraalError .class . getName ()) ) {
18041831 return new GraalError (message );
1805- } else if (clazz == IllegalArgumentException .class ) {
1832+ } else if (clazz . equals ( IllegalArgumentException .class . getName ()) ) {
18061833 return new IllegalArgumentException (message );
18071834 } else {
18081835 return new Throwable (message );
0 commit comments