2424 */
2525package com .oracle .svm .core .heap .dump ;
2626
27+ import java .util .EnumSet ;
28+
2729import org .graalvm .nativeimage .ImageSingletons ;
2830import org .graalvm .nativeimage .Platform ;
2931import org .graalvm .nativeimage .Platforms ;
4446import com .oracle .svm .core .heap .ObjectVisitor ;
4547import com .oracle .svm .core .heap .UnknownObjectField ;
4648import com .oracle .svm .core .hub .DynamicHub ;
49+ import com .oracle .svm .core .layeredimagesingleton .InitialLayerOnlyImageSingleton ;
50+ import com .oracle .svm .core .layeredimagesingleton .LayeredImageSingletonBuilderFlags ;
51+ import com .oracle .svm .core .layeredimagesingleton .LayeredImageSingletonSupport ;
52+ import com .oracle .svm .core .layeredimagesingleton .MultiLayeredImageSingleton ;
53+ import com .oracle .svm .core .layeredimagesingleton .UnsavedSingleton ;
4754import com .oracle .svm .core .memory .NullableNativeMemory ;
4855import com .oracle .svm .core .nmt .NmtCategory ;
4956import com .oracle .svm .core .util .coder .ByteStream ;
5057import com .oracle .svm .core .util .coder .ByteStreamAccess ;
5158import com .oracle .svm .core .util .coder .NativeCoder ;
5259import com .oracle .svm .core .util .coder .Pack200Coder ;
5360
54- import jdk .graal .compiler .api .replacements .Fold ;
5561import jdk .graal .compiler .word .Word ;
5662
5763/**
95101 * |----------------------------|
96102 * </pre>
97103 */
98- public class HeapDumpMetadata {
104+ public class HeapDumpMetadata implements InitialLayerOnlyImageSingleton {
99105 private final ComputeHubDataVisitor computeHubDataVisitor ;
100- @ UnknownObjectField (availability = AfterCompilation .class ) private byte [] data ;
101106
102107 private int fieldNameCount ;
103108 private int classInfoCount ;
@@ -110,30 +115,37 @@ public HeapDumpMetadata() {
110115 computeHubDataVisitor = new ComputeHubDataVisitor ();
111116 }
112117
113- @ Fold
114118 public static HeapDumpMetadata singleton () {
115119 return ImageSingletons .lookup (HeapDumpMetadata .class );
116120 }
117121
118- @ Platforms (Platform .HOSTED_ONLY .class )
119- public void setData (byte [] value ) {
120- this .data = value ;
121- }
122-
123122 public boolean initialize () {
124123 assert classInfos .isNull () && fieldInfoTable .isNull () && fieldNameTable .isNull ();
125124
126- Pointer start = NonmovableArrays .getArrayBase (NonmovableArrays .fromImageHeap (data ));
127- Pointer end = start .add (data .length );
125+ HeapDumpEncodedData [] encodedDataArray = HeapDumpEncodedData .layeredSingletons ();
128126
129127 ByteStream stream = StackValue .get (ByteStream .class );
130- ByteStreamAccess .initialize (stream , start );
131128
132- /* Read the header. */
133- int totalFieldCount = NativeCoder .readInt (stream );
134- int classCount = NativeCoder .readInt (stream );
135- fieldNameCount = NativeCoder .readInt (stream );
136- int maxTypeId = Pack200Coder .readUVAsInt (stream );
129+ int totalFieldCount = 0 ;
130+ int totalFieldNameCount = 0 ;
131+ int maxTypeId = Integer .MIN_VALUE ;
132+
133+ /*
134+ * First read all encoded data arrays to determine how large of data structures to allocate.
135+ */
136+ for (HeapDumpEncodedData encodedData : encodedDataArray ) {
137+ byte [] data = encodedData .data ;
138+
139+ Pointer start = NonmovableArrays .getArrayBase (NonmovableArrays .fromImageHeap (data ));
140+ ByteStreamAccess .initialize (stream , start );
141+
142+ /* Read the header. */
143+ totalFieldCount += NativeCoder .readInt (stream );
144+ NativeCoder .readInt (stream ); // class count
145+ totalFieldNameCount += NativeCoder .readInt (stream );
146+ maxTypeId = Integer .max (Pack200Coder .readUVAsInt (stream ), maxTypeId );
147+ }
148+ fieldNameCount = totalFieldNameCount ;
137149 classInfoCount = maxTypeId + 1 ;
138150
139151 /*
@@ -159,45 +171,65 @@ public boolean initialize() {
159171 return false ;
160172 }
161173
162- /* Read the classes and fields. */
163- int fieldIndex = 0 ;
164- for (int i = 0 ; i < classCount ; i ++) {
165- int typeId = Pack200Coder .readUVAsInt (stream );
166-
167- ClassInfo classInfo = getClassInfo (typeId );
168-
169- int numInstanceFields = Pack200Coder .readUVAsInt (stream );
170- classInfo .setInstanceFieldCount (numInstanceFields );
171-
172- int numStaticFields = Pack200Coder .readUVAsInt (stream );
173- classInfo .setStaticFieldCount (numStaticFields );
174-
175- classInfo .setInstanceFields (fieldInfoTable .addressOf (fieldIndex ));
176- for (int j = 0 ; j < numInstanceFields ; j ++) {
177- Pointer fieldInfo = (Pointer ) fieldInfoTable .addressOf (fieldIndex );
178- fieldInfo .writeWord (0 , stream .getPosition ());
179- FieldInfoAccess .skipFieldInfo (stream );
180- fieldIndex ++;
174+ /*
175+ * Next write the metadata from all data arrays into the data structures.
176+ */
177+ int fieldNameTableStartIdx = 0 ;
178+ for (HeapDumpEncodedData encodedData : encodedDataArray ) {
179+ byte [] data = encodedData .data ;
180+
181+ /* Re-initialize the stream. */
182+ Pointer start = NonmovableArrays .getArrayBase (NonmovableArrays .fromImageHeap (data ));
183+ ByteStreamAccess .initialize (stream , start );
184+
185+ /* Re-read the header. */
186+ NativeCoder .readInt (stream ); // field count
187+ int classCount = NativeCoder .readInt (stream );
188+ int currentFieldNameCount = NativeCoder .readInt (stream );
189+ Pack200Coder .readUVAsInt (stream ); // maxTypeId
190+
191+ /* Read the classes and fields. */
192+ int fieldIndex = 0 ;
193+ for (int i = 0 ; i < classCount ; i ++) {
194+ int typeId = Pack200Coder .readUVAsInt (stream );
195+
196+ ClassInfo classInfo = getClassInfo (typeId );
197+
198+ int numInstanceFields = Pack200Coder .readUVAsInt (stream );
199+ classInfo .setInstanceFieldCount (numInstanceFields );
200+
201+ int numStaticFields = Pack200Coder .readUVAsInt (stream );
202+ classInfo .setStaticFieldCount (numStaticFields );
203+
204+ classInfo .setInstanceFields (fieldInfoTable .addressOf (fieldIndex ));
205+ for (int j = 0 ; j < numInstanceFields ; j ++) {
206+ Pointer fieldInfo = (Pointer ) fieldInfoTable .addressOf (fieldIndex );
207+ fieldInfo .writeWord (0 , stream .getPosition ());
208+ FieldInfoAccess .skipFieldInfo (stream );
209+ fieldIndex ++;
210+ }
211+
212+ classInfo .setStaticFields (fieldInfoTable .addressOf (fieldIndex ));
213+ for (int j = 0 ; j < numStaticFields ; j ++) {
214+ Pointer fieldInfo = (Pointer ) fieldInfoTable .addressOf (fieldIndex );
215+ fieldInfo .writeWord (0 , stream .getPosition ());
216+ FieldInfoAccess .skipFieldInfo (stream );
217+ fieldIndex ++;
218+ }
181219 }
182220
183- classInfo . setStaticFields ( fieldInfoTable . addressOf ( fieldIndex ));
184- for (int j = 0 ; j < numStaticFields ; j ++) {
185- Pointer fieldInfo = (Pointer ) fieldInfoTable .addressOf (fieldIndex );
186- fieldInfo .writeWord (0 , stream .getPosition ());
187- FieldInfoAccess . skipFieldInfo (stream );
188- fieldIndex ++ ;
221+ /* Fill the symbol table. */
222+ for (int i = fieldNameTableStartIdx ; i < currentFieldNameCount + fieldNameTableStartIdx ; i ++) {
223+ Pointer fieldName = (Pointer ) fieldNameTable .addressOf (i );
224+ fieldName .writeWord (0 , stream .getPosition ());
225+ int length = Pack200Coder . readUVAsInt (stream );
226+ stream . setPosition ( stream . getPosition (). add ( length )) ;
189227 }
228+ fieldNameTableStartIdx += currentFieldNameCount ;
229+ Pointer end = start .add (data .length );
230+ assert stream .getPosition ().equal (end );
190231 }
191232
192- /* Fill the symbol table. */
193- for (int i = 0 ; i < fieldNameCount ; i ++) {
194- Pointer fieldName = (Pointer ) fieldNameTable .addressOf (i );
195- fieldName .writeWord (0 , stream .getPosition ());
196- int length = Pack200Coder .readUVAsInt (stream );
197- stream .setPosition (stream .getPosition ().add (length ));
198- }
199- assert stream .getPosition ().equal (end );
200-
201233 /* Store the DynamicHubs in their corresponding ClassInfo structs. */
202234 computeHubDataVisitor .initialize ();
203235 Heap .getHeap ().walkImageHeapObjects (computeHubDataVisitor );
@@ -290,6 +322,16 @@ static int computeFieldsDumpSize(FieldInfoPointer fields, int fieldCount) {
290322 return result ;
291323 }
292324
325+ @ Override
326+ public boolean accessibleInFutureLayers () {
327+ return true ;
328+ }
329+
330+ @ Override
331+ public EnumSet <LayeredImageSingletonBuilderFlags > getImageBuilderFlags () {
332+ return LayeredImageSingletonBuilderFlags .RUNTIME_ACCESS_ONLY ;
333+ }
334+
293335 @ RawStructure
294336 public interface ClassInfo extends PointerBase {
295337 @ RawField
@@ -444,4 +486,26 @@ public void visitObject(Object o) {
444486 }
445487 }
446488 }
489+
490+ public static class HeapDumpEncodedData implements MultiLayeredImageSingleton , UnsavedSingleton {
491+ @ UnknownObjectField (availability = AfterCompilation .class ) private byte [] data ;
492+
493+ @ Override
494+ public EnumSet <LayeredImageSingletonBuilderFlags > getImageBuilderFlags () {
495+ return LayeredImageSingletonBuilderFlags .ALL_ACCESS ;
496+ }
497+
498+ private static HeapDumpEncodedData currentLayer () {
499+ return LayeredImageSingletonSupport .singleton ().lookup (HeapDumpEncodedData .class , false , true );
500+ }
501+
502+ private static HeapDumpEncodedData [] layeredSingletons () {
503+ return MultiLayeredImageSingleton .getAllLayers (HeapDumpEncodedData .class );
504+ }
505+
506+ @ Platforms (Platform .HOSTED_ONLY .class )
507+ public static void setData (byte [] value ) {
508+ HeapDumpEncodedData .currentLayer ().data = value ;
509+ }
510+ }
447511}
0 commit comments