3030import java .lang .reflect .Modifier ;
3131import java .util .function .Consumer ;
3232import java .util .function .Function ;
33- import java .util .function .Predicate ;
3433
3534import org .graalvm .collections .EconomicMap ;
3635import org .graalvm .collections .MapCursor ;
@@ -111,50 +110,58 @@ private StubForAbstractClass() {
111110 private DynamicHub stubConstructorClass ;
112111 private DynamicHub serializedLambdaClass ;
113112
114- /**
115- * The ids are either a {@link DynamicHubKey} or {@code DynamicHub.typeID}.
116- */
117- public record SerializationLookupKey (Object declaringClassId , Object targetConstructorClassId ) {
113+ public record HostedSerializationLookupKey ( DynamicHubKey declaringClassId , DynamicHubKey targetConstructorClassId ) {
114+ }
115+
116+ public record SerializationLookupKey (int declaringClassId , int targetConstructorClassId ) {
118117 }
119118
119+ @ Platforms (Platform .HOSTED_ONLY .class ) //
120+ private EconomicMap <HostedSerializationLookupKey , Object > hostedConstructorAccessors ;
120121 @ UnknownObjectField (fullyQualifiedTypes = "org.graalvm.collections.EconomicMapImpl" , availability = AfterCompilation .class ) //
121- private final EconomicMap <SerializationLookupKey , Object > constructorAccessors ;
122+ private EconomicMap <SerializationLookupKey , Object > constructorAccessors ;
122123
123124 /**
124125 * The constructor accessors need to be rescanned manually because the
125126 * {@link SerializationSupport#constructorAccessors} map is only available after compilation.
126127 */
127128 @ Platforms (Platform .HOSTED_ONLY .class ) //
128- private Consumer <Object > scanObject ;
129+ private Consumer <Object > objectRescanner ;
129130
130131 public SerializationSupport () {
131- constructorAccessors = EconomicMap .create ();
132+ hostedConstructorAccessors = EconomicMap .create ();
133+ constructorAccessors = null ;
132134 }
133135
134136 public void setStubConstructor (DynamicHub stubConstructorClass ) {
135- VMError .guarantee (this .stubConstructorClass == null , "Cannot reset stubConstructor" );
137+ VMError .guarantee (this .stubConstructorClass == null , "Cannot set stubConstructor again " );
136138 this .stubConstructorClass = stubConstructorClass ;
137139 }
138140
139141 public void setSerializedLambdaClass (DynamicHub serializedLambdaClass ) {
142+ VMError .guarantee (this .serializedLambdaClass == null , "Cannot set serializedLambdaClass again" );
140143 this .serializedLambdaClass = serializedLambdaClass ;
141144 }
142145
143146 private DynamicHub getSerializedLambdaClass () {
144147 return serializedLambdaClass ;
145148 }
146149
147- public void setScanObject (Consumer <Object > scanObject ) {
148- this .scanObject = scanObject ;
150+ @ Platforms (Platform .HOSTED_ONLY .class )
151+ public void setObjectRescanner (Consumer <Object > objectRescanner ) {
152+ VMError .guarantee (this .serializedLambdaClass == null , "Cannot set objectRescanner again" );
153+ this .objectRescanner = objectRescanner ;
149154 }
150155
151156 @ Platforms (Platform .HOSTED_ONLY .class )
152157 public Object addConstructorAccessor (DynamicHub declaringClass , DynamicHub targetConstructorClass , Object constructorAccessor ) {
153158 VMError .guarantee (constructorAccessor instanceof SubstrateConstructorAccessor , "Not a SubstrateConstructorAccessor: %s" , constructorAccessor );
154- SerializationLookupKey key = BuildPhaseProvider .isHostedUniverseBuilt () ? new SerializationLookupKey (declaringClass .getTypeID (), targetConstructorClass .getTypeID ())
155- : new SerializationLookupKey (new DynamicHubKey (declaringClass ), new DynamicHubKey (targetConstructorClass ));
156- scanObject .accept (constructorAccessor );
157- return constructorAccessors .putIfAbsent (key , constructorAccessor );
159+ VMError .guarantee (!BuildPhaseProvider .isHostedUniverseBuilt ());
160+ HostedSerializationLookupKey key = new HostedSerializationLookupKey (new DynamicHubKey (declaringClass ), new DynamicHubKey (targetConstructorClass ));
161+ objectRescanner .accept (constructorAccessor );
162+ synchronized (hostedConstructorAccessors ) {
163+ return hostedConstructorAccessors .putIfAbsent (key , constructorAccessor );
164+ }
158165 }
159166
160167 @ Platforms (Platform .HOSTED_ONLY .class )
@@ -170,7 +177,7 @@ public SerializationLookupKey getKeyFromConstructorAccessorClass(Class<?> constr
170177
171178 @ Platforms (Platform .HOSTED_ONLY .class )
172179 public boolean isGeneratedSerializationClassLoader (ClassLoader classLoader ) {
173- var constructorAccessorsCursor = constructorAccessors .getEntries ();
180+ var constructorAccessorsCursor = hostedConstructorAccessors .getEntries ();
174181 while (constructorAccessorsCursor .advance ()) {
175182 if (constructorAccessorsCursor .getValue ().getClass ().getClassLoader () == classLoader ) {
176183 return true ;
@@ -181,7 +188,7 @@ public boolean isGeneratedSerializationClassLoader(ClassLoader classLoader) {
181188
182189 @ Platforms (Platform .HOSTED_ONLY .class )
183190 public String getClassLoaderSerializationLookupKey (ClassLoader classLoader ) {
184- var constructorAccessorsCursor = constructorAccessors .getEntries ();
191+ var constructorAccessorsCursor = hostedConstructorAccessors .getEntries ();
185192 while (constructorAccessorsCursor .advance ()) {
186193 if (constructorAccessorsCursor .getValue ().getClass ().getClassLoader () == classLoader ) {
187194 var key = constructorAccessorsCursor .getKey ();
@@ -208,14 +215,17 @@ public int getTypeID() {
208215 }
209216 }
210217
218+ @ Platforms (Platform .HOSTED_ONLY .class ) //
219+ private EconomicMap <DynamicHubKey , RuntimeDynamicAccessMetadata > hostedClasses = EconomicMap .create ();
211220 @ UnknownObjectField (fullyQualifiedTypes = "org.graalvm.collections.EconomicMapImpl" , availability = AfterCompilation .class ) //
212- private final EconomicMap <Object /* DynamicHubKey or DynamicHub.typeID */ , RuntimeDynamicAccessMetadata > classes = EconomicMap . create () ;
221+ private EconomicMap <Integer , RuntimeDynamicAccessMetadata > classes = null ;
213222 private final EconomicMap <String , RuntimeDynamicAccessMetadata > lambdaCapturingClasses = EconomicMap .create ();
214223
215224 @ Platforms (Platform .HOSTED_ONLY .class )
216225 public void registerSerializationTargetClass (AccessCondition cnd , DynamicHub hub , boolean preserved ) {
217- synchronized (classes ) {
218- var previous = classes .putIfAbsent (BuildPhaseProvider .isHostedUniverseBuilt () ? hub .getTypeID () : new DynamicHubKey (hub ), RuntimeDynamicAccessMetadata .createHosted (cnd , preserved ));
226+ VMError .guarantee (!BuildPhaseProvider .isHostedUniverseBuilt ());
227+ synchronized (hostedClasses ) {
228+ var previous = hostedClasses .putIfAbsent (new DynamicHubKey (hub ), RuntimeDynamicAccessMetadata .createHosted (cnd , preserved ));
219229 if (previous != null ) {
220230 previous .addCondition (cnd );
221231 if (!preserved ) {
@@ -226,28 +236,23 @@ public void registerSerializationTargetClass(AccessCondition cnd, DynamicHub hub
226236 }
227237
228238 public void replaceHubKeyWithTypeID () {
229- replaceHubKeyWithTypeID (classes , key -> key instanceof DynamicHubKey , SerializationSupport ::getTypeID );
230- replaceHubKeyWithTypeID (constructorAccessors , SerializationSupport ::shouldReplaceSerializationLookupKey , SerializationSupport ::replaceSerializationLookupKey );
239+ classes = EconomicMap .create ();
240+ replaceHubKeyWithTypeID (hostedClasses , classes , SerializationSupport ::getTypeID );
241+ hostedClasses = null ;
242+ constructorAccessors = EconomicMap .create ();
243+ replaceHubKeyWithTypeID (hostedConstructorAccessors , constructorAccessors , SerializationSupport ::replaceSerializationLookupKey );
244+ hostedConstructorAccessors = null ;
231245 }
232246
233- private static <T , U > void replaceHubKeyWithTypeID (EconomicMap <T , U > map , Predicate <T > condition , Function <T , T > converter ) {
234- EconomicMap <T , U > newEntries = EconomicMap .create ();
235- var cursor = map .getEntries ();
247+ private static <T , U , V > void replaceHubKeyWithTypeID (EconomicMap <T , U > hostedMap , EconomicMap <V , U > map , Function <T , V > converter ) {
248+ var cursor = hostedMap .getEntries ();
236249 while (cursor .advance ()) {
237250 T key = cursor .getKey ();
238- if (condition .test (key )) {
239- newEntries .put (converter .apply (key ), cursor .getValue ());
240- cursor .remove ();
241- }
251+ map .put (converter .apply (key ), cursor .getValue ());
242252 }
243- map .putAll (newEntries );
244253 }
245254
246- private static boolean shouldReplaceSerializationLookupKey (SerializationLookupKey key ) {
247- return key .declaringClassId () instanceof DynamicHubKey && key .targetConstructorClassId () instanceof DynamicHubKey ;
248- }
249-
250- private static SerializationLookupKey replaceSerializationLookupKey (SerializationLookupKey key ) {
255+ private static SerializationLookupKey replaceSerializationLookupKey (HostedSerializationLookupKey key ) {
251256 return new SerializationLookupKey (getTypeID (key .declaringClassId ()), getTypeID (key .targetConstructorClassId ()));
252257 }
253258
@@ -333,11 +338,13 @@ public static boolean isRegisteredForSerialization(DynamicHub hub) {
333338 }
334339
335340 public boolean isRegisteredForSerialization0 (DynamicHub dynamicHub ) {
341+ SubstrateUtil .guaranteeRuntimeOnly ();
336342 var conditionSet = classes .get (dynamicHub .getTypeID ());
337343 return conditionSet != null && conditionSet .satisfied ();
338344 }
339345
340346 public static boolean isPreservedForSerialization (DynamicHub dynamicHub ) {
347+ SubstrateUtil .guaranteeRuntimeOnly ();
341348 for (SerializationSupport singleton : SerializationSupport .layeredSingletons ()) {
342349 var conditionSet = singleton .classes .get (dynamicHub .getTypeID ());
343350 if (conditionSet != null ) {
0 commit comments