< prev index next >

src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/z/ZPage.java

Print this page

        

@@ -22,32 +22,47 @@
  *
  */
 
 package sun.jvm.hotspot.gc.z;
 
+import java.util.ArrayList;
+import java.util.List;
+
 import sun.jvm.hotspot.debugger.Address;
+import sun.jvm.hotspot.debugger.OopHandle;
+import sun.jvm.hotspot.gc.shared.LiveRegionsProvider;
+import sun.jvm.hotspot.memory.MemRegion;
+import sun.jvm.hotspot.oops.Oop;
+import sun.jvm.hotspot.oops.UnknownOopException;
 import sun.jvm.hotspot.runtime.VM;
 import sun.jvm.hotspot.runtime.VMObject;
 import sun.jvm.hotspot.runtime.VMObjectFactory;
+import sun.jvm.hotspot.types.AddressField;
 import sun.jvm.hotspot.types.CIntegerField;
 import sun.jvm.hotspot.types.Type;
 import sun.jvm.hotspot.types.TypeDataBase;
 
-public class ZPage extends VMObject {
+public class ZPage extends VMObject implements LiveRegionsProvider {
     private static CIntegerField typeField;
+    private static CIntegerField seqnumField;
     private static long virtualFieldOffset;
+    private static AddressField topField;
+    private static CIntegerField refcountField;
     private static long forwardingFieldOffset;
 
     static {
         VM.registerVMInitializedObserver((o, d) -> initialize(VM.getVM().getTypeDataBase()));
     }
 
     static private synchronized void initialize(TypeDataBase db) {
         Type type = db.lookupType("ZPage");
 
         typeField = type.getCIntegerField("_type");
+        seqnumField = type.getCIntegerField("_seqnum");
         virtualFieldOffset = type.getField("_virtual").getOffset();
+        topField = type.getAddressField("_top");
+        refcountField = type.getCIntegerField("_refcount");
         forwardingFieldOffset = type.getField("_forwarding").getOffset();
     }
 
     public ZPage(Address addr) {
         super(addr);

@@ -55,16 +70,44 @@
 
     private byte type() {
         return typeField.getJByte(addr);
     }
 
+    private int seqnum() {
+        return seqnumField.getJInt(addr);
+    }
+
     private ZVirtualMemory virtual() {
-        return (ZVirtualMemory)VMObjectFactory.newObject(ZVirtualMemory.class, addr.addOffsetTo(virtualFieldOffset));
+        return VMObjectFactory.newObject(ZVirtualMemory.class, addr.addOffsetTo(virtualFieldOffset));
+    }
+
+    private Address top() {
+        return topField.getValue(addr);
+    }
+
+    private int refcount() {
+        // refcount is uint32_t so need to be cautious when using this field.
+        return refcountField.getJInt(addr);
     }
 
     private ZForwardingTable forwarding() {
-        return (ZForwardingTable)VMObjectFactory.newObject(ZForwardingTable.class, addr.addOffsetTo(forwardingFieldOffset));
+        return VMObjectFactory.newObject(ZForwardingTable.class, addr.addOffsetTo(forwardingFieldOffset));
+    }
+
+    private boolean is_forwarding() {
+        return forwarding().table() != null;
+    }
+
+    private boolean is_relocatable() {
+        return is_active() && seqnum() < ZGlobals.ZGlobalSeqNum();
+    }
+
+    private boolean isPageRelocating() {
+        assert(is_active());
+        // is_forwarding():  Has a (relocation) forwarding table
+        // is_relocatable(): Has not been freed yet
+        return is_forwarding() && is_relocatable();
     }
 
     long start() {
         return virtual().start();
     }

@@ -96,17 +139,106 @@
         // There's no relocate operation in the SA.
         // Mimic object pinning and return the good view of the from object.
         return ZAddress.good(from);
     }
 
-
     long object_alignment_shift() {
         if (type() == ZGlobals.ZPageTypeSmall) {
             return ZGlobals.ZObjectAlignmentSmallShift();
         } else if (type() == ZGlobals.ZPageTypeMedium) {
             return ZGlobals.ZObjectAlignmentMediumShift;
         } else {
             assert(type() == ZGlobals.ZPageTypeLarge);
             return ZGlobals.ZObjectAlignmentLargeShift;
         }
     }
+
+    long objectAlignmentSize() {
+        return 1 << object_alignment_shift();
+    }
+
+    public boolean is_active() {
+        return refcount() != 0;
+    }
+
+    private long getObjectSize(Address good) {
+        OopHandle handle = good.addOffsetToAsOopHandle(0);
+        Oop obj = null;
+
+        try {
+           obj = VM.getVM().getObjectHeap().newOop(handle);
+        } catch (UnknownOopException exp) {
+          throw new RuntimeException(" UnknownOopException  " + exp);
+        }
+
+        return VM.getVM().alignUp(obj.getObjectSize(), objectAlignmentSize());
+    }
+
+    private void addNotRelocatedRegions(List<MemRegion> regions) {
+        MemRegion mr = null;
+
+        // Some objects have already been forwarded to new locations.
+        long topValue = top().asLongValue();
+        for (long offsetValue = start(); offsetValue < topValue;) {
+            Address from = ZAddress.good(ZUtils.longToAddress(offsetValue));
+
+            Address to = relocate_object(from);
+
+            long byteSize;
+            try {
+                byteSize = getObjectSize(to);
+            } catch (Exception e) {
+                // Parsing the ZHeap is inherently unsafe
+                // when classes have been unloaded. Dead objects
+                // might have stale Klass pointers, and there's
+                // no way to get the size of the dead object.
+                //
+                // If possible, run with -XX:-ClassUnloading
+                // to ensure that all Klasses are kept alive.
+                System.err.println("Unparsable regions found. Skipping: "
+                        + from
+                        + " "
+                        + from.addOffsetTo(topValue - offsetValue));
+                
+                // Can't proceed further. Just return the collected regions.
+                return;
+            }
+
+            if (from.equals(to)) {
+                // Not relocated - add region
+                if (mr == null) {
+                    mr = new MemRegion(from, 0 /* wordSize */);
+                    regions.add(mr);
+                }
+
+                long wordSize = byteSize / VM.getVM().getBytesPerWord();
+                mr.setWordSize(mr.wordSize() + wordSize);
+            } else {
+                // Forwarded somewhere else, split region.
+                mr = null;
+            }
+
+            offsetValue += byteSize;
+        }
+    }
+
+    public List<MemRegion> getLiveRegions() {
+        List<MemRegion> res = new ArrayList<>();
+
+        if (isPageRelocating()) {
+            addNotRelocatedRegions(res);
+        } else {
+            Address start = ZAddress.good(ZUtils.longToAddress(start()));
+
+            // Can't convert top() to a "good" address because it might
+            // be at the top of the "offset" range, and therefore also
+            // looks like one of the color bits. Instead use the "good"
+            // address and add the size.
+            long size = top().asLongValue() - start();
+            Address end = start.addOffsetTo(size);
+
+            res.add(new MemRegion(start, end));
+        }
+
+        return res;
+    }
 }
< prev index next >