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,52 @@ 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+ /* The last FieldList must refer back to the one before it,
173+ and must contain the first fields in the class. */
174+
175+ CVTypeRecord .CVFieldListRecord currentFieldList = new CVTypeRecord .CVFieldListRecord ();
176+ Deque <CVTypeRecord .CVFieldListRecord > fl = new LinkedList <>();
177+ fl .add (currentFieldList );
178+
179+ /* Build all Field List records in field order (FIFO). */
180+ for (CVTypeRecord .FieldRecord fieldRecord : fields ) {
181+ if (currentFieldList .getEstimatedSize () + CVUtil .align4 (fieldRecord .computeSize ()) >= CV_TYPE_RECORD_MAX_SIZE ) {
182+ currentFieldList = new CVTypeRecord .CVFieldListRecord ();
183+ fl .add (currentFieldList );
184+ }
185+ currentFieldList .add (fieldRecord );
186+ }
187+
188+ /* Emit all Field List records in reverse order (LIFO), adding Index records
189+ to all but the first emitted. */
190+ CVTypeRecord .CVFieldListRecord fieldListRecord = null ;
180191 int idx = 0 ;
181- while (!lists .isEmpty ()) {
182- CVTypeRecord . CVFieldListRecord fieldList = lists .removeLast ();
183- currentFieldList = builder .addTypeRecord (fieldList );
192+ while (!fl .isEmpty ()) {
193+ fieldListRecord = fl .removeLast ();
194+ fieldListRecord = builder .addTypeRecord (fieldListRecord );
184195 /* For all fieldlist but the first, link to the previous record. */
185196 if (idx != 0 ) {
186- fieldList .add (new CVTypeRecord .CVIndexRecord (idx ));
197+ fieldListRecord .add (new CVTypeRecord .CVIndexRecord (idx ));
187198 }
188- idx = currentFieldList .getSequenceNumber ();
199+ idx = fieldListRecord .getSequenceNumber ();
189200 }
190- return currentFieldList ;
201+ return fieldListRecord ;
191202 }
192203 }
193204
@@ -212,26 +223,22 @@ private CVTypeRecord buildStructureTypeEntry(final StructureTypeEntry typeEntry)
212223
213224 final List <MethodEntry > methods = typeEntry .isClass () ? ((ClassEntry ) typeEntry ).getMethods () : Collections .emptyList ();
214225
215- /* process fields */
216-
217226 /* Build fieldlist record */
218- CVTypeRecord .CVFieldListRecord fieldListRecord = new CVTypeRecord .CVFieldListRecord ();
219- FieldListContext fieldListContext = new FieldListContext (fieldListRecord );
220-
221- log ("building fieldlist %s" , fieldListRecord );
227+ FieldListBuilder fieldListBuilder = new FieldListBuilder ();
228+ log ("building field list" );
222229
223230 if (superTypeIndex != 0 ) {
224231 CVTypeRecord .CVBaseMemberRecord btype = new CVTypeRecord .CVBaseMemberRecord (MPROP_PUBLIC , superTypeIndex , 0 );
225232 log ("basetype %s" , btype );
226- fieldListContext . addRecordToFieldList (btype );
233+ fieldListBuilder . addField (btype );
227234 }
228235
229236 /* Only define manifested fields. */
230237 typeEntry .fields ().filter (CVTypeSectionBuilder ::isManifestedField ).forEach (f -> {
231238 log ("field %s attr=(%s) offset=%d size=%d valuetype=%s" , f .fieldName (), f .getModifiersString (), f .getOffset (), f .getSize (), f .getValueType ().getTypeName ());
232239 CVTypeRecord .FieldRecord fieldRecord = buildField (f );
233240 log ("field %s" , fieldRecord );
234- fieldListContext . addRecordToFieldList (fieldRecord );
241+ fieldListBuilder . addField (fieldRecord );
235242 });
236243
237244 if (typeEntry .isArray ()) {
@@ -250,7 +257,7 @@ private CVTypeRecord buildStructureTypeEntry(final StructureTypeEntry typeEntry)
250257 /* Build a field for the 0 length array. */
251258 CVTypeRecord .CVMemberRecord dm = new CVTypeRecord .CVMemberRecord (MPROP_PUBLIC , array0record .getSequenceNumber (), typeEntry .getSize (), "data" );
252259 log ("field %s" , dm );
253- fieldListContext . addRecordToFieldList (dm );
260+ fieldListBuilder . addField (dm );
254261 }
255262
256263 /*
@@ -292,25 +299,25 @@ private CVTypeRecord buildStructureTypeEntry(final StructureTypeEntry typeEntry)
292299
293300 /* LF_METHOD record */
294301 CVTypeRecord .CVOverloadedMethodRecord methodRecord = new CVTypeRecord .CVOverloadedMethodRecord ((short ) nmlist .count (), nmlist .getSequenceNumber (), mname );
295- fieldListContext . addRecordToFieldList (methodRecord );
302+ fieldListBuilder . addField (methodRecord );
296303 });
297304
298305 methods .stream ().filter (methodEntry -> !overloaded .contains (methodEntry .methodName ())).forEach (m -> {
299306 log ("`unique method %s %s %s(...)" , m .fieldName (), m .methodName (), m .getModifiersString (), m .getValueType ().getTypeName (), m .methodName ());
300307 CVTypeRecord .CVOneMethodRecord method = buildMethod ((ClassEntry ) typeEntry , m );
301308 log (" unique method %s" , method );
302- fieldListContext . addRecordToFieldList (method );
309+ fieldListBuilder . addField (method );
303310 });
304311 }
305312 /* Build fieldlist record from manifested fields. */
306- CVTypeRecord .CVFieldListRecord newfieldListRecord = fieldListContext . addTypeRecords (this );
313+ CVTypeRecord .CVFieldListRecord newfieldListRecord = fieldListBuilder . buildFieldListRecords (this );
307314 int fieldListIdx = newfieldListRecord .getSequenceNumber ();
308- int fieldListCount = newfieldListRecord . count ();
315+ int fieldCount = fieldListBuilder . getFieldCount ();
309316 log ("finished building fieldlist %s" , newfieldListRecord );
310317
311318 /* Build final class record. */
312319 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 );
320+ CVTypeRecord typeRecord = new CVTypeRecord .CVClassRecord (LF_CLASS , (short ) fieldCount , attrs , fieldListIdx , 0 , 0 , typeEntry .getSize (), typeEntry .getTypeName (), null );
314321 typeRecord = addTypeRecord (typeRecord );
315322
316323 if (typeEntry .isClass ()) {
@@ -330,7 +337,7 @@ private CVTypeRecord buildStructureTypeEntry(final StructureTypeEntry typeEntry)
330337
331338 types .typeNameMap .put (typeEntry .getTypeName (), typeRecord );
332339
333- /* CVSymbolSubsectionBuilder will add an associated S_UDT record to symbol table. */
340+ /* CVSymbolSubsectionBuilder will add associated S_UDT record to symbol table. */
334341 log (" finished class %s" , typeRecord );
335342
336343 return typeRecord ;
0 commit comments