22
22
*
23
23
*/
24
24
25
+ #include " memory/resourceArea.hpp"
26
+ #include " cds/cdsConfig.hpp"
25
27
#include " oops/fieldInfo.inline.hpp"
26
28
#include " runtime/atomic.hpp"
29
+ #include " utilities/packedTable.hpp"
27
30
28
31
void FieldInfo::print (outputStream* os, ConstantPool* cp) {
29
32
os->print_cr (" index=%d name_index=%d name=%s signature_index=%d signature=%s offset=%d "
@@ -37,8 +40,10 @@ void FieldInfo::print(outputStream* os, ConstantPool* cp) {
37
40
field_flags ().as_uint (),
38
41
initializer_index (),
39
42
generic_signature_index (),
40
- _field_flags.is_injected () ? lookup_symbol (generic_signature_index ())->as_utf8 () : cp->symbol_at (generic_signature_index ())->as_utf8 (),
41
- contended_group ());
43
+ _field_flags.is_generic () ? (_field_flags.is_injected () ?
44
+ lookup_symbol (generic_signature_index ())->as_utf8 () : cp->symbol_at (generic_signature_index ())->as_utf8 ()
45
+ ) : " " ,
46
+ is_contended () ? contended_group () : 0 );
42
47
}
43
48
44
49
void FieldInfo::print_from_growable_array (outputStream* os, GrowableArray<FieldInfo>* array, ConstantPool* cp) {
@@ -62,13 +67,17 @@ Array<u1>* FieldInfoStream::create_FieldInfoStream(GrowableArray<FieldInfo>* fie
62
67
StreamSizer s;
63
68
StreamFieldSizer sizer (&s);
64
69
70
+ assert (fields->length () == java_fields + injected_fields, " must be" );
71
+
65
72
sizer.consumer ()->accept_uint (java_fields);
66
73
sizer.consumer ()->accept_uint (injected_fields);
67
74
for (int i = 0 ; i < fields->length (); i++) {
68
75
FieldInfo* fi = fields->adr_at (i);
69
76
sizer.map_field_info (*fi);
70
77
}
71
- int storage_size = sizer.consumer ()->position () + 1 ;
78
+ // Originally there was an extra byte with 0 terminating the reading;
79
+ // now we check limits instead.
80
+ int storage_size = sizer.consumer ()->position ();
72
81
Array<u1>* const fis = MetadataFactory::new_array<u1>(loader_data, storage_size, CHECK_NULL);
73
82
74
83
using StreamWriter = UNSIGNED5::Writer<Array<u1>*, int , ArrayHelper<Array<u1>*, int >>;
@@ -79,15 +88,14 @@ Array<u1>* FieldInfoStream::create_FieldInfoStream(GrowableArray<FieldInfo>* fie
79
88
writer.consumer ()->accept_uint (java_fields);
80
89
writer.consumer ()->accept_uint (injected_fields);
81
90
for (int i = 0 ; i < fields->length (); i++) {
82
- FieldInfo* fi = fields->adr_at (i);
83
- writer.map_field_info (*fi);
91
+ writer.map_field_info (fields->at (i));
84
92
}
85
93
86
94
#ifdef ASSERT
87
95
FieldInfoReader r (fis);
88
- int jfc = r.next_uint ();
96
+ int jfc, ifc;
97
+ r.read_field_counts (&jfc, &ifc);
89
98
assert (jfc == java_fields, " Must be" );
90
- int ifc = r.next_uint ();
91
99
assert (ifc == injected_fields, " Must be" );
92
100
for (int i = 0 ; i < jfc + ifc; i++) {
93
101
FieldInfo fi;
@@ -113,30 +121,221 @@ Array<u1>* FieldInfoStream::create_FieldInfoStream(GrowableArray<FieldInfo>* fie
113
121
return fis;
114
122
}
115
123
124
+ int FieldInfoStream::compare_name_and_sig (const Symbol* n1, const Symbol* s1, const Symbol* n2, const Symbol* s2) {
125
+ int cmp = n1->fast_compare (n2);
126
+ return cmp != 0 ? cmp : s1->fast_compare (s2);
127
+ }
128
+
129
+
130
+ // We use both name and signature during the comparison; while JLS require unique
131
+ // names for fields, JVMS requires only unique name + signature combination.
132
+ struct field_pos {
133
+ Symbol* _name;
134
+ Symbol* _signature;
135
+ int _index;
136
+ int _position;
137
+ };
138
+
139
+ class FieldInfoSupplier : public PackedTableBuilder ::Supplier {
140
+ const field_pos* _positions;
141
+ size_t _elements;
142
+
143
+ public:
144
+ FieldInfoSupplier (const field_pos* positions, size_t elements): _positions(positions), _elements(elements) {}
145
+
146
+ bool next (uint32_t * key, uint32_t * value) override {
147
+ if (_elements == 0 ) {
148
+ return false ;
149
+ }
150
+ *key = _positions->_position ;
151
+ *value = _positions->_index ;
152
+ ++_positions;
153
+ --_elements;
154
+ return true ;
155
+ }
156
+ };
157
+
158
+ Array<u1>* FieldInfoStream::create_search_table (ConstantPool* cp, const Array<u1>* fis, ClassLoaderData* loader_data, TRAPS) {
159
+ if (CDSConfig::is_dumping_dynamic_archive ()) {
160
+ // We cannot use search table; in case of dynamic archives it should be sorted by "requested" addresses,
161
+ // but Symbol* addresses are coming from _constants, which has "buffered" addresses.
162
+ // For background, see new comments inside allocate_node_impl in symbolTable.cpp
163
+ return nullptr ;
164
+ }
165
+
166
+ FieldInfoReader r (fis);
167
+ int java_fields;
168
+ int injected_fields;
169
+ r.read_field_counts (&java_fields, &injected_fields);
170
+ assert (java_fields >= 0 , " must be" );
171
+ if (java_fields == 0 || fis->length () == 0 || static_cast <uint>(java_fields) < BinarySearchThreshold) {
172
+ return nullptr ;
173
+ }
174
+
175
+ ResourceMark rm;
176
+ field_pos* positions = NEW_RESOURCE_ARRAY (field_pos, java_fields);
177
+ for (int i = 0 ; i < java_fields; ++i) {
178
+ assert (r.has_next (), " number of fields must match" );
179
+
180
+ positions[i]._position = r.position ();
181
+ FieldInfo fi;
182
+ r.read_field_info (fi);
183
+
184
+ positions[i]._name = fi.name (cp);
185
+ positions[i]._signature = fi.signature (cp);
186
+ positions[i]._index = i;
187
+ }
188
+ auto compare_pair = [](const void * v1, const void * v2) {
189
+ const field_pos* p1 = reinterpret_cast <const field_pos*>(v1);
190
+ const field_pos* p2 = reinterpret_cast <const field_pos*>(v2);
191
+ return compare_name_and_sig (p1->_name , p1->_signature , p2->_name , p2->_signature );
192
+ };
193
+ qsort (positions, java_fields, sizeof (field_pos), compare_pair);
194
+
195
+ PackedTableBuilder builder (fis->length () - 1 , java_fields - 1 );
196
+ Array<u1>* table = MetadataFactory::new_array<u1>(loader_data, java_fields * builder.element_bytes (), CHECK_NULL);
197
+ FieldInfoSupplier supplier (positions, java_fields);
198
+ builder.fill (table->data (), static_cast <size_t >(table->length ()), supplier);
199
+ return table;
200
+ }
201
+
116
202
GrowableArray<FieldInfo>* FieldInfoStream::create_FieldInfoArray (const Array<u1>* fis, int * java_fields_count, int * injected_fields_count) {
117
- int length = FieldInfoStream::num_total_fields (fis);
118
- GrowableArray<FieldInfo>* array = new GrowableArray<FieldInfo>(length);
119
203
FieldInfoReader r (fis);
120
- *java_fields_count = r.next_uint ();
121
- *injected_fields_count = r.next_uint ();
204
+ r.read_field_counts (java_fields_count, injected_fields_count);
205
+ int length = *java_fields_count + *injected_fields_count;
206
+
207
+ GrowableArray<FieldInfo>* array = new GrowableArray<FieldInfo>(length);
122
208
while (r.has_next ()) {
123
209
FieldInfo fi;
124
210
r.read_field_info (fi);
125
211
array->append (fi);
126
212
}
127
213
assert (array->length () == length, " Must be" );
128
- assert (array->length () == *java_fields_count + *injected_fields_count, " Must be" );
129
214
return array;
130
215
}
131
216
132
217
void FieldInfoStream::print_from_fieldinfo_stream (Array<u1>* fis, outputStream* os, ConstantPool* cp) {
133
- int length = FieldInfoStream::num_total_fields (fis);
134
218
FieldInfoReader r (fis);
135
- int java_field_count = r.next_uint ();
136
- int injected_fields_count = r.next_uint ();
219
+ int java_fields_count;
220
+ int injected_fields_count;
221
+ r.read_field_counts (&java_fields_count, &injected_fields_count);
137
222
while (r.has_next ()) {
138
223
FieldInfo fi;
139
224
r.read_field_info (fi);
140
225
fi.print (os, cp);
141
226
}
142
227
}
228
+
229
+ class FieldInfoComparator : public PackedTableLookup ::Comparator {
230
+ const FieldInfoReader* _reader;
231
+ ConstantPool* _cp;
232
+ const Symbol* _name;
233
+ const Symbol* _signature;
234
+
235
+ public:
236
+ FieldInfoComparator (const FieldInfoReader* reader, ConstantPool* cp, const Symbol* name, const Symbol* signature):
237
+ _reader (reader), _cp(cp), _name(name), _signature(signature) {}
238
+
239
+ int compare_to (uint32_t position) override {
240
+ FieldInfoReader r2 (*_reader);
241
+ r2.set_position_and_next_index (position, -1 );
242
+ u2 name_index, sig_index;
243
+ r2.read_name_and_signature (&name_index, &sig_index);
244
+ Symbol* mid_name = _cp->symbol_at (name_index);
245
+ Symbol* mid_sig = _cp->symbol_at (sig_index);
246
+
247
+ return FieldInfoStream::compare_name_and_sig (_name, _signature, mid_name, mid_sig);
248
+ }
249
+
250
+ #ifdef ASSERT
251
+ void reset (uint32_t position) override {
252
+ FieldInfoReader r2 (*_reader);
253
+ r2.set_position_and_next_index (position, -1 );
254
+ u2 name_index, signature_index;
255
+ r2.read_name_and_signature (&name_index, &signature_index);
256
+ _name = _cp->symbol_at (name_index);
257
+ _signature = _cp->symbol_at (signature_index);
258
+ }
259
+ #endif // ASSERT
260
+ };
261
+
262
+ #ifdef ASSERT
263
+ void FieldInfoStream::validate_search_table (ConstantPool* cp, const Array<u1>* fis, const Array<u1>* search_table) {
264
+ if (search_table == nullptr ) {
265
+ return ;
266
+ }
267
+ FieldInfoReader reader (fis);
268
+ int java_fields, injected_fields;
269
+ reader.read_field_counts (&java_fields, &injected_fields);
270
+ assert (java_fields > 0 , " must be" );
271
+
272
+ PackedTableLookup lookup (fis->length () - 1 , java_fields - 1 , search_table);
273
+ assert (lookup.element_bytes () * java_fields == static_cast <unsigned int >(search_table->length ()), " size does not match" );
274
+
275
+ FieldInfoComparator comparator (&reader, cp, nullptr , nullptr );
276
+ // Check 1: assert that elements have the correct order based on the comparison function
277
+ lookup.validate_order (comparator);
278
+
279
+ // Check 2: Iterate through the original stream (not just search_table) and try if lookup works as expected
280
+ reader.set_position_and_next_index (0 , 0 );
281
+ reader.read_field_counts (&java_fields, &injected_fields);
282
+ while (reader.has_next ()) {
283
+ int field_start = reader.position ();
284
+ FieldInfo fi;
285
+ reader.read_field_info (fi);
286
+ if (fi.field_flags ().is_injected ()) {
287
+ // checking only java fields that precede injected ones
288
+ break ;
289
+ }
290
+
291
+ FieldInfoReader r2 (fis);
292
+ int index = r2.search_table_lookup (search_table, fi.name (cp), fi.signature (cp), cp, java_fields);
293
+ assert (index == static_cast <int >(fi.index ()), " wrong index: %d != %u" , index, fi.index ());
294
+ assert (index == r2.next_index (), " index should match" );
295
+ assert (field_start == r2.position (), " must find the same position" );
296
+ }
297
+ }
298
+ #endif // ASSERT
299
+
300
+ void FieldInfoStream::print_search_table (outputStream* st, ConstantPool* cp, const Array<u1>* fis, const Array<u1>* search_table) {
301
+ if (search_table == nullptr ) {
302
+ return ;
303
+ }
304
+ FieldInfoReader reader (fis);
305
+ int java_fields, injected_fields;
306
+ reader.read_field_counts (&java_fields, &injected_fields);
307
+ assert (java_fields > 0 , " must be" );
308
+ PackedTableLookup lookup (fis->length () - 1 , java_fields - 1 , search_table);
309
+ auto printer = [&] (size_t offset, uint32_t position, uint32_t index) {
310
+ reader.set_position_and_next_index (position, -1 );
311
+ u2 name_index, sig_index;
312
+ reader.read_name_and_signature (&name_index, &sig_index);
313
+ Symbol* name = cp->symbol_at (name_index);
314
+ Symbol* sig = cp->symbol_at (sig_index);
315
+ st->print (" [%zu] #%d,#%d = " , offset, name_index, sig_index);
316
+ name->print_symbol_on (st);
317
+ st->print (" :" );
318
+ sig->print_symbol_on (st);
319
+ st->print (" @ %p,%p" , name, sig);
320
+ st->cr ();
321
+ };
322
+
323
+ lookup.iterate(printer);
324
+ }
325
+
326
+ int FieldInfoReader::search_table_lookup (const Array<u1>* search_table, const Symbol* name, const Symbol* signature, ConstantPool* cp, int java_fields) {
327
+ assert (java_fields >= 0 , " must be" );
328
+ if (java_fields == 0 ) {
329
+ return -1 ;
330
+ }
331
+ FieldInfoComparator comp (this , cp, name, signature);
332
+ PackedTableLookup lookup (_r.limit () - 1 , java_fields - 1 , search_table);
333
+ uint32_t position;
334
+ static_assert (sizeof (uint32_t ) == sizeof (_next_index), " field size assert" );
335
+ if (lookup.search (comp, &position, reinterpret_cast <uint32_t *>(&_next_index))) {
336
+ _r.set_position (static_cast <int >(position));
337
+ return _next_index;
338
+ } else {
339
+ return -1 ;
340
+ }
341
+ }
0 commit comments