src/hotspot/share/memory/metaspaceClosure.cpp
changeset 54927 1512d88b24c6
parent 52631 3009ca99de32
child 55296 357c9dcb6eb9
--- a/src/hotspot/share/memory/metaspaceClosure.cpp	Fri May 17 10:48:02 2019 -0400
+++ b/src/hotspot/share/memory/metaspaceClosure.cpp	Fri May 17 08:29:55 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -34,9 +34,20 @@
   *(address*)mpp() = (address)p;
 }
 
-void MetaspaceClosure::push_impl(MetaspaceClosure::Ref* ref, Writability w) {
-  if (ref->not_null()) {
+void MetaspaceClosure::push_impl(MetaspaceClosure::Ref* ref) {
+  if (_nest_level < MAX_NEST_LEVEL) {
+    do_push(ref);
+    delete ref;
+  } else {
+    ref->set_next(_pending_refs);
+    _pending_refs = ref;
+  }
+}
+
+void MetaspaceClosure::do_push(MetaspaceClosure::Ref* ref) {
+  if (ref->not_null()) { // FIXME: make this configurable, so DynamicArchiveBuilder mark all pointers
     bool read_only;
+    Writability w = ref->writability();
     switch (w) {
     case _writable:
       read_only = false;
@@ -48,12 +59,29 @@
       assert(w == _default, "must be");
       read_only = ref->is_read_only_by_default();
     }
+    _nest_level ++;
     if (do_ref(ref, read_only)) { // true means we want to iterate the embedded pointer in <ref>
       ref->metaspace_pointers_do(this);
     }
+    _nest_level --;
   }
 }
 
+void MetaspaceClosure::finish() {
+  assert(_nest_level == 0, "must be");
+  while (_pending_refs != NULL) {
+    Ref* ref = _pending_refs;
+    _pending_refs = _pending_refs->next();
+    do_push(ref);
+    delete ref;
+  }
+}
+
+MetaspaceClosure::~MetaspaceClosure() {
+  assert(_pending_refs == NULL,
+         "you must explicitly call MetaspaceClosure::finish() to process all refs!");
+}
+
 bool UniqueMetaspaceClosure::do_ref(MetaspaceClosure::Ref* ref, bool read_only) {
   bool* found = _has_been_visited.lookup(ref->obj());
   if (found != NULL) {
@@ -64,7 +92,6 @@
     if (_has_been_visited.maybe_grow(MAX_TABLE_SIZE)) {
       log_info(cds, hashtables)("Expanded _has_been_visited table to %d", _has_been_visited.table_size());
     }
-    do_unique_ref(ref, read_only);
-    return true;  // Saw this for the first time: iterate the embedded pointers.
+    return do_unique_ref(ref, read_only);
   }
 }