/*
* 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 com.sun.max.annotate.*;
import com.sun.max.memory.*;
import com.sun.max.profile.*;
import com.sun.max.unsafe.*;
import com.sun.max.util.timer.*;
import com.sun.max.vm.*;
import com.sun.max.vm.MaxineVM.Phase;
import com.sun.max.vm.heap.*;
import com.sun.max.vm.runtime.*;
/**
* Adaptor for factoring a number of common boiler plate for HeapScheme implemented with components of the gcx package.
*/
public abstract class HeapSchemeWithTLABAdaptor extends HeapSchemeWithTLAB {
protected static boolean VerifyAfterGC = false;
static {
VMOptions.addFieldOption("-XX:", "VerifyAfterGC", HeapSchemeWithTLABAdaptor.class, "Verify heap after GC", Phase.PRISTINE);
}
/**
* Size to reserve at the end of a TLABs to guarantee that a dead object can always be
* appended to a TLAB to fill unused space before a TLAB refill.
* The headroom is used to compute a soft limit that'll be used as the tlab's top.
*/
@FOLD
protected static Size tlabHeadroom() {
return minObjectSize();
}
@FOLD
protected static int tlabHeadroomNumWords() {
return tlabHeadroom().unsignedShiftedRight(Word.widthValue().log2numberOfBytes).toInt();
}
protected static void fillTLABWithDeadObject(Pointer tlabAllocationMark, Pointer tlabEnd) {
// Need to plant a dead object in the leftover to make the heap parsable (required for sweeping).
Pointer hardLimit = tlabEnd.plus(tlabHeadroom());
if (tlabAllocationMark.greaterThan(tlabEnd)) {
FatalError.check(hardLimit.equals(tlabAllocationMark), "TLAB allocation mark cannot be greater than TLAB End");
return;
}
DarkMatter.format(tlabAllocationMark, hardLimit);
}
class TLABFiller extends HeapSchemeWithTLAB.ResetTLAB {
@Override
protected void doBeforeReset(Pointer etla, Pointer tlabMark, Pointer tlabTop) {
if (MaxineVM.isDebug() && logTLABEvents(tlabMark)) {
TLABLog.doOnRetireTLAB(etla);
}
fillTLABWithDeadObject(tlabMark, tlabTop);
}
}
protected final TLABFiller tlabFiller = new TLABFiller();
public HeapSchemeWithTLABAdaptor() {
super();
}
/**
* Debugging support for TLAB event logging. Tells whether a condition is met for logging a TLAB event.
* @param tlabStart start of the TLAB
* @return true if the event on the specified TLAB should be logged
*/
protected boolean logTLABEvents(Address tlabStart) {
return false;
}
abstract protected void allocateHeapAndGCStorage();
private static final TimerMetric heapStartupTime = new TimerMetric(new SingleUseTimer(Clock.SYSTEM_MILLISECONDS));
@Override
public void initialize(MaxineVM.Phase phase) {
super.initialize(phase);
if (phase == MaxineVM.Phase.PRISTINE) {
heapStartupTime.start();
allocateHeapAndGCStorage();
heapStartupTime.stop();
} else if (phase == MaxineVM.Phase.TERMINATING) {
if (Heap.logGCTime()) {
heapStartupTime.report("allocateHeapAndGCStorage", Log.out);
VirtualMemory.reportMetrics();
}
}
}
@Override
public int reservedVirtualSpaceKB() {
// 2^30 Kb = 1 TB of reserved virtual space.
// This will be truncated as soon as we taxed what we need at initialization time.
return Size.G.toInt();
}
@Override
protected void doBeforeTLABRefill(Pointer tlabAllocationMark, Pointer tlabEnd) {
fillTLABWithDeadObject(tlabAllocationMark, tlabEnd);
}
@Override
protected void tlabReset(Pointer tla) {
tlabFiller.run(tla);
}
@Override
protected void releaseUnusedReservedVirtualSpace() {
// Do nothing. Heap schemes using this package have their own way of doing this.
}
@INLINE
@Override
public final boolean supportsTagging() {
return false;
}
@INLINE
@Override
public final boolean supportsPadding() {
return false;
}
}