@@ -288,7 +288,7 @@ void HeapShared::clear_root(int index) {
288288 }
289289}
290290
291- bool HeapShared::archive_object (oop obj, KlassSubGraphInfo* subgraph_info) {
291+ bool HeapShared::archive_object (oop obj, oop referrer, KlassSubGraphInfo* subgraph_info) {
292292 assert (CDSConfig::is_dumping_heap (), " dump-time only" );
293293
294294 assert (!obj->is_stackChunk (), " do not archive stack chunks" );
@@ -304,7 +304,7 @@ bool HeapShared::archive_object(oop obj, KlassSubGraphInfo* subgraph_info) {
304304 } else {
305305 count_allocation (obj->size ());
306306 ArchiveHeapWriter::add_source_obj (obj);
307- CachedOopInfo info = make_cached_oop_info (obj);
307+ CachedOopInfo info = make_cached_oop_info (obj, referrer );
308308 archived_object_cache ()->put_when_absent (obj, info);
309309 archived_object_cache ()->maybe_grow ();
310310 mark_native_pointers (obj);
@@ -1350,33 +1350,39 @@ void HeapShared::clear_archived_roots_of(Klass* k) {
13501350 }
13511351}
13521352
1353- class WalkOopAndArchiveClosure : public BasicOopIterateClosure {
1353+ // Push all oops that are referenced by _referencing_obj onto the _stack.
1354+ class HeapShared ::ReferentPusher: public BasicOopIterateClosure {
1355+ PendingOopStack* _stack;
1356+ GrowableArray<oop> _found_oop_fields;
13541357 int _level;
13551358 bool _record_klasses_only;
13561359 KlassSubGraphInfo* _subgraph_info;
13571360 oop _referencing_obj;
1358-
1359- // The following are for maintaining a stack for determining
1360- // CachedOopInfo::_referrer
1361- static WalkOopAndArchiveClosure* _current;
1362- WalkOopAndArchiveClosure* _last;
13631361 public:
1364- WalkOopAndArchiveClosure (int level,
1362+ ReferentPusher (PendingOopStack* stack,
1363+ int level,
13651364 bool record_klasses_only,
13661365 KlassSubGraphInfo* subgraph_info,
13671366 oop orig) :
1367+ _stack (stack),
1368+ _found_oop_fields (),
13681369 _level (level),
13691370 _record_klasses_only (record_klasses_only),
13701371 _subgraph_info (subgraph_info),
13711372 _referencing_obj (orig) {
1372- _last = _current;
1373- _current = this ;
13741373 }
1375- ~WalkOopAndArchiveClosure () {
1376- _current = _last;
1374+ void do_oop (narrowOop *p) { ReferentPusher::do_oop_work (p); }
1375+ void do_oop ( oop *p) { ReferentPusher::do_oop_work (p); }
1376+
1377+ ~ReferentPusher () {
1378+ while (_found_oop_fields.length () > 0 ) {
1379+ // This produces the exact same traversal order as the previous version
1380+ // of ReferentPusher that recurses on the C stack -- a depth-first search,
1381+ // walking the oop fields in _referencing_obj by ascending field offsets.
1382+ oop obj = _found_oop_fields.pop ();
1383+ _stack->push (PendingOop (obj, _referencing_obj, _level + 1 ));
1384+ }
13771385 }
1378- void do_oop (narrowOop *p) { WalkOopAndArchiveClosure::do_oop_work (p); }
1379- void do_oop ( oop *p) { WalkOopAndArchiveClosure::do_oop_work (p); }
13801386
13811387 protected:
13821388 template <class T > void do_oop_work (T *p) {
@@ -1396,20 +1402,15 @@ class WalkOopAndArchiveClosure: public BasicOopIterateClosure {
13961402 }
13971403 }
13981404
1399- bool success = HeapShared::archive_reachable_objects_from (
1400- _level + 1 , _subgraph_info, obj);
1401- assert (success, " VM should have exited with unarchivable objects for _level > 1" );
1405+ _found_oop_fields.push (obj);
14021406 }
14031407 }
14041408
14051409 public:
1406- static WalkOopAndArchiveClosure* current () { return _current; }
14071410 oop referencing_obj () { return _referencing_obj; }
14081411 KlassSubGraphInfo* subgraph_info () { return _subgraph_info; }
14091412};
14101413
1411- WalkOopAndArchiveClosure* WalkOopAndArchiveClosure::_current = nullptr ;
1412-
14131414// Checks if an oop has any non-null oop fields
14141415class PointsToOopsChecker : public BasicOopIterateClosure {
14151416 bool _result;
@@ -1425,9 +1426,7 @@ class PointsToOopsChecker : public BasicOopIterateClosure {
14251426 bool result () { return _result; }
14261427};
14271428
1428- HeapShared::CachedOopInfo HeapShared::make_cached_oop_info (oop obj) {
1429- WalkOopAndArchiveClosure* walker = WalkOopAndArchiveClosure::current ();
1430- oop referrer = (walker == nullptr ) ? nullptr : walker->referencing_obj ();
1429+ HeapShared::CachedOopInfo HeapShared::make_cached_oop_info (oop obj, oop referrer) {
14311430 PointsToOopsChecker points_to_oops_checker;
14321431 obj->oop_iterate (&points_to_oops_checker);
14331432 return CachedOopInfo (referrer, points_to_oops_checker.result ());
@@ -1450,12 +1449,35 @@ void HeapShared::init_box_classes(TRAPS) {
14501449// (1) If orig_obj has not been archived yet, archive it.
14511450// (2) If orig_obj has not been seen yet (since start_recording_subgraph() was called),
14521451// trace all objects that are reachable from it, and make sure these objects are archived.
1453- // (3) Record the klasses of all orig_obj and all reachable objects.
1452+ // (3) Record the klasses of all objects that are reachable from orig_obj (including those that
1453+ // were already archived when this function is called)
14541454bool HeapShared::archive_reachable_objects_from (int level,
14551455 KlassSubGraphInfo* subgraph_info,
14561456 oop orig_obj) {
14571457 assert (orig_obj != nullptr , " must be" );
1458+ PendingOopStack stack;
1459+ stack.push (PendingOop (orig_obj, nullptr , level));
1460+
1461+ while (stack.length () > 0 ) {
1462+ PendingOop po = stack.pop ();
1463+ _object_being_archived = po;
1464+ bool status = walk_one_object (&stack, po.level (), subgraph_info, po.obj (), po.referrer ());
1465+ _object_being_archived = PendingOop ();
1466+
1467+ if (!status) {
1468+ // Don't archive a subgraph root that's too big. For archives static fields, that's OK
1469+ // as the Java code will take care of initializing this field dynamically.
1470+ assert (level == 1 , " VM should have exited with unarchivable objects for _level > 1" );
1471+ return false ;
1472+ }
1473+ }
14581474
1475+ return true ;
1476+ }
1477+
1478+ bool HeapShared::walk_one_object (PendingOopStack* stack, int level, KlassSubGraphInfo* subgraph_info,
1479+ oop orig_obj, oop referrer) {
1480+ assert (orig_obj != nullptr , " must be" );
14591481 if (!JavaClasses::is_supported_for_archiving (orig_obj)) {
14601482 // This object has injected fields that cannot be supported easily, so we disallow them for now.
14611483 // If you get an error here, you probably made a change in the JDK library that has added
@@ -1524,7 +1546,7 @@ bool HeapShared::archive_reachable_objects_from(int level,
15241546 bool record_klasses_only = already_archived;
15251547 if (!already_archived) {
15261548 ++_num_new_archived_objs;
1527- if (!archive_object (orig_obj, subgraph_info)) {
1549+ if (!archive_object (orig_obj, referrer, subgraph_info)) {
15281550 // Skip archiving the sub-graph referenced from the current entry field.
15291551 ResourceMark rm;
15301552 log_error (cds, heap)(
@@ -1547,8 +1569,13 @@ bool HeapShared::archive_reachable_objects_from(int level,
15471569 Klass *orig_k = orig_obj->klass ();
15481570 subgraph_info->add_subgraph_object_klass (orig_k);
15491571
1550- WalkOopAndArchiveClosure walker (level, record_klasses_only, subgraph_info, orig_obj);
1551- orig_obj->oop_iterate (&walker);
1572+ {
1573+ // Find all the oops that are referenced by orig_obj, push them onto the stack
1574+ // so we can work on them next.
1575+ ResourceMark rm;
1576+ ReferentPusher pusher (stack, level, record_klasses_only, subgraph_info, orig_obj);
1577+ orig_obj->oop_iterate (&pusher);
1578+ }
15521579
15531580 if (CDSConfig::is_initing_classes_at_dump_time ()) {
15541581 // The enum klasses are archived with aot-initialized mirror.
@@ -1573,8 +1600,7 @@ bool HeapShared::archive_reachable_objects_from(int level,
15731600// - No java.lang.Class instance (java mirror) can be included inside
15741601// an archived sub-graph. Mirror can only be the sub-graph entry object.
15751602//
1576- // The Java heap object sub-graph archiving process (see
1577- // WalkOopAndArchiveClosure):
1603+ // The Java heap object sub-graph archiving process (see ReferentPusher):
15781604//
15791605// 1) Java object sub-graph archiving starts from a given static field
15801606// within a Class instance (java mirror). If the static field is a
@@ -1722,6 +1748,7 @@ void HeapShared::check_special_subgraph_classes() {
17221748}
17231749
17241750HeapShared::SeenObjectsTable* HeapShared::_seen_objects_table = nullptr ;
1751+ HeapShared::PendingOop HeapShared::_object_being_archived;
17251752int HeapShared::_num_new_walked_objs;
17261753int HeapShared::_num_new_archived_objs;
17271754int HeapShared::_num_old_recorded_klasses;
@@ -2043,10 +2070,11 @@ bool HeapShared::is_dumped_interned_string(oop o) {
20432070
20442071void HeapShared::debug_trace () {
20452072 ResourceMark rm;
2046- WalkOopAndArchiveClosure* walker = WalkOopAndArchiveClosure::current ();
2047- if (walker != nullptr ) {
2073+ oop referrer = _object_being_archived. referrer ();
2074+ if (referrer != nullptr ) {
20482075 LogStream ls (Log (cds, heap)::error ());
2049- CDSHeapVerifier::trace_to_root (&ls, walker->referencing_obj ());
2076+ ls.print_cr (" Reference trace" );
2077+ CDSHeapVerifier::trace_to_root (&ls, referrer);
20502078 }
20512079}
20522080
0 commit comments