39
39
import org .graalvm .compiler .debug .GraalError ;
40
40
41
41
import java .lang .reflect .Modifier ;
42
+ import java .util .ArrayList ;
42
43
import java .util .Collections ;
43
44
import java .util .Deque ;
44
45
import java .util .HashMap ;
@@ -152,42 +153,52 @@ CVTypeRecord buildFunction(PrimaryEntry entry) {
152
153
return buildMemberFunction (entry .getClassEntry (), entry .getPrimary ().getMethodEntry ());
153
154
}
154
155
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 <>();
158
158
159
- final CVTypeRecord .CVFieldListRecord firstFieldList ;
160
- CVTypeRecord .CVFieldListRecord currentFieldList ;
161
- final Deque <CVTypeRecord .CVFieldListRecord > lists = new LinkedList <>();
159
+ FieldListBuilder () {
160
+ }
162
161
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 );
167
164
}
168
165
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 ();
176
168
}
177
169
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 ;
180
191
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 );
184
195
/* For all fieldlist but the first, link to the previous record. */
185
196
if (idx != 0 ) {
186
- fieldList .add (new CVTypeRecord .CVIndexRecord (idx ));
197
+ fieldListRecord .add (new CVTypeRecord .CVIndexRecord (idx ));
187
198
}
188
- idx = currentFieldList .getSequenceNumber ();
199
+ idx = fieldListRecord .getSequenceNumber ();
189
200
}
190
- return currentFieldList ;
201
+ return fieldListRecord ;
191
202
}
192
203
}
193
204
@@ -212,26 +223,22 @@ private CVTypeRecord buildStructureTypeEntry(final StructureTypeEntry typeEntry)
212
223
213
224
final List <MethodEntry > methods = typeEntry .isClass () ? ((ClassEntry ) typeEntry ).getMethods () : Collections .emptyList ();
214
225
215
- /* process fields */
216
-
217
226
/* 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" );
222
229
223
230
if (superTypeIndex != 0 ) {
224
231
CVTypeRecord .CVBaseMemberRecord btype = new CVTypeRecord .CVBaseMemberRecord (MPROP_PUBLIC , superTypeIndex , 0 );
225
232
log ("basetype %s" , btype );
226
- fieldListContext . addRecordToFieldList (btype );
233
+ fieldListBuilder . addField (btype );
227
234
}
228
235
229
236
/* Only define manifested fields. */
230
237
typeEntry .fields ().filter (CVTypeSectionBuilder ::isManifestedField ).forEach (f -> {
231
238
log ("field %s attr=(%s) offset=%d size=%d valuetype=%s" , f .fieldName (), f .getModifiersString (), f .getOffset (), f .getSize (), f .getValueType ().getTypeName ());
232
239
CVTypeRecord .FieldRecord fieldRecord = buildField (f );
233
240
log ("field %s" , fieldRecord );
234
- fieldListContext . addRecordToFieldList (fieldRecord );
241
+ fieldListBuilder . addField (fieldRecord );
235
242
});
236
243
237
244
if (typeEntry .isArray ()) {
@@ -250,7 +257,7 @@ private CVTypeRecord buildStructureTypeEntry(final StructureTypeEntry typeEntry)
250
257
/* Build a field for the 0 length array. */
251
258
CVTypeRecord .CVMemberRecord dm = new CVTypeRecord .CVMemberRecord (MPROP_PUBLIC , array0record .getSequenceNumber (), typeEntry .getSize (), "data" );
252
259
log ("field %s" , dm );
253
- fieldListContext . addRecordToFieldList (dm );
260
+ fieldListBuilder . addField (dm );
254
261
}
255
262
256
263
/*
@@ -292,25 +299,25 @@ private CVTypeRecord buildStructureTypeEntry(final StructureTypeEntry typeEntry)
292
299
293
300
/* LF_METHOD record */
294
301
CVTypeRecord .CVOverloadedMethodRecord methodRecord = new CVTypeRecord .CVOverloadedMethodRecord ((short ) nmlist .count (), nmlist .getSequenceNumber (), mname );
295
- fieldListContext . addRecordToFieldList (methodRecord );
302
+ fieldListBuilder . addField (methodRecord );
296
303
});
297
304
298
305
methods .stream ().filter (methodEntry -> !overloaded .contains (methodEntry .methodName ())).forEach (m -> {
299
306
log ("`unique method %s %s %s(...)" , m .fieldName (), m .methodName (), m .getModifiersString (), m .getValueType ().getTypeName (), m .methodName ());
300
307
CVTypeRecord .CVOneMethodRecord method = buildMethod ((ClassEntry ) typeEntry , m );
301
308
log (" unique method %s" , method );
302
- fieldListContext . addRecordToFieldList (method );
309
+ fieldListBuilder . addField (method );
303
310
});
304
311
}
305
312
/* Build fieldlist record from manifested fields. */
306
- CVTypeRecord .CVFieldListRecord newfieldListRecord = fieldListContext . addTypeRecords (this );
313
+ CVTypeRecord .CVFieldListRecord newfieldListRecord = fieldListBuilder . buildFieldListRecords (this );
307
314
int fieldListIdx = newfieldListRecord .getSequenceNumber ();
308
- int fieldListCount = newfieldListRecord . count ();
315
+ int fieldCount = fieldListBuilder . getFieldCount ();
309
316
log ("finished building fieldlist %s" , newfieldListRecord );
310
317
311
318
/* Build final class record. */
312
319
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 );
314
321
typeRecord = addTypeRecord (typeRecord );
315
322
316
323
if (typeEntry .isClass ()) {
@@ -330,7 +337,7 @@ private CVTypeRecord buildStructureTypeEntry(final StructureTypeEntry typeEntry)
330
337
331
338
types .typeNameMap .put (typeEntry .getTypeName (), typeRecord );
332
339
333
- /* CVSymbolSubsectionBuilder will add an associated S_UDT record to symbol table. */
340
+ /* CVSymbolSubsectionBuilder will add associated S_UDT record to symbol table. */
334
341
log (" finished class %s" , typeRecord );
335
342
336
343
return typeRecord ;
0 commit comments