2424 */
2525package com .oracle .svm .hosted ;
2626
27- import java .util .ArrayList ;
2827import java .util .Arrays ;
2928import java .util .Collection ;
3029import java .util .EnumSet ;
31- import java .util .HashMap ;
3230import java .util .HashSet ;
33- import java .util .List ;
34- import java .util .Map ;
35- import java .util .Objects ;
3631import java .util .Set ;
3732
3833import org .graalvm .nativeimage .ImageSingletons ;
5045import com .oracle .svm .core .layeredimagesingleton .ImageSingletonWriter ;
5146import com .oracle .svm .core .layeredimagesingleton .LayeredImageSingleton ;
5247import com .oracle .svm .core .layeredimagesingleton .LayeredImageSingletonBuilderFlags ;
48+ import com .oracle .svm .hosted .imagelayer .HostedImageLayerBuildingSupport ;
49+ import com .oracle .svm .hosted .imagelayer .SVMImageLayerLoader ;
5350import com .oracle .svm .hosted .meta .HostedType ;
5451
5552import jdk .graal .compiler .debug .Assertions ;
@@ -65,7 +62,7 @@ public boolean isInConfiguration(Feature.IsInConfigurationAccess access) {
6562 @ Override
6663 public void beforeUniverseBuilding (BeforeUniverseBuildingAccess access ) {
6764 if (ImageLayerBuildingSupport .buildingInitialLayer ()) {
68- ImageSingletons .add (LayerTypeCheckInfo .class , new LayerTypeCheckInfo ());
65+ ImageSingletons .add (LayerTypeCheckInfo .class , new LayerTypeCheckInfo (0 ));
6966 }
7067 }
7168
@@ -112,136 +109,86 @@ public static int loadTypeInfo(Collection<HostedType> types) {
112109 }
113110 }
114111
115- public static void persistTypeInfo (Collection <HostedType > types ) {
116- if (ImageLayerBuildingSupport .buildingImageLayer ()) {
117- ImageSingletons .lookup (LayerTypeCheckInfo .class ).persistTypeInfo (types );
118- }
119- }
120-
121- record TypeCheckInfo (int typeID , int numClassTypes , int numInterfaceTypes , int [] typecheckSlots ) {
122- private List <Integer > toIntList () {
123- ArrayList <Integer > list = new ArrayList <>();
124- list .add (typeID );
125- list .add (numClassTypes );
126- list .add (numInterfaceTypes );
127- Arrays .stream (typecheckSlots ).forEach (list ::add );
128-
129- return list ;
130- }
112+ @ SuppressWarnings ("unused" )
113+ public static boolean validateTypeInfo (Collection <HostedType > types ) {
114+ if (ImageLayerBuildingSupport .buildingExtensionLayer ()) {
115+ var loader = HostedImageLayerBuildingSupport .singleton ().getLoader ();
116+ for (HostedType type : types ) {
117+ if (type .getWrapped ().isInBaseLayer ()) {
118+ var priorInfo = getTypecheckInfo (loader , type );
119+ if (!priorInfo .installed ()) {
120+ // no need to validate this hub, as it was not installed
121+ continue ;
122+ }
123+ int typeID = type .getTypeID ();
124+ int numClassTypes = type .getNumClassTypes ();
125+ int numInterfaceTypes = type .getNumInterfaceTypes ();
126+ int [] typecheckSlots = type .getOpenTypeWorldTypeCheckSlots ();
127+ boolean matches = typeID == priorInfo .typeID && numClassTypes == priorInfo .numClassTypes && numInterfaceTypes == priorInfo .numInterfaceTypes &&
128+ Arrays .equals (typecheckSlots , priorInfo .typecheckSlots );
129+ if (!matches ) {
130+ var typeInfo = new TypeCheckInfo (true , typeID , numClassTypes , numInterfaceTypes , typecheckSlots );
131+ assert false : Assertions .errorMessage ("Mismatch for " , type , priorInfo , typeInfo , Arrays .toString (priorInfo .typecheckSlots ),
132+ Arrays .toString (typeInfo .typecheckSlots ));
131133
132- private static TypeCheckInfo fromIntList (List <Integer > list ) {
133- int typeID = list .get (0 );
134- int numClassTypes = list .get (1 );
135- int numInterfaceTypes = list .get (2 );
136- int [] typecheckSlots = list .subList (3 , list .size ()).stream ().mapToInt (i -> i ).toArray ();
137- return new TypeCheckInfo (typeID , numClassTypes , numInterfaceTypes , typecheckSlots );
134+ }
135+ }
136+ }
138137 }
138+ return true ;
139+ }
139140
140- @ Override
141- public boolean equals ( Object o ) {
142- if ( this == o ) {
143- return true ;
144- }
145- if ( o == null || getClass () != o . getClass () ) {
146- return false ;
141+ static TypeCheckInfo getTypecheckInfo ( SVMImageLayerLoader loader , HostedType hType ) {
142+ if ( hType . getWrapped (). isInBaseLayer () ) {
143+ var hubInfo = loader . getDynamicHubInfo ( hType . getWrapped ());
144+ var valuesReader = hubInfo . getTypecheckSlotValues () ;
145+ int [] typecheckSlots = new int [ valuesReader . size ()];
146+ for ( int i = 0 ; i < typecheckSlots . length ; i ++ ) {
147+ typecheckSlots [ i ] = valuesReader . get ( i ) ;
147148 }
148- TypeCheckInfo typeCheckInfo = ( TypeCheckInfo ) o ;
149- return typeID == typeCheckInfo . typeID && numClassTypes == typeCheckInfo . numClassTypes && numInterfaceTypes == typeCheckInfo . numInterfaceTypes &&
150- Arrays . equals ( typecheckSlots , typeCheckInfo . typecheckSlots ) ;
149+ return new TypeCheckInfo ( hubInfo . getInstalled (), hubInfo . getTypecheckId (), hubInfo . getNumClassTypes (), hubInfo . getNumInterfaceTypes (), typecheckSlots ) ;
150+ } else {
151+ return null ;
151152 }
153+ }
152154
153- @ Override
154- public int hashCode () {
155- int result = Objects .hash (typeID , numClassTypes , numInterfaceTypes );
156- result = 31 * result + Arrays .hashCode (typecheckSlots );
157- return result ;
158- }
155+ record TypeCheckInfo (boolean installed , int typeID , int numClassTypes , int numInterfaceTypes , int [] typecheckSlots ) {
159156 }
160157
161158 private static final class LayerTypeCheckInfo implements LayeredImageSingleton {
162- Map <Integer , TypeCheckInfo > identifierToTypeInfo = new HashMap <>();
163- int maxTypeID = 0 ;
159+ final int maxTypeID ;
160+
161+ LayerTypeCheckInfo (int maxTypeID ) {
162+ this .maxTypeID = maxTypeID ;
163+ }
164164
165165 public int loadTypeID (Collection <HostedType > types ) {
166- ArrayList < Integer > usedIDs = new ArrayList <> ();
166+ var loader = HostedImageLayerBuildingSupport . singleton (). getLoader ();
167167 for (HostedType type : types ) {
168- int identifierID = type .getWrapped ().getId ();
169- TypeCheckInfo info = identifierToTypeInfo .get (identifierID );
168+ TypeCheckInfo info = getTypecheckInfo (loader , type );
170169 if (info != null ) {
171- usedIDs .add (info .typeID );
172170 type .loadTypeID (info .typeID );
173171 }
174172 }
175173
176174 return maxTypeID ;
177175 }
178176
179- public void persistTypeInfo (Collection <HostedType > types ) {
180- for (HostedType type : types ) {
181- /*
182- * Currently we are calculating type id information for all types. However, for
183- * types not tracked across layers, the type ID may not be the same in different
184- * layers.
185- */
186- assert type .getTypeID () != -1 : type ;
187- if (type .getWrapped ().isTrackedAcrossLayers ()) {
188- int identifierID = type .getWrapped ().getId ();
189- int typeID = type .getTypeID ();
190- int numClassTypes = type .getNumClassTypes ();
191- int numInterfaceTypes = type .getNumInterfaceTypes ();
192- int [] typecheckSlots = type .getOpenTypeWorldTypeCheckSlots ();
193- var priorInfo = identifierToTypeInfo .get (identifierID );
194- var newTypeInfo = new TypeCheckInfo (typeID , numClassTypes , numInterfaceTypes , typecheckSlots );
195- if (priorInfo == null ) {
196- identifierToTypeInfo .put (identifierID , newTypeInfo );
197- } else {
198- assert newTypeInfo .equals (priorInfo ) : Assertions .errorMessage ("Mismatch for " , type , priorInfo , newTypeInfo , Arrays .toString (priorInfo .typecheckSlots ),
199- Arrays .toString (newTypeInfo .typecheckSlots ));
200- }
201- }
202- }
203- }
204-
205177 @ Override
206178 public EnumSet <LayeredImageSingletonBuilderFlags > getImageBuilderFlags () {
207179 return LayeredImageSingletonBuilderFlags .BUILDTIME_ACCESS_ONLY ;
208180 }
209181
210- private static String getTypeInfoKey (int id ) {
211- return String .format ("TypeInfo-%s" , id );
212- }
213-
214182 @ Override
215183 public PersistFlags preparePersist (ImageSingletonWriter writer ) {
216- /*
217- * Note all that is strictly needed to restore the typecheck information is the
218- * (identifierID -> typeID) mappings. In the future we can compact the amount of
219- * information we store.
220- */
221- var typeIdentifierIds = identifierToTypeInfo .keySet ().stream ().sorted ().toList ();
222- writer .writeIntList ("typeIdentifierIds" , typeIdentifierIds );
223184 writer .writeInt ("maxTypeID" , DynamicHubSupport .currentLayer ().getMaxTypeId ());
224185
225- for (int identifierID : typeIdentifierIds ) {
226- var typeInfo = identifierToTypeInfo .get (identifierID );
227- assert typeInfo != null ;
228- writer .writeIntList (getTypeInfoKey (identifierID ), typeInfo .toIntList ());
229- }
230-
231186 return PersistFlags .CREATE ;
232187 }
233188
234189 @ SuppressWarnings ("unused" )
235190 public static Object createFromLoader (ImageSingletonLoader loader ) {
236- var info = new LayerTypeCheckInfo ();
237- info .maxTypeID = loader .readInt ("maxTypeID" );
238- List <Integer > typeIdentifierIds = loader .readIntList ("typeIdentifierIds" );
239- for (var identifierID : typeIdentifierIds ) {
240- Object previous = info .identifierToTypeInfo .put (identifierID , TypeCheckInfo .fromIntList (loader .readIntList (getTypeInfoKey (identifierID ))));
241- assert previous == null : previous ;
242- }
243-
244- return info ;
191+ return new LayerTypeCheckInfo (loader .readInt ("maxTypeID" ));
245192 }
246193 }
247194}
0 commit comments