3939import org .graalvm .compiler .debug .GraalError ;
4040
4141import java .lang .reflect .Modifier ;
42+ import java .util .ArrayList ;
4243import java .util .Collections ;
4344import java .util .Deque ;
4445import java .util .HashMap ;
@@ -152,42 +153,56 @@ CVTypeRecord buildFunction(PrimaryEntry entry) {
152153 return buildMemberFunction (entry .getClassEntry (), entry .getPrimary ().getMethodEntry ());
153154 }
154155
155- static class FieldListContext {
156- /* Knock 100 bytes off to be safe from off-by-1, padding, LF_INDEX, etc. */
157- static final int FIELD_LIST_MAX_SIZE = CV_TYPE_RECORD_MAX_SIZE - 100 ;
156+ static class FieldListBuilder {
157+ final List <CVTypeRecord .FieldRecord > fields = new ArrayList <>();
158158
159- final CVTypeRecord .CVFieldListRecord firstFieldList ;
160- CVTypeRecord .CVFieldListRecord currentFieldList ;
161- final Deque <CVTypeRecord .CVFieldListRecord > lists = new LinkedList <>();
159+ FieldListBuilder () {
160+ }
162161
163- FieldListContext (CVTypeRecord .CVFieldListRecord initialRecord ) {
164- this .firstFieldList = initialRecord ;
165- this .currentFieldList = initialRecord ;
166- lists .add (firstFieldList );
162+ void addField (CVTypeRecord .FieldRecord field ) {
163+ fields .add (field );
167164 }
168165
169- void addRecordToFieldList (CVTypeRecord .FieldRecord field ) {
170- if ((currentFieldList .getEstimatedSize () + field .computeSize ()) > FIELD_LIST_MAX_SIZE ) {
171- /* end this fieldlist with an LF_INDEX to the new field list. */
172- currentFieldList = new CVTypeRecord .CVFieldListRecord ();
173- lists .add (currentFieldList );
174- }
175- currentFieldList .add (field );
166+ int getFieldCount () {
167+ return fields .size ();
176168 }
177169
178- CVTypeRecord .CVFieldListRecord addTypeRecords (CVTypeSectionBuilder builder ) {
179- /* Add all fieldlist records in the reverse order they were created. */
170+ CVTypeRecord .CVFieldListRecord buildFieldListRecords (CVTypeSectionBuilder builder ) {
171+
172+ /*
173+ * The last FieldList must refer back to the one before it, and must contain the first
174+ * fields in the class.
175+ */
176+
177+ CVTypeRecord .CVFieldListRecord currentFieldList = new CVTypeRecord .CVFieldListRecord ();
178+ Deque <CVTypeRecord .CVFieldListRecord > fl = new LinkedList <>();
179+ fl .add (currentFieldList );
180+
181+ /* Build all Field List records in field order (FIFO). */
182+ for (CVTypeRecord .FieldRecord fieldRecord : fields ) {
183+ if (currentFieldList .getEstimatedSize () + CVUtil .align4 (fieldRecord .computeSize ()) >= CV_TYPE_RECORD_MAX_SIZE ) {
184+ currentFieldList = new CVTypeRecord .CVFieldListRecord ();
185+ fl .add (currentFieldList );
186+ }
187+ currentFieldList .add (fieldRecord );
188+ }
189+
190+ /*
191+ * Emit all Field List records in reverse order (LIFO), adding Index records to all but
192+ * the first emitted.
193+ */
194+ CVTypeRecord .CVFieldListRecord fieldListRecord = null ;
180195 int idx = 0 ;
181- while (!lists .isEmpty ()) {
182- CVTypeRecord . CVFieldListRecord fieldList = lists .removeLast ();
183- currentFieldList = builder .addTypeRecord (fieldList );
196+ while (!fl .isEmpty ()) {
197+ fieldListRecord = fl .removeLast ();
198+ fieldListRecord = builder .addTypeRecord (fieldListRecord );
184199 /* For all fieldlist but the first, link to the previous record. */
185200 if (idx != 0 ) {
186- fieldList .add (new CVTypeRecord .CVIndexRecord (idx ));
201+ fieldListRecord .add (new CVTypeRecord .CVIndexRecord (idx ));
187202 }
188- idx = currentFieldList .getSequenceNumber ();
203+ idx = fieldListRecord .getSequenceNumber ();
189204 }
190- return currentFieldList ;
205+ return fieldListRecord ;
191206 }
192207 }
193208
@@ -212,26 +227,22 @@ private CVTypeRecord buildStructureTypeEntry(final StructureTypeEntry typeEntry)
212227
213228 final List <MethodEntry > methods = typeEntry .isClass () ? ((ClassEntry ) typeEntry ).getMethods () : Collections .emptyList ();
214229
215- /* process fields */
216-
217230 /* Build fieldlist record */
218- CVTypeRecord .CVFieldListRecord fieldListRecord = new CVTypeRecord .CVFieldListRecord ();
219- FieldListContext fieldListContext = new FieldListContext (fieldListRecord );
220-
221- log ("building fieldlist %s" , fieldListRecord );
231+ FieldListBuilder fieldListBuilder = new FieldListBuilder ();
232+ log ("building field list" );
222233
223234 if (superTypeIndex != 0 ) {
224235 CVTypeRecord .CVBaseMemberRecord btype = new CVTypeRecord .CVBaseMemberRecord (MPROP_PUBLIC , superTypeIndex , 0 );
225236 log ("basetype %s" , btype );
226- fieldListContext . addRecordToFieldList (btype );
237+ fieldListBuilder . addField (btype );
227238 }
228239
229240 /* Only define manifested fields. */
230241 typeEntry .fields ().filter (CVTypeSectionBuilder ::isManifestedField ).forEach (f -> {
231242 log ("field %s attr=(%s) offset=%d size=%d valuetype=%s" , f .fieldName (), f .getModifiersString (), f .getOffset (), f .getSize (), f .getValueType ().getTypeName ());
232243 CVTypeRecord .FieldRecord fieldRecord = buildField (f );
233244 log ("field %s" , fieldRecord );
234- fieldListContext . addRecordToFieldList (fieldRecord );
245+ fieldListBuilder . addField (fieldRecord );
235246 });
236247
237248 if (typeEntry .isArray ()) {
@@ -250,7 +261,7 @@ private CVTypeRecord buildStructureTypeEntry(final StructureTypeEntry typeEntry)
250261 /* Build a field for the 0 length array. */
251262 CVTypeRecord .CVMemberRecord dm = new CVTypeRecord .CVMemberRecord (MPROP_PUBLIC , array0record .getSequenceNumber (), typeEntry .getSize (), "data" );
252263 log ("field %s" , dm );
253- fieldListContext . addRecordToFieldList (dm );
264+ fieldListBuilder . addField (dm );
254265 }
255266
256267 /*
@@ -292,25 +303,25 @@ private CVTypeRecord buildStructureTypeEntry(final StructureTypeEntry typeEntry)
292303
293304 /* LF_METHOD record */
294305 CVTypeRecord .CVOverloadedMethodRecord methodRecord = new CVTypeRecord .CVOverloadedMethodRecord ((short ) nmlist .count (), nmlist .getSequenceNumber (), mname );
295- fieldListContext . addRecordToFieldList (methodRecord );
306+ fieldListBuilder . addField (methodRecord );
296307 });
297308
298309 methods .stream ().filter (methodEntry -> !overloaded .contains (methodEntry .methodName ())).forEach (m -> {
299310 log ("`unique method %s %s %s(...)" , m .fieldName (), m .methodName (), m .getModifiersString (), m .getValueType ().getTypeName (), m .methodName ());
300311 CVTypeRecord .CVOneMethodRecord method = buildMethod ((ClassEntry ) typeEntry , m );
301312 log (" unique method %s" , method );
302- fieldListContext . addRecordToFieldList (method );
313+ fieldListBuilder . addField (method );
303314 });
304315 }
305316 /* Build fieldlist record from manifested fields. */
306- CVTypeRecord .CVFieldListRecord newfieldListRecord = fieldListContext . addTypeRecords (this );
317+ CVTypeRecord .CVFieldListRecord newfieldListRecord = fieldListBuilder . buildFieldListRecords (this );
307318 int fieldListIdx = newfieldListRecord .getSequenceNumber ();
308- int fieldListCount = newfieldListRecord . count ();
319+ int fieldCount = fieldListBuilder . getFieldCount ();
309320 log ("finished building fieldlist %s" , newfieldListRecord );
310321
311322 /* Build final class record. */
312323 short attrs = 0 ; /* property attribute field (prop_t) */
313- CVTypeRecord typeRecord = new CVTypeRecord .CVClassRecord (LF_CLASS , (short ) fieldListCount , attrs , fieldListIdx , 0 , 0 , typeEntry .getSize (), typeEntry .getTypeName (), null );
324+ CVTypeRecord typeRecord = new CVTypeRecord .CVClassRecord (LF_CLASS , (short ) fieldCount , attrs , fieldListIdx , 0 , 0 , typeEntry .getSize (), typeEntry .getTypeName (), null );
314325 typeRecord = addTypeRecord (typeRecord );
315326
316327 if (typeEntry .isClass ()) {
@@ -330,7 +341,7 @@ private CVTypeRecord buildStructureTypeEntry(final StructureTypeEntry typeEntry)
330341
331342 types .typeNameMap .put (typeEntry .getTypeName (), typeRecord );
332343
333- /* CVSymbolSubsectionBuilder will add an associated S_UDT record to symbol table. */
344+ /* CVSymbolSubsectionBuilder will add associated S_UDT record to symbol table. */
334345 log (" finished class %s" , typeRecord );
335346
336347 return typeRecord ;
0 commit comments