39 #include "oops/oop.inline.hpp" |
39 #include "oops/oop.inline.hpp" |
40 #include "runtime/fieldDescriptor.inline.hpp" |
40 #include "runtime/fieldDescriptor.inline.hpp" |
41 #include "utilities/bitMap.inline.hpp" |
41 #include "utilities/bitMap.inline.hpp" |
42 |
42 |
43 #if INCLUDE_CDS_JAVA_HEAP |
43 #if INCLUDE_CDS_JAVA_HEAP |
44 KlassSubGraphInfo* HeapShared::_subgraph_info_list = NULL; |
44 address HeapShared::_narrow_oop_base; |
45 int HeapShared::_num_archived_subgraph_info_records = 0; |
45 int HeapShared::_narrow_oop_shift; |
46 Array<ArchivedKlassSubGraphInfoRecord>* HeapShared::_archived_subgraph_info_records = NULL; |
46 HeapShared::DumpTimeKlassSubGraphInfoTable* HeapShared::_dump_time_subgraph_info_table = NULL; |
47 |
47 HeapShared::RunTimeKlassSubGraphInfoTable HeapShared::_run_time_subgraph_info_table; |
48 KlassSubGraphInfo* HeapShared::find_subgraph_info(Klass* k) { |
|
49 KlassSubGraphInfo* info = _subgraph_info_list; |
|
50 while (info != NULL) { |
|
51 if (info->klass() == k) { |
|
52 return info; |
|
53 } |
|
54 info = info->next(); |
|
55 } |
|
56 return NULL; |
|
57 } |
|
58 |
48 |
59 // Get the subgraph_info for Klass k. A new subgraph_info is created if |
49 // Get the subgraph_info for Klass k. A new subgraph_info is created if |
60 // there is no existing one for k. The subgraph_info records the relocated |
50 // there is no existing one for k. The subgraph_info records the relocated |
61 // Klass* of the original k. |
51 // Klass* of the original k. |
62 KlassSubGraphInfo* HeapShared::get_subgraph_info(Klass* k) { |
52 KlassSubGraphInfo* HeapShared::get_subgraph_info(Klass* k) { |
|
53 assert(DumpSharedSpaces, "dump time only"); |
63 Klass* relocated_k = MetaspaceShared::get_relocated_klass(k); |
54 Klass* relocated_k = MetaspaceShared::get_relocated_klass(k); |
64 KlassSubGraphInfo* info = find_subgraph_info(relocated_k); |
55 KlassSubGraphInfo* info = _dump_time_subgraph_info_table->get(relocated_k); |
65 if (info != NULL) { |
56 if (info == NULL) { |
66 return info; |
57 _dump_time_subgraph_info_table->put(relocated_k, KlassSubGraphInfo(relocated_k)); |
67 } |
58 info = _dump_time_subgraph_info_table->get(relocated_k); |
68 |
59 ++ _dump_time_subgraph_info_table->_count; |
69 info = new KlassSubGraphInfo(relocated_k, _subgraph_info_list); |
60 } |
70 _subgraph_info_list = info; |
|
71 return info; |
61 return info; |
72 } |
|
73 |
|
74 address HeapShared::_narrow_oop_base; |
|
75 int HeapShared::_narrow_oop_shift; |
|
76 |
|
77 int HeapShared::num_of_subgraph_infos() { |
|
78 int num = 0; |
|
79 KlassSubGraphInfo* info = _subgraph_info_list; |
|
80 while (info != NULL) { |
|
81 num ++; |
|
82 info = info->next(); |
|
83 } |
|
84 return num; |
|
85 } |
62 } |
86 |
63 |
87 // Add an entry field to the current KlassSubGraphInfo. |
64 // Add an entry field to the current KlassSubGraphInfo. |
88 void KlassSubGraphInfo::add_subgraph_entry_field(int static_field_offset, oop v) { |
65 void KlassSubGraphInfo::add_subgraph_entry_field(int static_field_offset, oop v) { |
89 assert(DumpSharedSpaces, "dump time only"); |
66 assert(DumpSharedSpaces, "dump time only"); |
189 _subgraph_object_klasses->at_put(i, subgraph_k); |
165 _subgraph_object_klasses->at_put(i, subgraph_k); |
190 } |
166 } |
191 } |
167 } |
192 } |
168 } |
193 |
169 |
|
170 struct CopyKlassSubGraphInfoToArchive : StackObj { |
|
171 CompactHashtableWriter* _writer; |
|
172 CopyKlassSubGraphInfoToArchive(CompactHashtableWriter* writer) : _writer(writer) {} |
|
173 |
|
174 bool do_entry(Klass* klass, KlassSubGraphInfo& info) { |
|
175 if (info.subgraph_object_klasses() != NULL || info.subgraph_entry_fields() != NULL) { |
|
176 ArchivedKlassSubGraphInfoRecord* record = |
|
177 (ArchivedKlassSubGraphInfoRecord*)MetaspaceShared::read_only_space_alloc(sizeof(ArchivedKlassSubGraphInfoRecord)); |
|
178 record->init(&info); |
|
179 |
|
180 unsigned int hash = primitive_hash<Klass*>(klass); |
|
181 uintx deltax = MetaspaceShared::object_delta(record); |
|
182 guarantee(deltax <= MAX_SHARED_DELTA, "must not be"); |
|
183 u4 delta = u4(deltax); |
|
184 _writer->add(hash, delta); |
|
185 } |
|
186 return true; // keep on iterating |
|
187 } |
|
188 }; |
|
189 |
194 // Build the records of archived subgraph infos, which include: |
190 // Build the records of archived subgraph infos, which include: |
195 // - Entry points to all subgraphs from the containing class mirror. The entry |
191 // - Entry points to all subgraphs from the containing class mirror. The entry |
196 // points are static fields in the mirror. For each entry point, the field |
192 // points are static fields in the mirror. For each entry point, the field |
197 // offset and value are recorded in the sub-graph info. The value are stored |
193 // offset and value are recorded in the sub-graph info. The value are stored |
198 // back to the corresponding field at runtime. |
194 // back to the corresponding field at runtime. |
199 // - A list of klasses that need to be loaded/initialized before archived |
195 // - A list of klasses that need to be loaded/initialized before archived |
200 // java object sub-graph can be accessed at runtime. |
196 // java object sub-graph can be accessed at runtime. |
201 // |
197 void HeapShared::write_subgraph_info_table() { |
202 // The records are saved in the archive file and reloaded at runtime. |
198 // Allocate the contents of the hashtable(s) inside the RO region of the CDS archive. |
203 // |
199 DumpTimeKlassSubGraphInfoTable* d_table = _dump_time_subgraph_info_table; |
204 // Layout of the archived subgraph info records: |
200 CompactHashtableStats stats; |
205 // |
201 |
206 // records_size | num_records | records* |
202 _run_time_subgraph_info_table.reset(); |
207 // ArchivedKlassSubGraphInfoRecord | entry_fields | subgraph_object_klasses |
203 |
208 size_t HeapShared::build_archived_subgraph_info_records(int num_records) { |
204 int num_buckets = CompactHashtableWriter::default_num_buckets(d_table->_count); |
209 // remember the start address |
205 CompactHashtableWriter writer(num_buckets, &stats); |
210 char* start_p = MetaspaceShared::read_only_space_top(); |
206 CopyKlassSubGraphInfoToArchive copy(&writer); |
211 |
207 _dump_time_subgraph_info_table->iterate(©); |
212 // now populate the archived subgraph infos, which will be saved in the |
208 |
213 // archive file |
209 writer.dump(&_run_time_subgraph_info_table, "subgraphs"); |
214 _archived_subgraph_info_records = |
210 } |
215 MetaspaceShared::new_ro_array<ArchivedKlassSubGraphInfoRecord>(num_records); |
211 |
216 KlassSubGraphInfo* info = _subgraph_info_list; |
212 void HeapShared::serialize_subgraph_info_table_header(SerializeClosure* soc) { |
217 int i = 0; |
213 _run_time_subgraph_info_table.serialize_header(soc); |
218 while (info != NULL) { |
|
219 assert(i < _archived_subgraph_info_records->length(), "sanity"); |
|
220 ArchivedKlassSubGraphInfoRecord* record = |
|
221 _archived_subgraph_info_records->adr_at(i); |
|
222 record->init(info); |
|
223 info = info->next(); |
|
224 i ++; |
|
225 } |
|
226 |
|
227 // _subgraph_info_list is no longer needed |
|
228 delete _subgraph_info_list; |
|
229 _subgraph_info_list = NULL; |
|
230 |
|
231 char* end_p = MetaspaceShared::read_only_space_top(); |
|
232 size_t records_size = end_p - start_p; |
|
233 return records_size; |
|
234 } |
|
235 |
|
236 // Write the subgraph info records in the shared _ro region |
|
237 void HeapShared::write_archived_subgraph_infos() { |
|
238 assert(DumpSharedSpaces, "dump time only"); |
|
239 |
|
240 Array<intptr_t>* records_header = MetaspaceShared::new_ro_array<intptr_t>(3); |
|
241 |
|
242 _num_archived_subgraph_info_records = num_of_subgraph_infos(); |
|
243 size_t records_size = build_archived_subgraph_info_records( |
|
244 _num_archived_subgraph_info_records); |
|
245 |
|
246 // Now write the header information: |
|
247 // records_size, num_records, _archived_subgraph_info_records |
|
248 assert(records_header != NULL, "sanity"); |
|
249 intptr_t* p = (intptr_t*)(records_header->data()); |
|
250 *p = (intptr_t)records_size; |
|
251 p ++; |
|
252 *p = (intptr_t)_num_archived_subgraph_info_records; |
|
253 p ++; |
|
254 *p = (intptr_t)_archived_subgraph_info_records; |
|
255 } |
|
256 |
|
257 char* HeapShared::read_archived_subgraph_infos(char* buffer) { |
|
258 Array<intptr_t>* records_header = (Array<intptr_t>*)buffer; |
|
259 intptr_t* p = (intptr_t*)(records_header->data()); |
|
260 size_t records_size = (size_t)(*p); |
|
261 p ++; |
|
262 _num_archived_subgraph_info_records = *p; |
|
263 p ++; |
|
264 _archived_subgraph_info_records = |
|
265 (Array<ArchivedKlassSubGraphInfoRecord>*)(*p); |
|
266 |
|
267 buffer = (char*)_archived_subgraph_info_records + records_size; |
|
268 return buffer; |
|
269 } |
214 } |
270 |
215 |
271 void HeapShared::initialize_from_archived_subgraph(Klass* k) { |
216 void HeapShared::initialize_from_archived_subgraph(Klass* k) { |
272 if (!MetaspaceShared::open_archive_heap_region_mapped()) { |
217 if (!MetaspaceShared::open_archive_heap_region_mapped()) { |
273 return; // nothing to do |
218 return; // nothing to do |
274 } |
219 } |
275 |
220 assert(!DumpSharedSpaces, "Should not be called with DumpSharedSpaces"); |
276 if (_num_archived_subgraph_info_records == 0) { |
221 |
277 return; // no subgraph info records |
222 unsigned int hash = primitive_hash<Klass*>(k); |
278 } |
223 ArchivedKlassSubGraphInfoRecord* record = _run_time_subgraph_info_table.lookup(k, hash, 0); |
279 |
224 |
280 // Initialize from archived data. Currently this is done only |
225 // Initialize from archived data. Currently this is done only |
281 // during VM initialization time. No lock is needed. |
226 // during VM initialization time. No lock is needed. |
282 Thread* THREAD = Thread::current(); |
227 if (record != NULL) { |
283 for (int i = 0; i < _archived_subgraph_info_records->length(); i++) { |
228 Thread* THREAD = Thread::current(); |
284 ArchivedKlassSubGraphInfoRecord* record = _archived_subgraph_info_records->adr_at(i); |
229 if (log_is_enabled(Info, cds, heap)) { |
285 if (record->klass() == k) { |
230 ResourceMark rm; |
286 int i; |
231 log_info(cds, heap)("initialize_from_archived_subgraph " PTR_FORMAT " %s", p2i(k), |
287 // Found the archived subgraph info record for the requesting klass. |
232 k->external_name()); |
288 // Load/link/initialize the klasses of the objects in the subgraph. |
233 } |
289 // NULL class loader is used. |
234 |
290 Array<Klass*>* klasses = record->subgraph_object_klasses(); |
235 int i; |
291 if (klasses != NULL) { |
236 // Load/link/initialize the klasses of the objects in the subgraph. |
292 for (i = 0; i < klasses->length(); i++) { |
237 // NULL class loader is used. |
293 Klass* obj_k = klasses->at(i); |
238 Array<Klass*>* klasses = record->subgraph_object_klasses(); |
294 Klass* resolved_k = SystemDictionary::resolve_or_null( |
239 if (klasses != NULL) { |
295 (obj_k)->name(), THREAD); |
240 for (i = 0; i < klasses->length(); i++) { |
296 if (resolved_k != obj_k) { |
241 Klass* obj_k = klasses->at(i); |
297 return; |
242 Klass* resolved_k = SystemDictionary::resolve_or_null( |
298 } |
243 (obj_k)->name(), THREAD); |
299 if ((obj_k)->is_instance_klass()) { |
244 if (resolved_k != obj_k) { |
300 InstanceKlass* ik = InstanceKlass::cast(obj_k); |
245 return; |
301 ik->initialize(THREAD); |
246 } |
302 } else if ((obj_k)->is_objArray_klass()) { |
247 if ((obj_k)->is_instance_klass()) { |
303 ObjArrayKlass* oak = ObjArrayKlass::cast(obj_k); |
248 InstanceKlass* ik = InstanceKlass::cast(obj_k); |
304 oak->initialize(THREAD); |
249 ik->initialize(THREAD); |
305 } |
250 } else if ((obj_k)->is_objArray_klass()) { |
|
251 ObjArrayKlass* oak = ObjArrayKlass::cast(obj_k); |
|
252 oak->initialize(THREAD); |
306 } |
253 } |
307 } |
254 } |
308 |
255 } |
309 if (HAS_PENDING_EXCEPTION) { |
256 |
310 CLEAR_PENDING_EXCEPTION; |
257 if (HAS_PENDING_EXCEPTION) { |
311 // None of the field value will be set if there was an exception. |
258 CLEAR_PENDING_EXCEPTION; |
312 // The java code will not see any of the archived objects in the |
259 // None of the field value will be set if there was an exception. |
313 // subgraphs referenced from k in this case. |
260 // The java code will not see any of the archived objects in the |
314 return; |
261 // subgraphs referenced from k in this case. |
|
262 return; |
|
263 } |
|
264 |
|
265 // Load the subgraph entry fields from the record and store them back to |
|
266 // the corresponding fields within the mirror. |
|
267 oop m = k->java_mirror(); |
|
268 Array<juint>* entry_field_records = record->entry_field_records(); |
|
269 if (entry_field_records != NULL) { |
|
270 int efr_len = entry_field_records->length(); |
|
271 assert(efr_len % 2 == 0, "sanity"); |
|
272 for (i = 0; i < efr_len;) { |
|
273 int field_offset = entry_field_records->at(i); |
|
274 // The object refereced by the field becomes 'known' by GC from this |
|
275 // point. All objects in the subgraph reachable from the object are |
|
276 // also 'known' by GC. |
|
277 oop v = MetaspaceShared::materialize_archived_object( |
|
278 entry_field_records->at(i+1)); |
|
279 m->obj_field_put(field_offset, v); |
|
280 i += 2; |
|
281 |
|
282 log_debug(cds, heap)(" " PTR_FORMAT " init field @ %2d = " PTR_FORMAT, p2i(k), field_offset, p2i(v)); |
315 } |
283 } |
316 |
284 |
317 // Load the subgraph entry fields from the record and store them back to |
285 // Done. Java code can see the archived sub-graphs referenced from k's |
318 // the corresponding fields within the mirror. |
286 // mirror after this point. |
319 oop m = k->java_mirror(); |
|
320 Array<juint>* entry_field_records = record->entry_field_records(); |
|
321 if (entry_field_records != NULL) { |
|
322 int efr_len = entry_field_records->length(); |
|
323 assert(efr_len % 2 == 0, "sanity"); |
|
324 for (i = 0; i < efr_len;) { |
|
325 int field_offset = entry_field_records->at(i); |
|
326 // The object refereced by the field becomes 'known' by GC from this |
|
327 // point. All objects in the subgraph reachable from the object are |
|
328 // also 'known' by GC. |
|
329 oop v = MetaspaceShared::materialize_archived_object( |
|
330 entry_field_records->at(i+1)); |
|
331 m->obj_field_put(field_offset, v); |
|
332 i += 2; |
|
333 } |
|
334 } |
|
335 |
|
336 // Done. Java code can see the archived sub-graphs referenced from k's |
|
337 // mirror after this point. |
|
338 return; |
|
339 } |
287 } |
340 } |
288 } |
341 } |
289 } |
342 |
290 |
343 class WalkOopAndArchiveClosure: public BasicOopIterateClosure { |
291 class WalkOopAndArchiveClosure: public BasicOopIterateClosure { |