--- old/src/hotspot/share/gc/z/vmStructs_z.cpp 2019-02-15 20:10:11.927532030 +0100 +++ new/src/hotspot/share/gc/z/vmStructs_z.cpp 2019-02-15 20:10:11.359532034 +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), --- old/src/hotspot/share/gc/z/vmStructs_z.hpp 2019-02-15 20:10:12.587532025 +0100 +++ new/src/hotspot/share/gc/z/vmStructs_z.hpp 2019-02-15 20:10:12.059532029 +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-15 20:10:13.247532020 +0100 +++ new/src/hotspot/share/gc/z/zCollectedHeap.cpp 2019-02-15 20:10:12.715532024 +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); --- old/src/hotspot/share/gc/z/zCollectedHeap.hpp 2019-02-15 20:10:13.967532015 +0100 +++ new/src/hotspot/share/gc/z/zCollectedHeap.hpp 2019-02-15 20:10:13.379532019 +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, --- old/src/hotspot/share/gc/z/zMark.cpp 2019-02-15 20:10:14.623532010 +0100 +++ new/src/hotspot/share/gc/z/zMark.cpp 2019-02-15 20:10:14.095532014 +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(); } --- old/src/hotspot/share/oops/oopHandle.hpp 2019-02-15 20:10:15.283532005 +0100 +++ new/src/hotspot/share/oops/oopHandle.hpp 2019-02-15 20:10:14.755532009 +0100 @@ -36,6 +36,7 @@ // future uses for read barriers. class OopHandle { + friend class VMStructs; private: oop* _obj; --- old/src/hotspot/share/runtime/vmStructs.cpp 2019-02-15 20:10:15.947532000 +0100 +++ new/src/hotspot/share/runtime/vmStructs.cpp 2019-02-15 20:10:15.415532004 +0100 @@ -332,6 +332,7 @@ unchecked_nonstatic_field(Symbol, _body, sizeof(u1)) /* NOTE: no type */ \ nonstatic_field(Symbol, _body[0], u1) \ nonstatic_field(TypeArrayKlass, _max_length, jint) \ + nonstatic_field(OopHandle, _obj, oop*) \ \ /***********************/ \ /* Constant Pool Cache */ \ @@ -1299,7 +1300,8 @@ declare_oop_type(oop) \ declare_oop_type(narrowOop) \ declare_oop_type(typeArrayOop) \ - declare_oop_type(OopHandle) \ + \ + declare_toplevel_type(OopHandle) \ \ /*************************************/ \ /* MethodOop-related data structures */ \ --- old/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/classfile/ClassLoaderData.java 2019-02-15 20:10:16.659531995 +0100 +++ new/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/classfile/ClassLoaderData.java 2019-02-15 20:10:16.127531999 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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,7 +24,6 @@ package sun.jvm.hotspot.classfile; -import java.io.PrintStream; import sun.jvm.hotspot.debugger.*; import sun.jvm.hotspot.memory.*; import sun.jvm.hotspot.runtime.*; @@ -42,14 +41,14 @@ private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { Type type = db.lookupType("ClassLoaderData"); - classLoaderField = type.getAddressField("_class_loader"); + classLoaderFieldOffset = type.getAddressField("_class_loader").getOffset(); nextField = type.getAddressField("_next"); klassesField = new MetadataField(type.getAddressField("_klasses"), 0); isUnsafeAnonymousField = new CIntField(type.getCIntegerField("_is_unsafe_anonymous"), 0); dictionaryField = type.getAddressField("_dictionary"); } - private static AddressField classLoaderField; + private static long classLoaderFieldOffset; private static AddressField nextField; private static MetadataField klassesField; private static CIntField isUnsafeAnonymousField; @@ -72,13 +71,9 @@ } public Oop getClassLoader() { - Address handle = classLoaderField.getValue(getAddress()); - if (handle != null) { - // Load through the handle - OopHandle refs = handle.getOopHandleAt(0); - return (Instance)VM.getVM().getObjectHeap().newOop(refs); - } - return null; + Address addr = getAddress().addOffsetTo(classLoaderFieldOffset); + VMOopHandle vmOopHandle = VMObjectFactory.newObject(VMOopHandle.class, addr); + return vmOopHandle.resolve(); } public boolean getisUnsafeAnonymous() { --- old/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/cms/CompactibleFreeListSpace.java 2019-02-15 20:10:17.311531990 +0100 +++ new/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/cms/CompactibleFreeListSpace.java 2019-02-15 20:10:16.787531994 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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,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-15 20:10:18.023531985 +0100 +++ new/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/cms/ConcurrentMarkSweepGeneration.java 2019-02-15 20:10:17.443531989 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -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-15 20:10:18.679531980 +0100 +++ new/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/epsilon/EpsilonHeap.java 2019-02-15 20:10:18.155531984 +0100 @@ -66,11 +66,26 @@ return CollectedHeapName.EPSILON; } + @Override + public long capacity() { + return space.capacity(); + } + + @Override + public long used() { + return space.used(); + } + public ContiguousSpace space() { return space; } @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-15 20:10:19.387531975 +0100 +++ new/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/g1/G1CollectedHeap.java 2019-02-15 20:10:18.811531979 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -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-15 20:10:20.095531969 +0100 +++ new/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/g1/HeapRegion.java 2019-02-15 20:10:19.523531974 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -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-15 20:10:20.751531965 +0100 +++ new/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/parallel/ImmutableSpace.java 2019-02-15 20:10:20.219531968 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -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-15 20:10:21.471531959 +0100 +++ new/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/parallel/MutableSpace.java 2019-02-15 20:10:20.879531964 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -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-15 20:10:22.119531954 +0100 +++ new/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/parallel/ParallelScavengeHeap.java 2019-02-15 20:10:21.591531958 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -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-15 20:10:22.815531949 +0100 +++ new/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/serial/DefNewGeneration.java 2019-02-15 20:10:22.239531954 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -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-15 20:10:23.471531944 +0100 +++ new/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/serial/TenuredGeneration.java 2019-02-15 20:10:22.943531948 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -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-15 20:10:24.123531940 +0100 +++ new/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/shared/CollectedHeap.java 2019-02-15 20:10:23.595531944 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -28,9 +28,12 @@ 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.*; +import sun.jvm.hotspot.utilities.BitMapInterface; +import sun.jvm.hotspot.utilities.BitMapSegmented; public abstract class CollectedHeap extends VMObject { private static long reservedFieldOffset; @@ -58,8 +61,8 @@ return reservedRegion().start(); } - public long capacity() { return 0; } - public long used() { return 0; } + public abstract long capacity(); + public abstract long used(); public MemRegion reservedRegion() { return new MemRegion(addr.addOffsetTo(reservedFieldOffset)); @@ -75,6 +78,8 @@ public abstract CollectedHeapName kind(); + public abstract void liveRegionsIterate(LiveRegionsClosure closure); + public String oopAddressDescription(OopHandle handle) { return handle.toString(); } @@ -83,10 +88,18 @@ return handle.getOopHandleAt(offset); } + public OopHandle oop_load_in_native(Address addr) { + return addr.getOopHandleAt(0); + } + public void print() { printOn(System.out); } public void printOn(PrintStream tty) { MemRegion mr = reservedRegion(); tty.println("unknown subtype of CollectedHeap @ " + getAddress() + " (" + mr.start() + "," + mr.end() + ")"); } + + public BitMapInterface createBitMap(long bits) { + return new BitMapSegmented(bits); + } } --- old/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/shared/ContiguousSpace.java 2019-02-15 20:10:24.839531934 +0100 +++ new/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/shared/ContiguousSpace.java 2019-02-15 20:10:24.247531939 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -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-15 20:10:25.543531929 +0100 +++ new/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/shared/GenCollectedHeap.java 2019-02-15 20:10:24.971531933 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -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-15 20:10:26.191531924 +0100 +++ new/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/shared/Generation.java 2019-02-15 20:10:25.667531928 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -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-15 20:10:26.855531920 +0100 +++ new/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/shared/GenerationFactory.java 2019-02-15 20:10:26.327531923 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -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-15 20:10:27.531531915 +0100 +++ new/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/shared/Space.java 2019-02-15 20:10:26.979531919 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -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-15 20:10:28.243531909 +0100 +++ new/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/shenandoah/ShenandoahHeap.java 2019-02-15 20:10:27.659531914 +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; @@ -64,6 +65,11 @@ } @Override + public long capacity() { + return numOfRegions() * ShenandoahHeapRegion.regionSizeBytes(); + } + + @Override public long used() { return used.getValue(addr); } @@ -73,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-15 20:10:28.939531904 +0100 +++ new/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/z/ZAddress.java 2019-02-15 20:10:28.371531908 +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) { --- old/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/z/ZAddressRangeMapForPageTable.java 2019-02-15 20:10:29.659531899 +0100 +++ new/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/z/ZAddressRangeMapForPageTable.java 2019-02-15 20:10:29.067531903 +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++); + } } } --- old/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/z/ZCollectedHeap.java 2019-02-15 20:10:30.359531894 +0100 +++ new/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/z/ZCollectedHeap.java 2019-02-15 20:10:29.783531898 +0100 @@ -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 @@ -25,20 +25,22 @@ 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; import sun.jvm.hotspot.types.TypeDataBase; +import sun.jvm.hotspot.utilities.BitMapInterface; // Mirror class for ZCollectedHeap. public class ZCollectedHeap extends CollectedHeap { - private static long zHeapFieldOffset; static { @@ -70,11 +72,19 @@ super(addr); } - public OopHandle oop_load_at(OopHandle handle, long offset) { - assert(!VM.getVM().isCompressedOopsEnabled()); + @Override + public long capacity() { + return heap().capacity(); + } - Address oopAddress = handle.getAddressAt(offset); + @Override + public long used() { + return heap().used(); + } + + + private OopHandle oop_load_barrier(Address oopAddress) { oopAddress = ZBarrier.weak_barrier(oopAddress); if (oopAddress == null) { return null; @@ -83,6 +93,23 @@ return oopAddress.addOffsetToAsOopHandle(0); } + @Override + public OopHandle oop_load_at(OopHandle handle, long offset) { + assert(!VM.getVM().isCompressedOopsEnabled()); + + Address oopAddress = handle.getAddressAt(offset); + + return oop_load_barrier(oopAddress); + } + + // addr can be either in heap or in native + @Override + public OopHandle oop_load_in_native(Address addr) { + Address oopAddress = addr.getAddressAt(0); + + return oop_load_barrier(oopAddress); + } + public String oopAddressDescription(OopHandle handle) { Address origOop = ZOop.to_address(handle); Address loadBarrieredOop = ZBarrier.weak_barrier(origOop); @@ -92,4 +119,19 @@ return handle.toString(); } } + + @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 + return new ZExternalBitMap(this); + } } --- old/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/z/ZGlobals.java 2019-02-15 20:10:31.023531889 +0100 +++ new/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/z/ZGlobals.java 2019-02-15 20:10:30.495531893 +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(); } --- old/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/z/ZGlobalsForVMStructs.java 2019-02-15 20:10:31.675531884 +0100 +++ new/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/z/ZGlobalsForVMStructs.java 2019-02-15 20:10:31.147531888 +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); } --- old/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/z/ZOop.java 2019-02-15 20:10:32.315531879 +0100 +++ new/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/z/ZOop.java 2019-02-15 20:10:31.795531883 +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)); } } --- old/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/z/ZPage.java 2019-02-15 20:10:33.019531874 +0100 +++ new/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/z/ZPage.java 2019-02-15 20:10:32.447531878 +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,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,18 +72,50 @@ 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 long start() { + 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(); } + long size() { + return virtual().end() - virtual().start(); + } + Address forward_object(Address from) { // Lookup address in forwarding table long from_offset = ZAddress.offset(from); @@ -94,7 +141,6 @@ return ZAddress.good(from); } - long object_alignment_shift() { if (type() == ZGlobals.ZPageTypeSmall) { return ZGlobals.ZObjectAlignmentSmallShift(); @@ -105,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/ZPageAllocator.java 2019-02-15 20:10:33.731531869 +0100 +++ new/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/z/ZPageAllocator.java 2019-02-15 20:10:33.155531873 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 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 @@ -37,7 +37,7 @@ public class ZPageAllocator extends VMObject { - private static AddressField physicalField; + private static long physicalFieldOffset; private static CIntegerField usedField; static { @@ -47,12 +47,12 @@ static private synchronized void initialize(TypeDataBase db) { Type type = db.lookupType("ZPageAllocator"); - physicalField = type.getAddressField("_physical"); + physicalFieldOffset = type.getAddressField("_physical").getOffset(); usedField = type.getCIntegerField("_used"); } private ZPhysicalMemoryManager physical() { - Address physicalAddr = physicalField.getValue(addr); + Address physicalAddr = addr.addOffsetTo(physicalFieldOffset); return (ZPhysicalMemoryManager)VMObjectFactory.newObject(ZPhysicalMemoryManager.class, physicalAddr); } --- old/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/z/ZPageTable.java 2019-02-15 20:10:34.451531863 +0100 +++ new/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/z/ZPageTable.java 2019-02-15 20:10:33.863531868 +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 { + 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-15 20:10:35.111531859 +0100 +++ new/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/z/ZPageTableEntry.java 2019-02-15 20:10:34.579531863 +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; + } } --- old/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/Klass.java 2019-02-15 20:10:35.771531854 +0100 +++ new/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/Klass.java 2019-02-15 20:10:35.239531858 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -51,7 +51,7 @@ private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { Type type = db.lookupType("Klass"); - javaMirror = type.getAddressField("_java_mirror"); + javaMirrorFieldOffset = type.getField("_java_mirror").getOffset(); superField = new MetadataField(type.getAddressField("_super"), 0); layoutHelper = new IntField(type.getJIntField("_layout_helper"), 0); name = type.getAddressField("_name"); @@ -89,7 +89,7 @@ public boolean isArrayKlass() { return false; } // Fields - private static AddressField javaMirror; + private static long javaMirrorFieldOffset; private static MetadataField superField; private static IntField layoutHelper; private static AddressField name; @@ -101,23 +101,15 @@ private static CIntField vtableLen; private static AddressField classLoaderData; - private Address getValue(AddressField field) { - return addr.getAddressAt(field.getOffset()); - } - protected Symbol getSymbol(AddressField field) { return Symbol.create(addr.getAddressAt(field.getOffset())); } // Accessors for declared fields public Instance getJavaMirror() { - Address handle = javaMirror.getValue(getAddress()); - if (handle != null) { - // Load through the handle - OopHandle refs = handle.getOopHandleAt(0); - return (Instance)VM.getVM().getObjectHeap().newOop(refs); - } - return null; + Address addr = getAddress().addOffsetTo(javaMirrorFieldOffset); + VMOopHandle vmOopHandle = VMObjectFactory.newObject(VMOopHandle.class, addr); + return vmOopHandle.resolve(); } public Klass getSuper() { return (Klass) superField.getValue(this); } public Klass getJavaSuper() { return null; } --- old/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/ObjectHeap.java 2019-02-15 20:10:36.459531849 +0100 +++ new/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/ObjectHeap.java 2019-02-15 20:10:35.899531853 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -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)) { --- old/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/VMObjectFactory.java 2019-02-15 20:10:37.123531844 +0100 +++ new/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/VMObjectFactory.java 2019-02-15 20:10:36.599531848 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -45,14 +45,14 @@ */ public class VMObjectFactory { - public static Object newObject(Class clazz, Address addr) + public static T newObject(Class clazz, Address addr) throws ConstructionException { try { if (addr == null) { return null; } - Constructor c = clazz.getConstructor(new Class[] { + Constructor c = clazz.getConstructor(new Class[] { Address.class }); return c.newInstance(new Object[] { addr }); --- old/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/HeapHprofBinWriter.java 2019-02-15 20:10:37.831531839 +0100 +++ new/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/HeapHprofBinWriter.java 2019-02-15 20:10:37.247531843 +0100 @@ -390,9 +390,6 @@ public synchronized void write(String fileName) throws IOException { VM vm = VM.getVM(); - if (vm.getUniverse().heap() instanceof ZCollectedHeap) { - throw new RuntimeException("This operation is not supported with ZGC."); - } // open file stream and create buffered data output stream fos = new FileOutputStream(fileName); --- old/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/MarkBits.java 2019-02-15 20:10:38.507531834 +0100 +++ new/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/MarkBits.java 2019-02-15 20:10:37.979531837 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -41,8 +41,7 @@ start = reserved.start(); end = reserved.end(); long numOopHandles = end.minus(start) / VM.getVM().getOopSize(); - // FIXME: will have trouble with larger heap sizes - bits = new BitMap((int) numOopHandles); + bits = heap.createBitMap(numOopHandles); } public void clear() { @@ -60,34 +59,22 @@ } OopHandle handle = obj.getHandle(); - // FIXME: will have trouble with larger heap sizes long idx = handle.minus(start) / VM.getVM().getOopSize(); - if ((idx < 0) || (idx >= bits.size())) { - System.err.println("MarkBits: WARNING: object " + handle + " outside of heap, ignoring"); - return false; - } - int intIdx = (int) idx; - if (bits.at(intIdx)) { + if (bits.at(idx)) { return false; // already marked } - bits.atPut(intIdx, true); + bits.atPut(idx, true); return true; } /** Forces clearing of a given mark bit. */ public void clear(Oop obj) { OopHandle handle = obj.getHandle(); - // FIXME: will have trouble with larger heap sizes long idx = handle.minus(start) / VM.getVM().getOopSize(); - if ((idx < 0) || (idx >= bits.size())) { - System.err.println("MarkBits: WARNING: object " + handle + " outside of heap, ignoring"); - return; - } - int intIdx = (int) idx; - bits.atPut(intIdx, false); + bits.atPut(idx, false); } - private BitMap bits; + private BitMapInterface bits; private Address start; private Address end; } --- old/test/hotspot/jtreg/serviceability/sa/ClhsdbJhisto.java 2019-02-15 20:10:39.167531829 +0100 +++ new/test/hotspot/jtreg/serviceability/sa/ClhsdbJhisto.java 2019-02-15 20:10:38.639531833 +0100 @@ -36,7 +36,6 @@ * @summary Test clhsdb jhisto command * @requires vm.hasSA * @requires vm.gc != "Shenandoah" - * @requires vm.gc != "Z" * @library /test/lib * @run main/othervm ClhsdbJhisto */ --- old/test/hotspot/jtreg/serviceability/sa/TestHeapDumpForInvokeDynamic.java 2019-02-15 20:10:39.871531823 +0100 +++ new/test/hotspot/jtreg/serviceability/sa/TestHeapDumpForInvokeDynamic.java 2019-02-15 20:10:39.295531828 +0100 @@ -50,7 +50,6 @@ * @test * @library /test/lib * @requires vm.hasSAandCanAttach & os.family != "mac" - * @requires vm.gc != "Z" * @modules java.base/jdk.internal.misc * jdk.hotspot.agent/sun.jvm.hotspot * jdk.hotspot.agent/sun.jvm.hotspot.utilities --- old/test/hotspot/jtreg/serviceability/sa/TestHeapDumpForLargeArray.java 2019-02-15 20:10:40.531531819 +0100 +++ new/test/hotspot/jtreg/serviceability/sa/TestHeapDumpForLargeArray.java 2019-02-15 20:10:40.003531823 +0100 @@ -48,7 +48,6 @@ * @bug 8171084 * @requires vm.hasSAandCanAttach & (vm.bits == "64" & os.maxMemory > 8g) * @requires vm.gc != "Shenandoah" - * @requires vm.gc != "Z" * @modules java.base/jdk.internal.misc * jdk.hotspot.agent/sun.jvm.hotspot * jdk.hotspot.agent/sun.jvm.hotspot.utilities --- old/test/hotspot/jtreg/serviceability/sa/TestJmapCore.java 2019-02-15 20:10:41.231531813 +0100 +++ new/test/hotspot/jtreg/serviceability/sa/TestJmapCore.java 2019-02-15 20:10:40.663531818 +0100 @@ -138,19 +138,8 @@ if (dumpFile.exists() && dumpFile.isFile()) { HprofParser.parse(dumpFile); } else { - boolean ZGCUsed = false; - - for (String opt: Utils.getFilteredTestJavaOpts()) { - if (opt.contains("+UseZGC")) { - ZGCUsed = true; - break; - } - } - - if (!ZGCUsed) { - throw new RuntimeException( - "Could not find dump file " + dumpFile.getAbsolutePath()); - } + throw new RuntimeException( + "Could not find dump file " + dumpFile.getAbsolutePath()); } System.out.println("PASSED"); --- /dev/null 2019-02-14 11:31:37.500399000 +0100 +++ new/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/shared/LiveRegionsClosure.java 2019-02-15 20:10:41.359531813 +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-14 11:31:37.500399000 +0100 +++ new/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/shared/LiveRegionsProvider.java 2019-02-15 20:10:42.135531807 +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-14 11:31:37.500399000 +0100 +++ new/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/z/ZExternalBitMap.java 2019-02-15 20:10:42.855531801 +0100 @@ -0,0 +1,111 @@ +/* + * 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.z; + +import java.util.HashMap; + +import sun.jvm.hotspot.runtime.VM; +import sun.jvm.hotspot.utilities.BitMap; +import sun.jvm.hotspot.utilities.BitMapInterface; + +/** Discontiguous bitmap for ZGC. */ +public class ZExternalBitMap implements BitMapInterface { + private ZPageTable pageTable; + private final long oopSize; + + private HashMap pageToBitMap = new HashMap(); + + public ZExternalBitMap(ZCollectedHeap collectedHeap) { + pageTable = collectedHeap.heap().pageTable(); + oopSize = VM.getVM().getOopSize(); + } + + private ZPage getPage(long zOffset) { + if (zOffset > ZGlobals.ZAddressOffsetMask) { + throw new RuntimeException("Not a Z offset: " + zOffset); + } + + ZPage page = pageTable.get(ZUtils.longToAddress(zOffset)); + if (page == null) { + throw new RuntimeException("Address not in pageTable: " + zOffset); + } + return page; + } + + private BitMap getOrAddBitMap(ZPage page) { + BitMap bitMap = pageToBitMap.get(page); + if (bitMap == null) { + long size = page.size(); + + long maxNumObjects = size >>> page.object_alignment_shift(); + if (maxNumObjects > Integer.MAX_VALUE) { + throw new RuntimeException("int overflow"); + } + int intMaxNumObjects = (int)maxNumObjects; + + bitMap = new BitMap(intMaxNumObjects); + pageToBitMap.put(page, bitMap); + } + + return bitMap; + } + + private int pageLocalBitMapIndex(ZPage page, long zOffset) { + long pageLocalZOffset = zOffset - page.start(); + return (int)(pageLocalZOffset >>> page.object_alignment_shift()); + } + + private long convertToZOffset(long offset) { + long addr = ZGlobals.ZAddressSpaceStart + oopSize * offset; + return addr & ZGlobals.ZAddressOffsetMask; + } + + @Override + public boolean at(long offset) { + long zOffset = convertToZOffset(offset); + ZPage page = getPage(zOffset); + BitMap bitMap = getOrAddBitMap(page); + int index = pageLocalBitMapIndex(page, zOffset); + + return bitMap.at(index); + } + + @Override + public void atPut(long offset, boolean value) { + long zOffset = convertToZOffset(offset); + ZPage page = getPage(zOffset); + BitMap bitMap = getOrAddBitMap(page); + int index = pageLocalBitMapIndex(page, zOffset); + + bitMap.atPut(index, value); + } + + @Override + public void clear() { + for (BitMap bitMap : pageToBitMap.values()) { + bitMap.clear(); + } + } +} --- /dev/null 2019-02-14 11:31:37.500399000 +0100 +++ new/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/z/ZUtils.java 2019-02-15 20:10:43.571531796 +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)); + } +} --- /dev/null 2019-02-14 11:31:37.500399000 +0100 +++ new/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/VMOopHandle.java 2019-02-15 20:10:44.303531791 +0100 @@ -0,0 +1,65 @@ +/* + * 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.oops; + +import sun.jvm.hotspot.debugger.Address; +import sun.jvm.hotspot.debugger.OopHandle; +import sun.jvm.hotspot.runtime.VM; +import sun.jvm.hotspot.runtime.VMObject; +import sun.jvm.hotspot.types.AddressField; +import sun.jvm.hotspot.types.Type; +import sun.jvm.hotspot.types.TypeDataBase; + +public class VMOopHandle extends VMObject { + private static AddressField objField; + + static { + VM.registerVMInitializedObserver((o, d) -> initialize(VM.getVM().getTypeDataBase())); + } + + private static synchronized void initialize(TypeDataBase db) { + Type type = db.lookupType("OopHandle"); + + objField = type.getAddressField("_obj"); + } + + public VMOopHandle(Address addr) { + super(addr); + } + + public Address getObj() { + return objField.getValue(addr); + } + + public Instance resolve() { + Address handle = getObj(); + if (handle != null) { + // Load through the handle + OopHandle refs = VM.getVM().getUniverse().heap().oop_load_in_native(handle); + return (Instance)VM.getVM().getObjectHeap().newOop(refs); + } + return null; + } +} --- /dev/null 2019-02-14 11:31:37.500399000 +0100 +++ new/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/BitMapInterface.java 2019-02-15 20:10:45.067531785 +0100 @@ -0,0 +1,32 @@ +/* + * 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.utilities; + +/** Minimal bitmap interface to support bitmaps spanning more than Integer.MAX_VALUE bits. */ +public interface BitMapInterface { + public boolean at(long offset); + public void atPut(long offset, boolean value); + public void clear(); +} --- /dev/null 2019-02-14 11:31:37.500399000 +0100 +++ new/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/BitMapSegmented.java 2019-02-15 20:10:45.787531780 +0100 @@ -0,0 +1,99 @@ +/* + * 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.utilities; + +/** A BitMap implementing the BitMapInterface. */ +public class BitMapSegmented implements BitMapInterface { + private static final int SegmentSizeBits = 30; + private static final int SegmentSize = 1 << (SegmentSizeBits - 1); + + public BitMapSegmented(long sizeInBits) { + this.size = sizeInBits; + + if (sizeInBits == 0) { + segmentBitMaps = new BitMap[0]; + return; + } + + int lastSegmentSize = (int)(sizeInBits % SegmentSize); + + int segments = segmentIndex(sizeInBits - 1) + 1; + int completeSegments = segments - ((lastSegmentSize != 0) ? 1 : 0); + + segmentBitMaps = new BitMap[segments]; + + for (int i = 0; i < completeSegments; i++) { + segmentBitMaps[i] = new BitMap(SegmentSize); + } + + if (lastSegmentSize != 0) { + segmentBitMaps[completeSegments] = new BitMap(lastSegmentSize); + } + } + + public long size() { + return size; + } + + // Accessors + public boolean at(long offset) { + assert offset < size; + + int segmentIndex = segmentIndex(offset); + int segmentOffset = segmentOffset(offset); + return segmentBitMaps[segmentIndex].at(segmentOffset); + } + + public void atPut(long offset, boolean value) { + assert offset < size; + + int segmentIndex = segmentIndex(offset); + int segmentOffset = segmentOffset(offset); + segmentBitMaps[segmentIndex].atPut(segmentOffset, value); + } + + public void clear() { + for (BitMap map : segmentBitMaps) { + map.clear(); + } + } + + //---------------------------------------------------------------------- + // Internals only below this point + // + private final long size; // in bits + private final BitMap[] segmentBitMaps; + + private int segmentIndex(long offset) { + long longIndex = offset / SegmentSize; + + assert longIndex < Integer.MAX_VALUE; + return (int)longIndex; + } + + private int segmentOffset(long offset) { + return (int)(offset % SegmentSize); + } +}