/*
* Copyright (c) 2010, 2012, 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 com.sun.max.vm.heap.gcx;
import static com.sun.max.vm.VMOptions.*;
import com.sun.max.annotate.*;
import com.sun.max.unsafe.*;
import com.sun.max.vm.*;
import com.sun.max.vm.MaxineVM.Phase;
import com.sun.max.vm.log.VMLog.Record;
import com.sun.max.vm.log.hosted.*;
/**
* Interface that space managers must implement to be notified of sweeping events emitted by a sweeping collector.
* The interface allows both precise and imprecise sweeping. Precise sweeping inspects
* every marked location to determine the end of the live data and identify every
* dead space, and invoke the space manager for every. Imprecise sweeping only inspects marked location separated by a minimum
* distance, thus avoiding inspecting object when the size of a potential free chunk is
* too small to be of interest to the free space manager.
*/
public abstract class Sweeper {
static boolean TraceSweep = false;
static {
if (MaxineVM.isDebug()) {
VMOptions.addFieldOption("-XX:", "TraceSweep", Sweeper.class, "Trace heap sweep operations", Phase.PRISTINE);
}
}
static final VMIntOption freeChunkMinSizeOption =
register(new VMIntOption("-XX:FreeChunkMinSize=", 256,
"Minimum size of contiguous space considered for space reclamation." +
"Below this size, the space is ignored (dark matter)"),
MaxineVM.Phase.PRISTINE);
protected SweepLogger logger = MaxineVM.isDebug() ? new SweepLogger(true) : new SweepLogger();
/**
* Invoked when doing precise sweeping on the first black object following the pointer last returned by this method.
* @param liveObject a pointer to a live cell in the heap
* @return a pointer to the position in the heap where to resume sweeping.
*/
public abstract Pointer processLiveObject(Pointer liveObject);
/**
* Invoked when doing imprecise sweeping to process an large interval between to marked locations.
* Imprecise heap sweeping ignores any space before two live objects smaller than a specified amount of space.
* When the distance between two live marks is large enough to indicate a potentially large chunk of free space,
* the sweeper invoke this method.
*
* @param leftLiveObject
* @param rightLiveObject
*/
public abstract Pointer processLargeGap(Pointer leftLiveObject, Pointer rightLiveObject);
/**
* Invoked to record a known chunk of free space larger than the minimum reclaimable space.
* Used both by precise and imprecise sweeper to record the unmarked space at both end of the traced space.
* @param freeChunk
* @param size
*/
public abstract void processDeadSpace(Address freeChunk, Size size);
/**
* Prepare the space manager for a sweep of the space it manages.
*/
public abstract void beginSweep();
/**
* Notify the space manager that sweeping is terminated.
*/
public abstract void endSweep();
/**
* Total free space after sweeping.
* May not be accurate with actual free space if allocation took place since endSweep was called.
*/
public abstract Size freeSpaceAfterSweep();
/**
* Minimum size to be considered reclaimable.
*/
public abstract Size minReclaimableSpace();
/**
* Linearly walk over the spaces swept by the sweeper to perform post-mark-sweep verification using the verifier given in argument.
* @param verifier
*/
public abstract void verify(AfterMarkSweepVerifier verifier);
/**
* Start of the region being swept.
* @return an address
*/
public abstract Address startOfSweepingRegion();
/**
* End of the region being swept.
* @return an address
*/
public abstract Address endOfSweepingRegion();
@HOSTED_ONLY
@VMLoggerInterface(defaultConstructor = true)
private interface SweepLoggerInterface {
void gap(
@VMLogParam(name = "leftLiveObject") Pointer leftLiveObject,
@VMLogParam(name = "rightLiveObject") Pointer rightLiveObject);
void deadSpace(
@VMLogParam(name = "deadSpace") Address deadSpace,
@VMLogParam(name = "size") Size size);
void freeSpace(
@VMLogParam(name = "freeSpace") Address freeSpace,
@VMLogParam(name = "size") Size size);
}
static final class SweepLogger extends SweepLoggerAuto {
SweepLogger(boolean active) {
super("Swept", "Trace dead space reclaimed by the sweeper");
}
SweepLogger() {
}
private void traceSpace(String spaceType, Address space, Size size) {
Log.print(spaceType);
Log.print(" Space @");
Log.print(space);
Log.print("(");
Log.print(size.toLong());
Log.println(")");
}
@Override
protected void traceDeadSpace(Address deadSpace, Size size) {
traceSpace("Dead", deadSpace, size);
}
@Override
protected void traceGap(Pointer leftLiveObject, Pointer rightLiveObject) {
Log.print("Gap between [");
Log.print(leftLiveObject);
Log.print(", ");
Log.print(rightLiveObject);
Log.print("]");
}
@Override
protected void traceFreeSpace(Address freeSpace, Size size) {
traceSpace("Free", freeSpace, size);
}
}
// START GENERATED CODE
private static abstract class SweepLoggerAuto extends com.sun.max.vm.log.VMLogger {
public enum Operation {
DeadSpace, FreeSpace, Gap;
@SuppressWarnings("hiding")
public static final Operation[] VALUES = values();
}
private static final int[] REFMAPS = null;
protected SweepLoggerAuto(String name, String optionDescription) {
super(name, Operation.VALUES.length, optionDescription, REFMAPS);
}
protected SweepLoggerAuto() {
}
@Override
public String operationName(int opCode) {
return Operation.VALUES[opCode].name();
}
@INLINE
public final void logDeadSpace(Address deadSpace, Size size) {
log(Operation.DeadSpace.ordinal(), deadSpace, size);
}
protected abstract void traceDeadSpace(Address deadSpace, Size size);
@INLINE
public final void logFreeSpace(Address freeSpace, Size size) {
log(Operation.FreeSpace.ordinal(), freeSpace, size);
}
protected abstract void traceFreeSpace(Address freeSpace, Size size);
@INLINE
public final void logGap(Pointer leftLiveObject, Pointer rightLiveObject) {
log(Operation.Gap.ordinal(), leftLiveObject, rightLiveObject);
}
protected abstract void traceGap(Pointer leftLiveObject, Pointer rightLiveObject);
@Override
protected void trace(Record r) {
switch (r.getOperation()) {
case 0: { //DeadSpace
traceDeadSpace(toAddress(r, 1), toSize(r, 2));
break;
}
case 1: { //FreeSpace
traceFreeSpace(toAddress(r, 1), toSize(r, 2));
break;
}
case 2: { //Gap
traceGap(toPointer(r, 1), toPointer(r, 2));
break;
}
}
}
}
// END GENERATED CODE
}