28
28
#include " cds/archiveHeapLoader.hpp"
29
29
#include " cds/archiveHeapWriter.hpp"
30
30
#include " cds/archiveUtils.hpp"
31
+ #include " cds/cdsAccess.hpp"
31
32
#include " cds/cdsConfig.hpp"
32
33
#include " cds/cdsEnumKlass.hpp"
33
34
#include " cds/cdsHeapVerifier.hpp"
@@ -248,12 +249,6 @@ int HeapShared::append_root(oop obj) {
248
249
// No GC should happen since we aren't scanning _pending_roots.
249
250
assert (Thread::current () == (Thread*)VMThread::vm_thread (), " should be in vm thread" );
250
251
251
- if (UsePermanentHeapObjects && obj != nullptr ) {
252
- int n = get_archived_object_permanent_index_locked (obj);
253
- assert (n >= 0 , " must have been added" );
254
- return n;
255
- }
256
-
257
252
if (_pending_roots == nullptr ) {
258
253
_pending_roots = new GrowableArrayCHeap<OopHandle, mtClassShared>(500 );
259
254
}
@@ -322,77 +317,53 @@ oop HeapShared::orig_to_scratch_object(oop orig_obj) {
322
317
return nullptr ;
323
318
}
324
319
325
- class ArchivedObjectPermanentIndexTable : public ResourceHashtable <OopHandle, int ,
320
+ // Permanent oops are used to support AOT-compiled methods, which may have in-line references
321
+ // to Strings and MH oops.
322
+ //
323
+ // At runtime, these oops are stored in _runtime_permanent_oops (which keeps them alive forever)
324
+ // and are accssed vis CDSAccess::get_archived_object(int).
325
+ struct PermanentOopInfo {
326
+ int _index; // Gets assigned only if HeapShared::get_archived_object_permanent_index() has been called on the object
327
+ int _heap_offset; // Offset of the object from the bottom of the archived heap.
328
+ PermanentOopInfo (int index, int heap_offset) : _index(index), _heap_offset(heap_offset) {}
329
+ };
330
+
331
+ class PermanentOopTable : public ResourceHashtable <OopHandle, PermanentOopInfo,
326
332
36137 , // prime number
327
333
AnyObj::C_HEAP,
328
334
mtClassShared,
329
335
oop_handle_hash,
330
336
oop_handle_equals> {};
331
337
332
- static ArchivedObjectPermanentIndexTable* _permanent_index_table = nullptr ;
333
-
334
- void HeapShared::add_to_permanent_index_table (oop obj) {
335
- assert_locked_or_safepoint (ArchivedObjectTables_lock);
336
-
337
- assert (CDSConfig::is_dumping_heap (), " must be" );
338
- if (UsePermanentHeapObjects) {
339
- if (_permanent_index_table == nullptr ) {
340
- _permanent_index_table = new (mtClass)ArchivedObjectPermanentIndexTable ();
341
- }
342
- if (_pending_roots == nullptr ) {
343
- _pending_roots = new GrowableArrayCHeap<OopHandle, mtClassShared>(500 );
344
- }
345
-
346
- if (_orig_to_scratch_object_table != nullptr ) {
347
- OopHandle orig (&obj);
348
- OopHandle* v = _orig_to_scratch_object_table->get (orig);
349
- if (v != nullptr ) {
350
- obj = v->resolve ();
351
- }
352
- }
338
+ static int _dumptime_permanent_oop_count = 0 ;
339
+ static PermanentOopTable* _dumptime_permanent_oop_table = nullptr ;
340
+ static GrowableArrayCHeap<OopHandle, mtClassShared>* _runtime_permanent_oops = nullptr ;
353
341
354
- OopHandle oh (Universe::vm_global (), obj);
355
- int index = _pending_roots->append (oh);
356
- _permanent_index_table->put_when_absent (oh, index );
342
+ // ArchiveHeapWriter adds each archived heap object to _dumptime_permanent_oop_table,
343
+ // so we can remember their offset (from the bottom of the archived heap).
344
+ void HeapShared::add_to_permanent_oop_table (oop obj, int offset) {
345
+ assert_at_safepoint ();
346
+ if (_dumptime_permanent_oop_table == nullptr ) {
347
+ _dumptime_permanent_oop_table = new (mtClass)PermanentOopTable ();
357
348
}
349
+
350
+ PermanentOopInfo info (-1 , offset);
351
+ OopHandle oh (Universe::vm_global (), obj);
352
+ _dumptime_permanent_oop_table->put_when_absent (oh, info);
358
353
}
359
354
355
+ // A permanent index is assigned to an archived object ONLY when
356
+ // the AOT compiler calls this function.
360
357
int HeapShared::get_archived_object_permanent_index (oop obj) {
361
358
MutexLocker ml (ArchivedObjectTables_lock, Mutex::_no_safepoint_check_flag);
362
- return get_archived_object_permanent_index_locked (obj);
363
- }
364
359
365
- // Can be called in the "old" workflow.
366
- int HeapShared::get_archived_object_permanent_index_locked (oop obj) {
367
- assert_locked_or_safepoint (ArchivedObjectTables_lock);
368
- if (!UsePermanentHeapObjects) {
369
- return -1 ;
360
+ if (!CDSConfig::is_dumping_heap ()) {
361
+ return -1 ; // Called by the Leyden old workflow
370
362
}
371
- if (! CDSConfig::is_dumping_heap () && ! ArchiveHeapLoader::is_in_use () ) {
363
+ if (_dumptime_permanent_oop_table == nullptr ) {
372
364
return -1 ;
373
365
}
374
366
375
- if (_permanent_index_table == nullptr ) {
376
- if (!ArchiveHeapLoader::is_in_use ()) {
377
- // Called in the old workflow
378
- return -1 ;
379
- } else {
380
- _permanent_index_table = new (mtClass)ArchivedObjectPermanentIndexTable ();
381
- int count = 0 ;
382
- for (int segment_idx = 0 ; segment_idx < _root_segments->length (); segment_idx++) {
383
- objArrayOop segment = (objArrayOop)_root_segments->at (segment_idx).resolve ();
384
- for (int i = 0 ; i < segment->length (); i++, count++) {
385
- oop root = segment->obj_at (i);
386
- if (root != nullptr ) {
387
- OopHandle tmp (Universe::vm_global (), root);
388
- int index = count;
389
- _permanent_index_table->put_when_absent (tmp, index );
390
- }
391
- }
392
- }
393
- }
394
- }
395
-
396
367
if (_orig_to_scratch_object_table != nullptr ) {
397
368
OopHandle orig (&obj);
398
369
OopHandle* v = _orig_to_scratch_object_table->get (orig);
@@ -402,28 +373,78 @@ int HeapShared::get_archived_object_permanent_index_locked(oop obj) {
402
373
}
403
374
404
375
OopHandle tmp (&obj);
405
- int * v = _permanent_index_table->get (tmp);
406
- if (v != nullptr ) {
407
- int n = *v;
408
- return n;
376
+ PermanentOopInfo* info = _dumptime_permanent_oop_table->get (tmp);
377
+ if (info == nullptr ) {
378
+ return -1 ;
379
+ } else {
380
+ if (info->_index < 0 ) {
381
+ info->_index = _dumptime_permanent_oop_count++;
382
+ }
383
+ return info->_index ;
409
384
}
410
-
411
- return -1 ;
412
385
}
413
386
414
387
oop HeapShared::get_archived_object (int permanent_index) {
415
- if (ArchiveHeapLoader::is_in_use ()) {
416
- return get_root (permanent_index);
417
- } else {
418
- assert (CDSConfig::is_dumping_heap (), " must be" );
419
- if (_pending_roots != nullptr ) {
420
- return _pending_roots->at (permanent_index).resolve ();
421
- } else {
422
- return nullptr ;
423
- }
388
+ assert (permanent_index >= 0 , " sanity" );
389
+ assert (ArchiveHeapLoader::is_in_use (), " sanity" );
390
+ assert (_runtime_permanent_oops != nullptr , " sanity" );
391
+
392
+ oop obj = _runtime_permanent_oops->at (permanent_index).resolve ();
393
+ log_info (cds)(" GET perm obj %d = %p" , permanent_index, cast_from_oop<void *>(obj));
394
+ if (obj != nullptr ) {
395
+ log_info (cds)(" GET perm obj %d class = %p" , permanent_index, obj->klass ());
396
+ log_info (cds)(" GET perm obj %d class = %s" , permanent_index, obj->klass ()->external_name ());
397
+ }
398
+ return obj;
399
+ }
400
+
401
+ // Remember all archived heap objects that have a permanent index.
402
+ // table[i] = offset of oop whose permanent index is i.
403
+ void CachedCodeDirectoryInternal::dumptime_init_internal () {
404
+ const int count = _dumptime_permanent_oop_count;
405
+ int * table = (int *)CDSAccess::allocate_from_code_cache (count * sizeof (int ));
406
+ for (int i = 0 ; i < count; i++) {
407
+ table[count] = -1 ;
408
+ }
409
+ _dumptime_permanent_oop_table->iterate([&](OopHandle o, PermanentOopInfo& info) {
410
+ int index = info._index ;
411
+ if (index >= 0 ) {
412
+ assert (index < count, " sanity" );
413
+ table[index ] = info._heap_offset ;
414
+ }
415
+ return true ; // continue
416
+ });
417
+
418
+ for (int i = 0 ; i < count; i++) {
419
+ assert (table[i] >= 0 , " must be" );
424
420
}
421
+
422
+ log_info (cds)(" Dumped %d permanent oops" , count);
423
+
424
+ _permanent_oop_count = count;
425
+ CDSAccess::set_pointer (&_permanent_oop_offsets, table);
425
426
}
426
427
428
+ // This is called during the bootstrap of the production run, before any GC can happen.
429
+ // Record each permanent oop in a OopHandle for GC safety.
430
+ void CachedCodeDirectoryInternal::runtime_init_internal () {
431
+ int count = _permanent_oop_count;
432
+ int * table = _permanent_oop_offsets;
433
+ _runtime_permanent_oops = new GrowableArrayCHeap<OopHandle, mtClassShared>();
434
+ for (int i = 0 ; i < count; i++) {
435
+ oop obj = ArchiveHeapLoader::oop_from_offset (table[i]);
436
+ OopHandle oh (Universe::vm_global (), obj);
437
+ _runtime_permanent_oops->append (oh);
438
+
439
+ ResourceMark rm;
440
+ log_info (cds)(" perm obj %d = %p" , i, cast_from_oop<void *>(obj));
441
+ if (obj != nullptr ) {
442
+ log_info (cds)(" perm obj %d class = %p" , i, obj->klass ());
443
+ log_info (cds)(" perm obj %d class = %s" , i, obj->klass ()->external_name ());
444
+ }
445
+ }
446
+ };
447
+
427
448
void HeapShared::get_segment_indexes (int idx, int & seg_idx, int & int_idx) {
428
449
assert (_root_segment_max_size_elems > 0 , " sanity" );
429
450
@@ -482,7 +503,6 @@ bool HeapShared::archive_object(oop obj) {
482
503
debug_trace ();
483
504
return false ;
484
505
} else {
485
- add_to_permanent_index_table (obj);
486
506
count_allocation (obj->size ());
487
507
ArchiveHeapWriter::add_source_obj (obj);
488
508
CachedOopInfo info = make_cached_oop_info (obj);
0 commit comments