/*
* 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.tele.object;
import com.sun.max.tele.*;
import com.sun.max.tele.reference.*;
import com.sun.max.unsafe.*;
import com.sun.max.vm.heap.*;
/**
* Canonical surrogate for a {@link BootHeapRegion} object in the VM,
* a singleton that describes the memory occupied by the boot heap.
* <p>
* Usage defaults to 100% if nothing can be determined about the allocation mark.
*/
public class TeleBootHeapRegion extends TeleLinearAllocationMemoryRegion {
private static final int TRACE_VALUE = 1;
/**
* Location in VM memory (in the boot heap) of the first byte of the boot heap reference map.
*/
private Address referenceMap = Address.zero();
/**
* End of the byte array that holds the boot heap reference map.
*/
private Address referenceMapEnd = Address.zero();
private final int mask;
public TeleBootHeapRegion(TeleVM vm, RemoteReference bootHeapRegionReference) {
super(vm, bootHeapRegionReference);
mask = (1 << Word.widthValue().log2numberOfBits) - 1;
}
/** {@inheritDoc}
* <p>
* Preempt upward the priority for tracing on {@link BootHeapRegion} objects,
* since they usually represent very significant regions.
*/
@Override
protected int getObjectUpdateTraceValue(long epoch) {
return TRACE_VALUE;
}
@Override
protected boolean updateObjectCache(long epoch, StatsPrinter statsPrinter) {
if (!super.updateObjectCache(epoch, statsPrinter)) {
return false;
}
if (referenceMap.isZero()) {
final RemoteReference refMapByteArrayRef = fields().BootHeapRegion_referenceMapBytes.readRemoteReference(reference());
if (!refMapByteArrayRef.isZero()) {
final TeleArrayObject refMapByteArray = (TeleArrayObject) objects().makeTeleObject(refMapByteArrayRef);
referenceMapEnd = refMapByteArray.objectMemoryRegion().end();
referenceMap = refMapByteArrayRef.toOrigin().plus(refMapByteArray.arrayOffsetFromOrigin());
}
}
return true;
}
/**
* Determines whether the address, presumed to be in the boot heap region, is the location of a reference field that
* might be changed during VM operation.
*
* @param address a VM memory location presumed to be in the boot heap region
* @return {@code true} iff the address is covered by the reference map and is marked as <em>mutable</em>.
*/
public boolean isRefMapMarked(Address address) {
if (!referenceMap.isZero() && isAllocated() && contains(address)) {
final int bitIndex = address.minus(getRegionStart()).unsignedShiftedRight(Word.widthValue().log2numberOfBytes).toInt();
final int wordIndex = bitIndex >> Word.widthValue().log2numberOfBits;
final Address tableWordAddress = referenceMap.plus(wordIndex * Word.size());
if (tableWordAddress.lessThan(referenceMapEnd)) {
/*
* The boot heap reference map does not cover the entire boot heap. In order to minimize the size of the map, the
* boot heap is arranged with all the mutable objects at the beginning. If the computed mark bit for a boot heap
* address would be past the end of the reference map table, then we know it immutable/unmarked.
*/
final Address refMapWord = memory().readWord(tableWordAddress).asAddress();
final int bitWordIndex = bitIndex & mask;
//final String suffix = refMapWord.isBitSet(bitWordIndex) ? " MARKED" : "";
//System.out.println("bit=" + bitIndex + " (" + wordIndex + "/" + bitWordIndex + ") word@" + tableWordAddress.to0xHexString() + ", value=" + refMapWord.to0xHexString() + suffix);
return refMapWord.isBitSet(bitWordIndex);
}
}
return false;
}
}