8218922: SA: Enable best-effort implementation of live regions iteration for ZGC
Reviewed-by: eosterlund, ysuenaga
--- a/src/hotspot/share/gc/z/vmStructs_z.cpp Tue Feb 19 10:03:41 2019 +0100
+++ b/src/hotspot/share/gc/z/vmStructs_z.cpp Tue Feb 19 10:04:28 2019 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 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
@@ -26,6 +26,7 @@
ZGlobalsForVMStructs::ZGlobalsForVMStructs() :
_ZGlobalPhase(&ZGlobalPhase),
+ _ZGlobalSeqNum(&ZGlobalSeqNum),
_ZAddressGoodMask(&ZAddressGoodMask),
_ZAddressBadMask(&ZAddressBadMask),
_ZAddressWeakBadMask(&ZAddressWeakBadMask),
--- a/src/hotspot/share/gc/z/vmStructs_z.hpp Tue Feb 19 10:03:41 2019 +0100
+++ b/src/hotspot/share/gc/z/vmStructs_z.hpp Tue Feb 19 10:04:28 2019 +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) \
--- a/src/hotspot/share/gc/z/zCollectedHeap.cpp Tue Feb 19 10:03:41 2019 +0100
+++ b/src/hotspot/share/gc/z/zCollectedHeap.cpp Tue Feb 19 10:04:28 2019 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -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);
--- a/src/hotspot/share/gc/z/zCollectedHeap.hpp Tue Feb 19 10:03:41 2019 +0100
+++ b/src/hotspot/share/gc/z/zCollectedHeap.hpp Tue Feb 19 10:04:28 2019 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -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,
--- a/src/hotspot/share/gc/z/zMark.cpp Tue Feb 19 10:03:41 2019 +0100
+++ b/src/hotspot/share/gc/z/zMark.cpp Tue Feb 19 10:04:28 2019 +0100
@@ -119,6 +119,11 @@
}
class ZMarkRootsIteratorClosure : public ZRootsIteratorClosure {
+private:
+ static void fixup_address(HeapWord** p) {
+ *p = (HeapWord*)ZAddress::good_or_null((uintptr_t)*p);
+ }
+
public:
ZMarkRootsIteratorClosure() {
ZStatTLAB::reset();
@@ -136,6 +141,7 @@
// Retire TLAB
if (UseTLAB && thread->is_Java_thread()) {
+ thread->tlab().addresses_do(fixup_address);
thread->tlab().retire(ZStatTLAB::get());
thread->tlab().resize();
}
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/z/ZAddress.java Tue Feb 19 10:03:41 2019 +0100
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/z/ZAddress.java Tue Feb 19 10:04:28 2019 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 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
@@ -61,7 +61,7 @@
value |= ZGlobals.ZAddressSpaceStart;
}
- return ZOop.to_address(value);
+ return ZUtils.longToAddress(value);
}
static Address good(Address value) {
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/z/ZAddressRangeMapForPageTable.java Tue Feb 19 10:03:41 2019 +0100
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/z/ZAddressRangeMapForPageTable.java Tue Feb 19 10:04:28 2019 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 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
@@ -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++);
+ }
}
}
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/z/ZCollectedHeap.java Tue Feb 19 10:03:41 2019 +0100
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/z/ZCollectedHeap.java Tue Feb 19 10:04:28 2019 +0100
@@ -25,6 +25,7 @@
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;
@@ -121,9 +122,11 @@
@Override
public void liveRegionsIterate(LiveRegionsClosure closure) {
- // 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");
+ Iterator<ZPage> iter = heap().pageTable().activePagesIterator();
+ while (iter.hasNext()) {
+ ZPage page = iter.next();
+ closure.doLiveRegions(page);
+ }
}
@Override
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/z/ZExternalBitMap.java Tue Feb 19 10:03:41 2019 +0100
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/z/ZExternalBitMap.java Tue Feb 19 10:04:28 2019 +0100
@@ -47,7 +47,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);
}
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/z/ZGlobals.java Tue Feb 19 10:03:41 2019 +0100
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/z/ZGlobals.java Tue Feb 19 10:04:28 2019 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 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
@@ -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();
}
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/z/ZGlobalsForVMStructs.java Tue Feb 19 10:03:41 2019 +0100
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/z/ZGlobalsForVMStructs.java Tue Feb 19 10:04:28 2019 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 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
@@ -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);
}
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/z/ZOop.java Tue Feb 19 10:03:41 2019 +0100
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/z/ZOop.java Tue Feb 19 10:04:28 2019 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 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
@@ -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));
}
}
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/z/ZPage.java Tue Feb 19 10:03:41 2019 +0100
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/z/ZPage.java Tue Feb 19 10:04:28 2019 +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<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;
+ }
}
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/z/ZPageTable.java Tue Feb 19 10:03:41 2019 +0100
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/z/ZPageTable.java Tue Feb 19 10:04:28 2019 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 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
@@ -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<ZPage> {
+ 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<ZPage> {
+ 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<ZPage> iterator() {
+ return new ZPagesIterator();
+ }
+
+ public Iterator<ZPage> activePagesIterator() {
+ return new ZPagesFilteredIterator(new ZPageFilter() {
+ public boolean accept(ZPage page) {
+ return page.is_active();
+ }
+ });
+ }
}
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/z/ZPageTableEntry.java Tue Feb 19 10:03:41 2019 +0100
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/z/ZPageTableEntry.java Tue Feb 19 10:04:28 2019 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 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
@@ -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;
+ }
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/z/ZUtils.java Tue Feb 19 10:04:28 2019 +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));
+ }
+}