--- old/src/hotspot/share/gc/z/vmStructs_z.cpp 2019-02-13 16:34:50.946271754 +0100 +++ new/src/hotspot/share/gc/z/vmStructs_z.cpp 2019-02-13 16:34:50.566271767 +0100 @@ -26,6 +26,7 @@ ZGlobalsForVMStructs::ZGlobalsForVMStructs() : _ZGlobalPhase(&ZGlobalPhase), + _ZGlobalSeqNum(&ZGlobalSeqNum), _ZAddressGoodMask(&ZAddressGoodMask), _ZAddressBadMask(&ZAddressBadMask), _ZAddressWeakBadMask(&ZAddressWeakBadMask), --- old/src/hotspot/share/gc/z/vmStructs_z.hpp 2019-02-13 16:34:51.450271736 +0100 +++ new/src/hotspot/share/gc/z/vmStructs_z.hpp 2019-02-13 16:34:51.058271750 +0100 @@ -42,6 +42,8 @@ uint32_t* _ZGlobalPhase; + uint32_t* _ZGlobalSeqNum; + uintptr_t* _ZAddressGoodMask; uintptr_t* _ZAddressBadMask; uintptr_t* _ZAddressWeakBadMask; @@ -55,6 +57,7 @@ #define VM_STRUCTS_ZGC(nonstatic_field, volatile_nonstatic_field, static_field) \ static_field(ZGlobalsForVMStructs, _instance_p, ZGlobalsForVMStructs*) \ nonstatic_field(ZGlobalsForVMStructs, _ZGlobalPhase, uint32_t*) \ + nonstatic_field(ZGlobalsForVMStructs, _ZGlobalSeqNum, uint32_t*) \ nonstatic_field(ZGlobalsForVMStructs, _ZAddressGoodMask, uintptr_t*) \ nonstatic_field(ZGlobalsForVMStructs, _ZAddressBadMask, uintptr_t*) \ nonstatic_field(ZGlobalsForVMStructs, _ZAddressWeakBadMask, uintptr_t*) \ @@ -67,7 +70,10 @@ nonstatic_field(ZHeap, _pagetable, ZPageTable) \ \ nonstatic_field(ZPage, _type, const uint8_t) \ + nonstatic_field(ZPage, _seqnum, uint32_t) \ nonstatic_field(ZPage, _virtual, const ZVirtualMemory) \ + volatile_nonstatic_field(ZPage, _top, uintptr_t) \ + volatile_nonstatic_field(ZPage, _refcount, uint32_t) \ nonstatic_field(ZPage, _forwarding, ZForwardingTable) \ \ nonstatic_field(ZPageAllocator, _physical, ZPhysicalMemoryManager) \ @@ -101,6 +107,7 @@ declare_constant(ZAddressOffsetShift) \ declare_constant(ZAddressOffsetBits) \ declare_constant(ZAddressOffsetMask) \ + declare_constant(ZAddressOffsetMax) \ declare_constant(ZAddressSpaceStart) #define VM_TYPES_ZGC(declare_type, declare_toplevel_type, declare_integer_type) \ --- old/src/hotspot/share/gc/z/zCollectedHeap.cpp 2019-02-13 16:34:51.978271718 +0100 +++ new/src/hotspot/share/gc/z/zCollectedHeap.cpp 2019-02-13 16:34:51.582271732 +0100 @@ -118,10 +118,6 @@ return is_in(p); } -void ZCollectedHeap::fill_with_dummy_object(HeapWord* start, HeapWord* end, bool zap) { - // Does nothing, not a parsable heap -} - HeapWord* ZCollectedHeap::allocate_new_tlab(size_t min_size, size_t requested_size, size_t* actual_size) { const size_t size_in_bytes = ZUtils::words_to_bytes(align_object_size(requested_size)); const uintptr_t addr = _heap.alloc_tlab(size_in_bytes); --- old/src/hotspot/share/gc/z/zCollectedHeap.hpp 2019-02-13 16:34:52.482271701 +0100 +++ new/src/hotspot/share/gc/z/zCollectedHeap.hpp 2019-02-13 16:34:52.106271714 +0100 @@ -75,8 +75,6 @@ virtual bool is_in(const void* p) const; virtual bool is_in_closed_subset(const void* p) const; - virtual void fill_with_dummy_object(HeapWord* start, HeapWord* end, bool zap); - virtual HeapWord* mem_allocate(size_t size, bool* gc_overhead_limit_was_exceeded); virtual MetaWord* satisfy_failed_metadata_allocation(ClassLoaderData* loader_data, size_t size, --- old/src/hotspot/share/runtime/vmStructs.cpp 2019-02-13 16:34:52.994271683 +0100 +++ new/src/hotspot/share/runtime/vmStructs.cpp 2019-02-13 16:34:52.618271696 +0100 @@ -1245,6 +1245,7 @@ declare_integer_type(intptr_t) \ declare_unsigned_integer_type(uintx) \ declare_unsigned_integer_type(uintptr_t) \ + declare_unsigned_integer_type(volatile uintptr_t) \ declare_unsigned_integer_type(uint8_t) \ declare_unsigned_integer_type(uint32_t) \ declare_unsigned_integer_type(uint64_t) \ --- old/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/cms/CompactibleFreeListSpace.java 2019-02-13 16:34:53.550271663 +0100 +++ new/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/cms/CompactibleFreeListSpace.java 2019-02-13 16:34:53.182271676 +0100 @@ -35,7 +35,7 @@ import sun.jvm.hotspot.types.*; import sun.jvm.hotspot.utilities.*; -public class CompactibleFreeListSpace extends CompactibleSpace { +public class CompactibleFreeListSpace extends CompactibleSpace implements LiveRegionsProvider { private static AddressField collectorField; private static AddressField indexedFreeListField; private static AddressField dictionaryField; @@ -93,10 +93,10 @@ } public long used0() { - List regions = getLiveRegions(); + List regions = getLiveRegions(); long usedSize = 0L; - for (Iterator itr = regions.iterator(); itr.hasNext();) { - MemRegion mr = (MemRegion) itr.next(); + for (Iterator itr = regions.iterator(); itr.hasNext();) { + MemRegion mr = itr.next(); usedSize += mr.byteSize(); } return usedSize; @@ -154,8 +154,9 @@ return addr; } - public List/**/ getLiveRegions() { - List res = new ArrayList(); // List + @Override + public List getLiveRegions() { + List res = new ArrayList<>(); VM vm = VM.getVM(); Debugger dbg = vm.getDebugger(); ObjectHeap heap = vm.getObjectHeap(); --- old/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/cms/ConcurrentMarkSweepGeneration.java 2019-02-13 16:34:54.034271646 +0100 +++ new/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/cms/ConcurrentMarkSweepGeneration.java 2019-02-13 16:34:53.658271660 +0100 @@ -66,6 +66,9 @@ public void spaceIterate(SpaceClosure blk, boolean usedOnly) { blk.doSpace(cmsSpace()); } + public void liveRegionsIterate(LiveRegionsClosure closure) { + closure.doLiveRegions(cmsSpace()); + } public Generation.Name kind() { return Generation.Name.CONCURRENT_MARK_SWEEP; --- old/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/epsilon/EpsilonHeap.java 2019-02-13 16:34:54.546271629 +0100 +++ new/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/epsilon/EpsilonHeap.java 2019-02-13 16:34:54.166271642 +0100 @@ -81,6 +81,11 @@ } @Override + public void liveRegionsIterate(LiveRegionsClosure closure) { + closure.doLiveRegions(space()); + } + + @Override public void printOn(PrintStream tty) { MemRegion mr = reservedRegion(); tty.println("Epsilon heap"); --- old/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/g1/G1CollectedHeap.java 2019-02-13 16:34:55.054271611 +0100 +++ new/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/g1/G1CollectedHeap.java 2019-02-13 16:34:54.670271624 +0100 @@ -32,8 +32,9 @@ import sun.jvm.hotspot.debugger.Address; import sun.jvm.hotspot.gc.shared.CollectedHeap; import sun.jvm.hotspot.gc.shared.CollectedHeapName; -import sun.jvm.hotspot.gc.shared.SpaceClosure; +import sun.jvm.hotspot.gc.shared.LiveRegionsClosure; import sun.jvm.hotspot.gc.shared.PrintRegionClosure; +import sun.jvm.hotspot.gc.shared.SpaceClosure; import sun.jvm.hotspot.memory.MemRegion; import sun.jvm.hotspot.runtime.VM; import sun.jvm.hotspot.runtime.VMObjectFactory; @@ -138,6 +139,15 @@ } @Override + public void liveRegionsIterate(LiveRegionsClosure closure) { + Iterator iter = heapRegionIterator(); + while (iter.hasNext()) { + HeapRegion hr = iter.next(); + closure.doLiveRegions(hr); + } + } + + @Override public void printOn(PrintStream tty) { MemRegion mr = reservedRegion(); --- old/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/g1/HeapRegion.java 2019-02-13 16:34:55.558271593 +0100 +++ new/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/g1/HeapRegion.java 2019-02-13 16:34:55.186271606 +0100 @@ -32,6 +32,7 @@ import sun.jvm.hotspot.debugger.Address; import sun.jvm.hotspot.debugger.OopHandle; import sun.jvm.hotspot.gc.shared.CompactibleSpace; +import sun.jvm.hotspot.gc.shared.LiveRegionsProvider; import sun.jvm.hotspot.memory.MemRegion; import sun.jvm.hotspot.runtime.VM; import sun.jvm.hotspot.runtime.VMObjectFactory; @@ -43,7 +44,7 @@ // Mirror class for HeapRegion. Currently we don't actually include // any of its fields but only iterate over it. -public class HeapRegion extends CompactibleSpace { +public class HeapRegion extends CompactibleSpace implements LiveRegionsProvider { // static int GrainBytes; static private CIntegerField grainBytesField; static private AddressField topField; @@ -86,8 +87,8 @@ } @Override - public List getLiveRegions() { - List res = new ArrayList(); + public List getLiveRegions() { + List res = new ArrayList<>(); res.add(new MemRegion(bottom(), top())); return res; } --- old/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/parallel/ImmutableSpace.java 2019-02-13 16:34:56.050271576 +0100 +++ new/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/parallel/ImmutableSpace.java 2019-02-13 16:34:55.678271589 +0100 @@ -73,7 +73,7 @@ } /** returns all MemRegions where live objects are */ - public abstract List/**/ getLiveRegions(); + public abstract List getLiveRegions(); /** Returned value is in bytes */ public long capacity() { return end().minus(bottom()); } --- old/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/parallel/MutableSpace.java 2019-02-13 16:34:56.526271560 +0100 +++ new/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/parallel/MutableSpace.java 2019-02-13 16:34:56.158271572 +0100 @@ -62,8 +62,8 @@ } /** returns all MemRegions where live objects are */ - public List/**/ getLiveRegions() { - List res = new ArrayList(); + public List getLiveRegions() { + List res = new ArrayList<>(); res.add(new MemRegion(bottom(), top())); return res; } --- old/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/parallel/ParallelScavengeHeap.java 2019-02-13 16:34:56.998271543 +0100 +++ new/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/parallel/ParallelScavengeHeap.java 2019-02-13 16:34:56.614271557 +0100 @@ -29,6 +29,7 @@ import sun.jvm.hotspot.debugger.*; import sun.jvm.hotspot.gc.shared.*; +import sun.jvm.hotspot.memory.MemRegion; import sun.jvm.hotspot.runtime.*; import sun.jvm.hotspot.types.*; @@ -88,6 +89,35 @@ return CollectedHeapName.PARALLEL; } + // Simple wrapper to provide toString() usable for debugging. + private class LiveRegionProviderImpl implements LiveRegionsProvider { + private String name; + private MutableSpace space; + + public LiveRegionProviderImpl(String name, MutableSpace space) { + this.name = name; + this.space = space; + } + + @Override + public List getLiveRegions() { + return space.getLiveRegions(); + } + @Override + public String toString() { + return name; + } + } + + public void liveRegionsIterate(LiveRegionsClosure closure) { + // Add eden space + closure.doLiveRegions(new LiveRegionProviderImpl("eden", youngGen().edenSpace())); + // Add from-space but not to-space + closure.doLiveRegions(new LiveRegionProviderImpl("from", youngGen().fromSpace())); + + closure.doLiveRegions(new LiveRegionProviderImpl("old ", oldGen().objectSpace())); + } + public void printOn(PrintStream tty) { tty.print("ParallelScavengeHeap [ "); youngGen().printOn(tty); --- old/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/serial/DefNewGeneration.java 2019-02-13 16:34:57.470271527 +0100 +++ new/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/serial/DefNewGeneration.java 2019-02-13 16:34:57.090271540 +0100 @@ -94,6 +94,11 @@ } } + public void liveRegionsIterate(LiveRegionsClosure closure) { + closure.doLiveRegions(eden()); + closure.doLiveRegions(from()); + } + public void printOn(PrintStream tty) { tty.print(" eden"); eden().printOn(tty); --- old/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/serial/TenuredGeneration.java 2019-02-13 16:34:57.958271510 +0100 +++ new/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/serial/TenuredGeneration.java 2019-02-13 16:34:57.582271523 +0100 @@ -76,6 +76,10 @@ blk.doSpace(theSpace()); } + public void liveRegionsIterate(LiveRegionsClosure closure) { + closure.doLiveRegions(theSpace()); + } + public void printOn(PrintStream tty) { tty.print(" old "); theSpace().printOn(tty); --- old/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/shared/CollectedHeap.java 2019-02-13 16:34:58.442271493 +0100 +++ new/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/shared/CollectedHeap.java 2019-02-13 16:34:58.066271506 +0100 @@ -28,6 +28,7 @@ import java.util.*; import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.gc.shared.*; import sun.jvm.hotspot.memory.*; import sun.jvm.hotspot.runtime.*; import sun.jvm.hotspot.types.*; @@ -77,6 +78,8 @@ public abstract CollectedHeapName kind(); + public abstract void liveRegionsIterate(LiveRegionsClosure closure); + public String oopAddressDescription(OopHandle handle) { return handle.toString(); } --- old/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/shared/ContiguousSpace.java 2019-02-13 16:34:58.938271476 +0100 +++ new/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/shared/ContiguousSpace.java 2019-02-13 16:34:58.554271489 +0100 @@ -32,7 +32,7 @@ import sun.jvm.hotspot.runtime.*; import sun.jvm.hotspot.types.*; -public class ContiguousSpace extends CompactibleSpace { +public class ContiguousSpace extends CompactibleSpace implements LiveRegionsProvider { private static AddressField topField; static { @@ -79,8 +79,8 @@ } /** Returns regions of Space where live objects live */ - public List/**/ getLiveRegions() { - List res = new ArrayList(); + public List getLiveRegions() { + List res = new ArrayList<>(); res.add(new MemRegion(bottom(), top())); return res; } --- old/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/shared/GenCollectedHeap.java 2019-02-13 16:34:59.446271458 +0100 +++ new/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/shared/GenCollectedHeap.java 2019-02-13 16:34:59.062271471 +0100 @@ -28,6 +28,7 @@ import java.util.*; import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.gc.shared.*; import sun.jvm.hotspot.runtime.*; import sun.jvm.hotspot.types.*; import sun.jvm.hotspot.utilities.*; @@ -134,6 +135,14 @@ } } + public void liveRegionsIterate(LiveRegionsClosure closure) { + // Run through all generations, obtaining bottom-top pairs. + for (int i = 0; i < nGens(); i++) { + Generation gen = getGen(i); + gen.liveRegionsIterate(closure); + } + } + public void printOn(PrintStream tty) { for (int i = 0; i < nGens(); i++) { tty.print("Gen " + i + ": "); --- old/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/shared/Generation.java 2019-02-13 16:34:59.954271440 +0100 +++ new/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/shared/Generation.java 2019-02-13 16:34:59.566271454 +0100 @@ -184,6 +184,7 @@ /** Iteration - do not use for time critical operations */ public abstract void spaceIterate(SpaceClosure blk, boolean usedOnly); + public abstract void liveRegionsIterate(LiveRegionsClosure closure); public void print() { printOn(System.out); } public abstract void printOn(PrintStream tty); --- old/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/shared/GenerationFactory.java 2019-02-13 16:35:00.462271423 +0100 +++ new/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/shared/GenerationFactory.java 2019-02-13 16:35:00.086271436 +0100 @@ -65,6 +65,8 @@ } public void spaceIterate(SpaceClosure blk, boolean usedOnly) { } + public void liveRegionsIterate(LiveRegionsClosure closure) { + } public void printOn(java.io.PrintStream tty) { tty.println("unknown subtype of Generation @ " + getAddress() + " (" + virtualSpace().low() + "," + virtualSpace().high() + ")"); --- old/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/shared/Space.java 2019-02-13 16:35:00.958271405 +0100 +++ new/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/shared/Space.java 2019-02-13 16:35:00.582271418 +0100 @@ -89,9 +89,6 @@ return handle.addOffsetToAsOopHandle(size); } - /** returns all MemRegions where live objects are */ - public abstract List/**/ getLiveRegions(); - /** Returned value is in bytes */ public long capacity() { return end().minus(bottom()); } /** Returned value is in bytes */ --- old/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/shenandoah/ShenandoahHeap.java 2019-02-13 16:35:01.462271388 +0100 +++ new/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/shenandoah/ShenandoahHeap.java 2019-02-13 16:35:01.086271401 +0100 @@ -25,6 +25,7 @@ import sun.jvm.hotspot.gc.shared.CollectedHeap; import sun.jvm.hotspot.gc.shared.CollectedHeapName; +import sun.jvm.hotspot.gc.shared.LiveRegionsClosure; import sun.jvm.hotspot.debugger.Address; import sun.jvm.hotspot.runtime.VM; import sun.jvm.hotspot.types.Type; @@ -78,6 +79,12 @@ } @Override + public void liveRegionsIterate(LiveRegionsClosure closure) { + // Operation (currently) not supported with Shenandoah GC. + System.err.println("Warning: Operation not supported with Shenandoah GC"); + } + + @Override public void printOn(PrintStream tty) { MemRegion mr = reservedRegion(); tty.print("Shenandoah heap"); --- old/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/z/ZAddress.java 2019-02-13 16:35:01.950271371 +0100 +++ new/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/z/ZAddress.java 2019-02-13 16:35:01.562271384 +0100 @@ -61,7 +61,7 @@ value |= ZGlobals.ZAddressSpaceStart; } - return ZOop.to_address(value); + return ZUtils.longToAddress(value); } static Address good(Address value) { --- old/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/z/ZAddressRangeMapForPageTable.java 2019-02-13 16:35:02.454271353 +0100 +++ new/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/z/ZAddressRangeMapForPageTable.java 2019-02-13 16:35:02.078271366 +0100 @@ -54,15 +54,38 @@ return mapField.getValue(addr); } + public long size() { + return ZGlobals.ZAddressOffsetMax >> AddressRangeShift; + } + private long index_for_addr(Address addr) { long index = ZAddress.offset(addr) >> AddressRangeShift; return index; } + Address at(long index) { + return map().getAddressAt(index * VM.getVM().getBytesPerLong()); + } + Address get(Address addr) { long index = index_for_addr(addr); + return at(index); + } - return map().getAddressAt(index * VM.getVM().getBytesPerLong()); + public class Iterator { + private long next = 0; + + boolean hasNext() { + return next < size(); + } + + Address next() { + if (next >= size()) { + throw new RuntimeException("OOIBE"); + } + + return at(next++); + } } } --- old/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/z/ZCollectedHeap.java 2019-02-13 16:35:02.910271337 +0100 +++ new/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/z/ZCollectedHeap.java 2019-02-13 16:35:02.542271350 +0100 @@ -25,11 +25,13 @@ package sun.jvm.hotspot.gc.z; import java.io.PrintStream; +import java.util.Iterator; import sun.jvm.hotspot.debugger.Address; import sun.jvm.hotspot.debugger.OopHandle; import sun.jvm.hotspot.gc.shared.CollectedHeap; import sun.jvm.hotspot.gc.shared.CollectedHeapName; +import sun.jvm.hotspot.gc.shared.LiveRegionsClosure; import sun.jvm.hotspot.runtime.VM; import sun.jvm.hotspot.runtime.VMObjectFactory; import sun.jvm.hotspot.types.Type; @@ -39,7 +41,6 @@ // Mirror class for ZCollectedHeap. public class ZCollectedHeap extends CollectedHeap { - private static long zHeapFieldOffset; static { @@ -119,6 +120,15 @@ } } + @Override + public void liveRegionsIterate(LiveRegionsClosure closure) { + Iterator iter = heap().pageTable().activePagesIterator(); + while (iter.hasNext()) { + ZPage page = iter.next(); + closure.doLiveRegions(page); + } + } + @Override public BitMapInterface createBitMap(long size) { // Ignores the size --- old/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/z/ZExternalBitMap.java 2019-02-13 16:35:03.418271320 +0100 +++ new/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/z/ZExternalBitMap.java 2019-02-13 16:35:03.034271333 +0100 @@ -23,7 +23,7 @@ throw new RuntimeException("Not a Z offset: " + zOffset); } - ZPage page = pageTable.get(ZOop.to_address(zOffset)); + ZPage page = pageTable.get(ZUtils.longToAddress(zOffset)); if (page == null) { throw new RuntimeException("Address not in pageTable: " + zOffset); } --- old/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/z/ZGlobals.java 2019-02-13 16:35:03.914271302 +0100 +++ new/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/z/ZGlobals.java 2019-02-13 16:35:03.542271315 +0100 @@ -54,6 +54,7 @@ // Pointer part of address public static long ZAddressOffsetBits; public static long ZAddressOffsetMask; + public static long ZAddressOffsetMax; // Address space start/end/size public static long ZAddressSpaceStart; @@ -84,6 +85,7 @@ ZAddressOffsetBits = db.lookupLongConstant("ZAddressOffsetBits").longValue(); ZAddressOffsetMask = db.lookupLongConstant("ZAddressOffsetMask").longValue(); + ZAddressOffsetMax = db.lookupLongConstant("ZAddressOffsetMax").longValue(); ZAddressSpaceStart = db.lookupLongConstant("ZAddressSpaceStart").longValue(); } @@ -96,6 +98,10 @@ return instance().ZGlobalPhase(); } + public static int ZGlobalSeqNum() { + return instance().ZGlobalSeqNum(); + } + public static long ZAddressGoodMask() { return instance().ZAddressGoodMask(); } --- old/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/z/ZGlobalsForVMStructs.java 2019-02-13 16:35:04.414271285 +0100 +++ new/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/z/ZGlobalsForVMStructs.java 2019-02-13 16:35:04.030271298 +0100 @@ -33,6 +33,7 @@ class ZGlobalsForVMStructs extends VMObject { private static AddressField ZGlobalPhaseField; + private static AddressField ZGlobalSeqNumField; private static AddressField ZAddressGoodMaskField; private static AddressField ZAddressBadMaskField; private static AddressField ZAddressWeakBadMaskField; @@ -47,6 +48,7 @@ Type type = db.lookupType("ZGlobalsForVMStructs"); ZGlobalPhaseField = type.getAddressField("_ZGlobalPhase"); + ZGlobalSeqNumField = type.getAddressField("_ZGlobalSeqNum"); ZAddressGoodMaskField = type.getAddressField("_ZAddressGoodMask"); ZAddressBadMaskField = type.getAddressField("_ZAddressBadMask"); ZAddressWeakBadMaskField = type.getAddressField("_ZAddressWeakBadMask"); @@ -62,6 +64,10 @@ return ZGlobalPhaseField.getValue(addr).getJIntAt(0); } + int ZGlobalSeqNum() { + return ZGlobalSeqNumField.getValue(addr).getJIntAt(0); + } + long ZAddressGoodMask() { return ZAddressGoodMaskField.getValue(addr).getJLongAt(0); } --- old/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/z/ZOop.java 2019-02-13 16:35:04.934271267 +0100 +++ new/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/z/ZOop.java 2019-02-13 16:35:04.546271280 +0100 @@ -26,23 +26,9 @@ import sun.jvm.hotspot.debugger.Address; import sun.jvm.hotspot.debugger.OopHandle; -import sun.jvm.hotspot.runtime.VM; class ZOop { - private static final long MSB = ~0L ^ (~0L >>> 1); - - private static Address msbAddress() { - return VM.getVM().getUniverse().heap().start().orWithMask(MSB).andWithMask(MSB); - } - - static Address to_address(long value) { - // If the value of an Address becomes 0, null is returned instead of an Address. - // Start with a one-bit address and as a last step, remove that bit. - Address oneAddress = msbAddress(); - return oneAddress.orWithMask(value).xorWithMask(ZAddress.as_long(oneAddress)); - } - static Address to_address(OopHandle oop) { - return to_address(ZAddress.as_long(oop)); + return ZUtils.longToAddress(ZAddress.as_long(oop)); } } --- old/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/z/ZPage.java 2019-02-13 16:35:05.438271249 +0100 +++ new/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/z/ZPage.java 2019-02-13 16:35:05.062271262 +0100 @@ -24,17 +24,29 @@ 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 { @@ -45,7 +57,10 @@ 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(); } @@ -57,12 +72,40 @@ 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() { @@ -98,7 +141,6 @@ return ZAddress.good(from); } - long object_alignment_shift() { if (type() == ZGlobals.ZPageTypeSmall) { return ZGlobals.ZObjectAlignmentSmallShift(); @@ -109,4 +151,94 @@ 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 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 getLiveRegions() { + List 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; + } } --- old/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/z/ZPageTable.java 2019-02-13 16:35:05.958271231 +0100 +++ new/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/z/ZPageTable.java 2019-02-13 16:35:05.570271245 +0100 @@ -24,6 +24,8 @@ package sun.jvm.hotspot.gc.z; +import java.util.Iterator; + import sun.jvm.hotspot.debugger.Address; import sun.jvm.hotspot.runtime.VM; import sun.jvm.hotspot.runtime.VMObject; @@ -63,4 +65,112 @@ boolean is_relocating(Address o) { return getEntry(o).relocating(); } + + private class ZPagesIterator implements Iterator { + private ZAddressRangeMapForPageTable.Iterator mapIter; + private ZPage next; + + ZPagesIterator() { + mapIter = map().new Iterator(); + positionToNext(); + } + + private ZPage positionToNext() { + ZPage current = next; + + // Find next + ZPage found = null; + while (mapIter.hasNext()) { + ZPageTableEntry entry = new ZPageTableEntry(mapIter.next()); + if (!entry.isEmpty()) { + ZPage page = entry.page(); + // Medium pages have repeated entries for all covered slots, + // therefore we need to compare against the current page. + if (page != null && !page.equals(current)) { + found = page; + break; + } + } + } + + next = found; + + return current; + } + + @Override + public boolean hasNext() { + return next != null; + } + + @Override + public ZPage next() { + return positionToNext(); + } + + @Override + public void remove() { + /* not supported */ + } + } + + abstract class ZPageFilter { + public abstract boolean accept(ZPage page); + } + + class ZPagesFilteredIterator implements Iterator { + private ZPage next; + private ZPagesIterator iter = new ZPagesIterator(); + private ZPageFilter filter; + + ZPagesFilteredIterator(ZPageFilter filter) { + this.filter = filter; + positionToNext(); + } + + public ZPage positionToNext() { + ZPage current = next; + + // Find next + ZPage found = null; + while (iter.hasNext()) { + ZPage page = iter.next(); + if (filter.accept(page)) { + found = page; + break; + } + } + + next = found; + + return current; + } + + @Override + public boolean hasNext() { + return next != null; + } + + @Override + public ZPage next() { + return positionToNext(); + } + + @Override + public void remove() { + /* not supported */ + } + } + + public Iterator iterator() { + return new ZPagesIterator(); + } + + public Iterator activePagesIterator() { + return new ZPagesFilteredIterator(new ZPageFilter() { + public boolean accept(ZPage page) { + return page.is_active(); + } + }); + } } --- old/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/z/ZPageTableEntry.java 2019-02-13 16:35:06.482271213 +0100 +++ new/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/z/ZPageTableEntry.java 2019-02-13 16:35:06.082271227 +0100 @@ -35,10 +35,18 @@ } ZPage page() { - return (ZPage)VMObjectFactory.newObject(ZPage.class, entry.andWithMask(~1L)); + return (ZPage)VMObjectFactory.newObject(ZPage.class, zPageBits()); + } + + private Address zPageBits() { + return entry.andWithMask(~1L); } boolean relocating() { return (entry.asLongValue() & 1) == 1; } + + boolean isEmpty() { + return entry == null || zPageBits() == null; + } } --- old/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/ObjectHeap.java 2019-02-13 16:35:06.990271195 +0100 +++ new/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/ObjectHeap.java 2019-02-13 16:35:06.606271209 +0100 @@ -304,87 +304,48 @@ visitor.epilogue(); } - private void addLiveRegions(String name, List input, List output) { - for (Iterator itr = input.iterator(); itr.hasNext();) { - MemRegion reg = (MemRegion) itr.next(); + private static class LiveRegionsCollector implements LiveRegionsClosure { + LiveRegionsCollector(List
l) { + liveRegions = l; + } + + @Override + public void doLiveRegions(LiveRegionsProvider lrp) { + for (MemRegion reg : lrp.getLiveRegions()) { Address top = reg.end(); Address bottom = reg.start(); if (Assert.ASSERTS_ENABLED) { - Assert.that(top != null, "top address in a live region should not be null"); + Assert.that(top != null, "top address in a live region should not be null"); } if (Assert.ASSERTS_ENABLED) { - Assert.that(bottom != null, "bottom address in a live region should not be null"); + Assert.that(bottom != null, "bottom address in a live region should not be null"); } - output.add(top); - output.add(bottom); + liveRegions.add(top); + liveRegions.add(bottom); if (DEBUG) { - System.err.println("Live region: " + name + ": " + bottom + ", " + top); - } - } + System.err.println("Live region: " + lrp + ": " + bottom + ", " + top); + } + } } - private class LiveRegionsCollector implements SpaceClosure { - LiveRegionsCollector(List l) { - liveRegions = l; - } - - public void doSpace(Space s) { - addLiveRegions(s.toString(), s.getLiveRegions(), liveRegions); - } - private List liveRegions; + private List
liveRegions; } // Returns a List
where the addresses come in pairs. These // designate the live regions of the heap. - private List collectLiveRegions() { + private List
collectLiveRegions() { // We want to iterate through all live portions of the heap, but // do not want to abort the heap traversal prematurely if we find // a problem (like an allocated but uninitialized object at the // top of a generation). To do this we enumerate all generations' // bottom and top regions, and factor in TLABs if necessary. - // List
. Addresses come in pairs. - List liveRegions = new ArrayList(); + // Addresses come in pairs. + List
liveRegions = new ArrayList<>(); LiveRegionsCollector lrc = new LiveRegionsCollector(liveRegions); CollectedHeap heap = VM.getVM().getUniverse().heap(); - - if (heap instanceof GenCollectedHeap) { - GenCollectedHeap genHeap = (GenCollectedHeap) heap; - // Run through all generations, obtaining bottom-top pairs. - for (int i = 0; i < genHeap.nGens(); i++) { - Generation gen = genHeap.getGen(i); - gen.spaceIterate(lrc, true); - } - } else if (heap instanceof ParallelScavengeHeap) { - ParallelScavengeHeap psh = (ParallelScavengeHeap) heap; - PSYoungGen youngGen = psh.youngGen(); - // Add eden space - addLiveRegions("eden", youngGen.edenSpace().getLiveRegions(), liveRegions); - // Add from-space but not to-space - addLiveRegions("from", youngGen.fromSpace().getLiveRegions(), liveRegions); - PSOldGen oldGen = psh.oldGen(); - addLiveRegions("old ", oldGen.objectSpace().getLiveRegions(), liveRegions); - } else if (heap instanceof G1CollectedHeap) { - G1CollectedHeap g1h = (G1CollectedHeap) heap; - g1h.heapRegionIterate(lrc); - } else if (heap instanceof ShenandoahHeap) { - // Operation (currently) not supported with Shenandoah GC. Print - // a warning and leave the list of live regions empty. - System.err.println("Warning: Operation not supported with Shenandoah GC"); - } else if (heap instanceof ZCollectedHeap) { - // Operation (currently) not supported with ZGC. Print - // a warning and leave the list of live regions empty. - System.err.println("Warning: Operation not supported with ZGC"); - } else if (heap instanceof EpsilonHeap) { - EpsilonHeap eh = (EpsilonHeap) heap; - liveRegions.add(eh.space().top()); - liveRegions.add(eh.space().bottom()); - } else { - if (Assert.ASSERTS_ENABLED) { - Assert.that(false, "Unexpected CollectedHeap type: " + heap.getClass().getName()); - } - } + heap.liveRegionsIterate(lrc); // If UseTLAB is enabled, snip out regions associated with TLABs' // dead regions. Note that TLABs can be present in any generation. @@ -440,11 +401,9 @@ return liveRegions; } - private void sortLiveRegions(List liveRegions) { - Collections.sort(liveRegions, new Comparator() { - public int compare(Object o1, Object o2) { - Address a1 = (Address) o1; - Address a2 = (Address) o2; + private void sortLiveRegions(List
liveRegions) { + Collections.sort(liveRegions, new Comparator
() { + public int compare(Address a1, Address a2) { if (AddressOps.lt(a1, a2)) { return -1; } else if (AddressOps.gt(a1, a2)) { --- /dev/null 2019-02-13 12:45:42.534750667 +0100 +++ new/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/shared/LiveRegionsClosure.java 2019-02-13 16:35:07.086271192 +0100 @@ -0,0 +1,29 @@ +/* + * Copyright (c) 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package sun.jvm.hotspot.gc.shared; + +public interface LiveRegionsClosure { + public void doLiveRegions(LiveRegionsProvider lrp); +} --- /dev/null 2019-02-13 12:45:42.534750667 +0100 +++ new/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/shared/LiveRegionsProvider.java 2019-02-13 16:35:07.594271174 +0100 @@ -0,0 +1,33 @@ +/* + * Copyright (c) 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package sun.jvm.hotspot.gc.shared; + +import java.util.List; + +import sun.jvm.hotspot.memory.MemRegion; + +public interface LiveRegionsProvider { + public List getLiveRegions(); +} --- /dev/null 2019-02-13 12:45:42.534750667 +0100 +++ new/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/z/ZUtils.java 2019-02-13 16:35:08.102271156 +0100 @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2018, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package sun.jvm.hotspot.gc.z; + +import sun.jvm.hotspot.debugger.Address; +import sun.jvm.hotspot.runtime.VM; + +class ZUtils { + private static final long MSB = ~0L ^ (~0L >>> 1); + + private static Address msbAddress() { + return VM.getVM().getUniverse().heap().start().orWithMask(MSB).andWithMask(MSB); + } + + static Address longToAddress(long value) { + // If the value of an Address becomes 0, null is returned instead of an Address. + // Start with a one-bit address and as a last step, remove that bit. + Address oneAddress = msbAddress(); + return oneAddress.orWithMask(value).xorWithMask(ZAddress.as_long(oneAddress)); + } +}