1 /*
  2  * Copyright (c) 2017, 2021, Red Hat, Inc. All rights reserved.
  3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4  *
  5  * This code is free software; you can redistribute it and/or modify it
  6  * under the terms of the GNU General Public License version 2 only, as
  7  * published by the Free Software Foundation.
  8  *
  9  * This code is distributed in the hope that it will be useful, but WITHOUT
 10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 12  * version 2 for more details (a copy is included in the LICENSE file that
 13  * accompanied this code).
 14  *
 15  * You should have received a copy of the GNU General Public License version
 16  * 2 along with this work; if not, write to the Free Software Foundation,
 17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 18  *
 19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 20  * or visit www.oracle.com if you need additional information or have any
 21  * questions.
 22  *
 23  */
 24 
 25 package sun.jvm.hotspot.gc.shenandoah;
 26 
 27 import sun.jvm.hotspot.gc.shared.CollectedHeap;
 28 import sun.jvm.hotspot.gc.shared.CollectedHeapName;
 29 import sun.jvm.hotspot.gc.shared.LiveRegionsClosure;
 30 import sun.jvm.hotspot.debugger.Address;
 31 import sun.jvm.hotspot.runtime.VM;
 32 import sun.jvm.hotspot.runtime.VMObjectFactory;
 33 import sun.jvm.hotspot.types.AddressField;
 34 import sun.jvm.hotspot.types.Type;
 35 import sun.jvm.hotspot.types.TypeDataBase;
 36 import sun.jvm.hotspot.memory.MemRegion;
 37 import sun.jvm.hotspot.types.CIntegerField;
 38 import sun.jvm.hotspot.utilities.BitMapInterface;
 39 
 40 import java.io.PrintStream;
 41 import sun.jvm.hotspot.utilities.Observable;
 42 import sun.jvm.hotspot.utilities.Observer;
 43 
 44 public class ShenandoahHeap extends CollectedHeap {
 45     private static CIntegerField numRegions;
 46     private static CIntegerField used;
 47     private static CIntegerField committed;
 48     private static AddressField  regions;
 49     private static CIntegerField logMinObjAlignmentInBytes;
 50 
 51     private static long regionPtrFieldSize;
 52     static {
 53         VM.registerVMInitializedObserver(new Observer() {
 54             public void update(Observable o, Object data) {
 55                 initialize(VM.getVM().getTypeDataBase());
 56             }
 57         });
 58     }
 59 
 60     private static synchronized void initialize(TypeDataBase db) {
 61         Type type = db.lookupType("ShenandoahHeap");
 62         numRegions = type.getCIntegerField("_num_regions");
 63         used = type.getCIntegerField("_used");
 64         committed = type.getCIntegerField("_committed");
 65         regions = type.getAddressField("_regions");
 66         logMinObjAlignmentInBytes = type.getCIntegerField("_log_min_obj_alignment_in_bytes");
 67 
 68         Type regionPtrType = db.lookupType("ShenandoahHeapRegion*");
 69         regionPtrFieldSize = regionPtrType.getSize();
 70     }
 71 
 72     public ShenandoahHeap(Address addr) {
 73         super(addr);
 74     }
 75 
 76     @Override
 77     public CollectedHeapName kind() {
 78         return CollectedHeapName.SHENANDOAH;
 79     }
 80 
 81     public long numOfRegions() {
 82         return numRegions.getValue(addr);
 83     }
 84 
 85     @Override
 86     public long capacity() {
 87         return numOfRegions() * ShenandoahHeapRegion.regionSizeBytes();
 88     }
 89 
 90     @Override
 91     public long used() {
 92         return used.getValue(addr);
 93     }
 94 
 95     public long committed() {
 96         return committed.getValue(addr);
 97     }
 98 
 99     public int getLogMinObjAlignmentInBytes() {
100         return logMinObjAlignmentInBytes.getJInt(addr);
101     }
102 
103     public ShenandoahHeapRegion getRegion(long index) {
104         if (index < numOfRegions()) {
105             Address arrayAddr = regions.getValue(addr);
106             Address regAddr = arrayAddr.getAddressAt(index * regionPtrFieldSize);
107             ShenandoahHeapRegion region = VMObjectFactory.newObject(ShenandoahHeapRegion.class, regAddr);
108             region.setHeap(this);
109             return region;
110         }
111         return null;
112     }
113 
114     public ShenandoahHeapRegion regionAtOffset(long offset) {
115         long index = offset >>> ShenandoahHeapRegion.regionSizeBytesShift();
116         if (index < 0 || index >= numOfRegions()) {
117             throw new RuntimeException("Invalid offset: " + offset);
118         }
119         return getRegion(index);
120     }
121 
122     @Override
123     public void liveRegionsIterate(LiveRegionsClosure closure) {
124         for (long index = 0; index < numOfRegions(); index ++) {
125             ShenandoahHeapRegion region = getRegion(index);
126             closure.doLiveRegions(region);
127         }
128     }
129 
130     @Override
131     public void printOn(PrintStream tty) {
132         MemRegion mr = reservedRegion();
133         tty.print("Shenandoah heap");
134         tty.print(" [" + mr.start() + ", " + mr.end() + "]");
135         tty.println(" region size " + ShenandoahHeapRegion.regionSizeBytes() / 1024 + " K");
136     }
137 
138     @Override
139     public BitMapInterface createBitMap(long bits) {
140         return new ShenandoahBitMap(this);
141     }
142 
143 }