/*
* Copyright (c) 2017, 2019, Red Hat, Inc. All rights reserved.
*
* 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.shenandoah;
import sun.jvm.hotspot.debugger.OopHandle;
import sun.jvm.hotspot.gc.shared.ContiguousSpace;
import sun.jvm.hotspot.gc.shared.LiveRegionsProvider;
import sun.jvm.hotspot.memory.MemRegion;
import sun.jvm.hotspot.oops.Mark;
import sun.jvm.hotspot.oops.Oop;
import sun.jvm.hotspot.oops.UnknownOopException;
import sun.jvm.hotspot.types.*;
import sun.jvm.hotspot.runtime.VM;
import sun.jvm.hotspot.debugger.Address;
import sun.jvm.hotspot.utilities.AddressOps;
import java.util.ArrayList;
import java.util.List;
import java.util.Observable;
import java.util.Observer;
public class ShenandoahHeapRegion extends ContiguousSpace implements LiveRegionsProvider {
private static int EmptyUncommitted;
private static int EmptyCommitted;
private static int Regular;
private static int HumongousStart;
private static int HumongousCont;
private static int PinnedHumongousStart;
private static int CSet;
private static int Pinned;
private static int PinnedCSet;
private static int Trash;
private static CIntegerField RegionSizeBytesField;
private static Field RegionStateField;
private static CIntegerField RegionNumberField;
private static CIntegerField RegionSizeBytesShiftField;
private ShenandoahHeap heap;
static {
VM.registerVMInitializedObserver(new Observer() {
public void update(Observable o, Object data) {
initialize(VM.getVM().getTypeDataBase());
}
});
}
static private synchronized void initialize(TypeDataBase db) {
Type type = db.lookupType("ShenandoahHeapRegion");
RegionSizeBytesField = type.getCIntegerField("RegionSizeBytes");
RegionStateField = type.getField("_state");
RegionNumberField = type.getCIntegerField("_region_number");
RegionSizeBytesShiftField = type.getCIntegerField("RegionSizeBytesShift");
EmptyUncommitted = db.lookupIntConstant("ShenandoahHeapRegion::_empty_uncommitted").intValue();
EmptyCommitted = db.lookupIntConstant("ShenandoahHeapRegion::_empty_committed").intValue();
Regular = db.lookupIntConstant("ShenandoahHeapRegion::_regular").intValue();
HumongousStart = db.lookupIntConstant("ShenandoahHeapRegion::_humongous_start").intValue();
HumongousCont = db.lookupIntConstant("ShenandoahHeapRegion::_humongous_cont").intValue();
PinnedHumongousStart = db.lookupIntConstant("ShenandoahHeapRegion::_pinned_humongous_start").intValue();
CSet = db.lookupIntConstant("ShenandoahHeapRegion::_cset").intValue();
Pinned = db.lookupIntConstant("ShenandoahHeapRegion::_pinned").intValue();
PinnedCSet = db.lookupIntConstant("ShenandoahHeapRegion::_pinned_cset").intValue();
Trash = db.lookupIntConstant("ShenandoahHeapRegion::_trash").intValue();
}
public static long regionSizeBytes() {
return RegionSizeBytesField.getValue();
}
public static int regionSizeBytesShift() {
return RegionSizeBytesShiftField.getJInt();
}
public ShenandoahHeapRegion(Address addr) {
super(addr);
}
public void setHeap(ShenandoahHeap heap) {
this.heap = heap;
}
@Override
public int hashCode() {
return (int)regionNumber();
}
@Override
public boolean equals(Object other) {
if (other instanceof ShenandoahHeapRegion) {
ShenandoahHeapRegion otherRegion = (ShenandoahHeapRegion)other;
return otherRegion.regionNumber() == regionNumber();
}
return false;
}
public List<MemRegion> getLiveRegions() {
List<MemRegion> res = new ArrayList<>();
int state = regionState();
if (state == EmptyUncommitted || state == EmptyCommitted || state == Trash) {
// No live data
} else if (state == HumongousCont) {
// Handled by HumongousStart
} else if (state == HumongousStart || state == PinnedHumongousStart) {
handleHumongousRegion(res);
} else if (state == Regular || state == Pinned) {
handleRegularRegion(res);
} else if (state == CSet || state == PinnedCSet) {
// CSet
handleCSetRegion(res);
} else {
throw new RuntimeException("Unknown region state: " + state);
}
return res;
}
/*
* Note: RegionState is an enum on JVM side. Seems that there is not
* a standard way to read enum value. We read it as an integer
* from the field's offset.
*/
private int regionState() {
long offset = RegionStateField.getOffset();
return addr.getJIntAt(offset);
}
private void handleHumongousRegion(List<MemRegion> res) {
long index = regionNumber();
Address topAddr = top();
ShenandoahHeapRegion region = heap.getRegion(++ index);
while (region.regionState() == HumongousCont) {
topAddr = region.top();
region = heap.getRegion(++ index);
}
res.add(new MemRegion(bottom(), topAddr));
}
private void handleRegularRegion(List<MemRegion> res) {
res.add(new MemRegion(bottom(), top()));
}
// Filter out forwarded objects, they should be counted in other regions
private void handleCSetRegion(List<MemRegion> res) {
Address end = top();
Address start = bottom();
Address regionStart = null;
Address regionEnd = null;
while (AddressOps.lessThan(start, end)) {
long size = getObjectSize(start);
if (hasForwardee(start)) {
// has to-space object, skip this one
if (regionEnd != null) {
MemRegion mr = new MemRegion(regionStart, regionEnd);
res.add(mr);
regionStart = null;
regionEnd = null;
}
} else {
if (regionStart == null) {
regionStart = start;
} else {
regionEnd = start.addOffsetTo(size);
}
}
start = start.addOffsetTo(size);
}
if (regionStart != null) {
/**代码未完, 请加载全部代码(NowJava.com).**/