Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8308603

Removing do_pending_ref/enclosing_ref from MetaspaceClosure

XMLWordPrintable

    • Icon: Enhancement Enhancement
    • Resolution: Fixed
    • Icon: P4 P4
    • 22
    • 21
    • hotspot
    • b02

      MetaspaceClosure is used to traverse all *pointers* in the metaspace objects. It works recursively.

      To avoid overflowing the C callstack due to excessively deep hierarchies, we use a side stack and limit the recursion to no more than 5 levels deep.

      https://github.com/openjdk/jdk/blob/5d8ba938bef162b74816147eb1002a0620a419ba/src/hotspot/share/memory/metaspaceClosure.cpp#L35-L44

      void MetaspaceClosure::push_impl(MetaspaceClosure::Ref* ref) {
        if (_nest_level < MAX_NEST_LEVEL) { // == 5
          do_push(ref);
          delete ref;
        } else {
          do_pending_ref(ref);
          ref->set_next(_pending_refs);
          _pending_refs = ref;
        }
      }

      If we have objects that look like this

              A->B->C->D->E->F->G

      where

          (A->B) means A has a field A.fa that points to B
          (B->C) means B has a field B.fb that points to C
          ...
          (F->G) means F has a field F.ff that points to G

      We call MetaspaceClosure::push() six times to record the pointers of

         A->B, B->C, C->D, ..., F->G

      Each of these pointers are represented by a MetaspaceClosure::Ref object.

      When visiting C->D, we call MetaspaceClosure::push() with C->D immediately (nesting level is smaller than 5). Inside push(), we call MetaspaceClosure::enclosing_ref() to find C, and mark the pointer C.fc.

      When visiting F->G, the nesting level is too deep, so we save the Ref of F->G into MetaspaceClosure::_pending_refs (the "else" block in the above code snippet). However, as soon as we return from push_impl, we lose the fact that F.ff is pointing to G.

      To work around this, our hack is to call do_pending_ref(), which can mark the F.ff pointer.

      ====================================

      This is too complicated. It can be simplified by remember the address of F in the MetaspaceClosure::Ref that represents the F->G relationship.

      It's kind of odd that we don't do that already. In the Ref, we already remember the address of the pointer (i.e., Ref::mpp() == &F.ff). We should just as well remember F itself.

            iklam Ioi Lam
            iklam Ioi Lam
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated:
              Resolved: