/* * Copyright (c) 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.heap.region; import java.io.*; import java.lang.management.*; import java.util.*; import com.sun.max.tele.*; import com.sun.max.tele.memory.*; import com.sun.max.tele.object.*; import com.sun.max.tele.reference.*; import com.sun.max.tele.util.*; import com.sun.max.unsafe.*; import com.sun.max.vm.heap.*; import com.sun.max.vm.heap.gcx.rset.ctbl.*; // TODO (mlvdv) this is just a skeleton; it is non-functional /** * A specialized subclass of the Mark Bitmap used by some GC implementations. The singleton instance, corresponding to * the one used in the VM, is not created until the VM heap scheme has allocated the bit map data and initialized * everything, so no refreshing is needed. * <p> * The Mark Bitmap's data is stored in a region separate from the heap, allocated from the OS. The region is filled with * a single array (in standard Maxine format) of longs. */ public final class VmCardTable extends AbstractVmHolder implements MaxCardTable, VmObjectHoldingRegion<MaxCardTable> { private static final String ENTITY_NAME = "Heap-Card Table data"; private static final List<MaxEntityMemoryRegion< ? extends MaxEntity>> EMPTY = Collections.emptyList(); /** * Representation of a VM memory region used to hold a card Table. The card table is implemented as a single byte array that * occupied the entire region. * <p> * The card table may be reallocated during the startup sequence of the VM. * <p> * This region has no parent; it is allocated dynamically from the OS * <p> * This region has no children. */ private final class CardTableMemoryRegion extends AbstractVmHolder implements MaxEntityMemoryRegion<MaxCardTable> { private final MaxCardTable owner; protected CardTableMemoryRegion(TeleVM vm, MaxCardTable owner) { super(vm); this.owner = owner; } public MaxEntityMemoryRegion< ? extends MaxEntity> parent() { // The Card Table fully occupies a region allocated from the OS, not part of any other region. return null; } public List<MaxEntityMemoryRegion< ? extends MaxEntity>> children() { return EMPTY; } public MaxCardTable owner() { return owner; } public String regionName() { return "Card Table"; } @Override public Address start() { // TODO Auto-generated method stub return null; } @Override public long nBytes() { // TODO Auto-generated method stub return 0; } @Override public Address end() { // TODO Auto-generated method stub return null; } @Override public boolean isAllocated() { // TODO Auto-generated method stub return false; } @Override public MemoryUsage getUsage() { // TODO Auto-generated method stub return null; } @Override public boolean contains(Address address) { // TODO Auto-generated method stub return false; } public Address mark() { return null; } public boolean containsInAllocated(Address address) { return contains(address); } @Override public boolean overlaps(MaxMemoryRegion memoryRegion) { // TODO Auto-generated method stub return false; } @Override public boolean sameAs(MaxMemoryRegion memoryRegion) { // TODO Auto-generated method stub return false; } } private final TeleCardTableRSet cardTableRSet; private final CardTable cardTable; private final CardTableMemoryRegion cardTableMemoryRegion; private final CardTableObjectReferenceManager objectReferenceManager; // private final TeleFixedMemoryRegion coveredMemoryRegion; // private final TeleArrayObject cardTableArray; // TODO (mlvdv) should be a TeleCardTable public VmCardTable(TeleVM vm, TeleCardTableRSet cardTableRSet) { super(vm); this.cardTableRSet = cardTableRSet; this.cardTable = cardTableRSet.cardTable(); this.cardTableMemoryRegion = new CardTableMemoryRegion(vm, this); this.objectReferenceManager = new CardTableObjectReferenceManager(vm, null); // final long coveredSize = 0L; // remoteHeapMarker.coveredAreaEnd().minus(remoteHeapMarker.coveredAreaStart()).toLong(); // this.coveredMemoryRegion = null; // new TeleFixedMemoryRegion(vm, ENTITY_NAME, remoteHeapMarker.coveredAreaStart(), coveredSize); // final Address dataRegionStart = Address.zero(); //remoteHeapMarker.colorMapDataRegion().getRegionStart(); // final long dataRegionSize = 0L; //remoteHeapMarker.colorMapDataRegion().getRegionNBytes(); // this.cardTableArray = (TeleArrayObject) vm.objects().makeTeleObject(objectReferenceManager.byteArrayRef); // this.cardTableArray.setMaxineRole(ENTITY_NAME); } public String entityName() { return ENTITY_NAME; } public String entityDescription() { return "The region of OS-allocated memory in which a Card Table is stored, formatted as a single long array"; } public MaxEntityMemoryRegion<MaxCardTable> memoryRegion() { return cardTableMemoryRegion; } /** * {@inheritDoc} * <p> * This the allocation holding the mark bitmap. */ public boolean contains(Address address) { return cardTableMemoryRegion.contains(address); } public MaxObject representation() { // TODO - return the TeleArray return null; } public MaxMemoryRegion coveredMemoryRegion() { return new TeleFixedMemoryRegion(vm(), "CardTable covered region", cardTable.coveredAreaStart(), cardTable.coveredAreaEnd()); } public boolean isCovered(Address heapAddress) { return cardTable.isCovered(heapAddress); } public int cardSize() { // TODO return 0; } // public int getBitIndexOf(Address heapAddress) { // return coveredMemoryRegion.contains(heapAddress) ? byteIndexOf(heapAddress) : -1; // } // // // public Address heapAddress(int bitIndex) { // return addressOf(bitIndex); // } // // public Address bitmapWordAddress(int bitIndex) { // return bitmapWordPointerAt(bitIndex); // } // // public long readBitmapWord(int bitIndex) { // return hostedBitmapWordAt(bitIndex); // } // // public int getBitIndexInWord(int bitIndex) { // return bitIndexInWord(bitIndex); // } // // public boolean isBitSet(int bitIndex) { // return isSet(bitIndex); // } // // public void setBit(int bitIndex) { // TeleError.unimplemented(); // } // /** // * {@inheritDoc} // * <p> // * Override the standard method in {@link TricolorHeapMarker} for reading a word out of the bitmap table with one // * that reads the memory remotely from the VM. // */ // @Override // protected long hostedBitmapWordAt(int bitIndex) { // return vm().memoryIO().getLong(base, 0, bitmapWordIndex(bitIndex)); // } // // public MarkColor getMarkColor(Address heapAddress) { // if (vm().objects().objectStatusAt(heapAddress).isLive() && isCovered(heapAddress)) { // return getMarkColorUnsafe(heapAddress); // } // return null; // } // // public MarkColor getMarkColor(int bitIndex) { // final Address heapAddress = addressOf(bitIndex); // if (vm().objects().objectStatusAt(heapAddress).isLive()) { // return getMarkColorUnsafe(heapAddress); // } // return null; // } // // /** // * Gets the marking at a particular index of the bitmap. Does <em>not check</em> that there is an object at that // * location, or even whether the address is covered by the bitmap, so the mark could be at an invalid location. // */ // public MarkColor getMarkColorUnsafe(Address address) { // final int bitIndex = bitIndexOf(address); // try { // if (isWhite(bitIndex)) { // if (isClear(bitIndex + 1)) { // return MARK_WHITE; // } // TeleWarning.message("Invalid mark in mark bitmap @" + bitIndex); // return MARK_INVALID; // } else if (isGreyWhenNotWhite(bitIndex)) { // return MARK_GRAY; // } // if (isClear(bitIndex + 1)) { // return MARK_BLACK; // } // TeleWarning.message("Invalid mark in mark bitmap @" + bitIndex); // return MARK_INVALID; // } catch (DataIOError e) { // return MARK_UNAVAILABLE; // } // } // // /** // * @return bitmap index one past the last covered heap address // */ // private int endBitIndex() { // return bitIndexOf(coveredMemoryRegion.end()); // } // // public int nextSetBitAfter(int startBitIndex) { // for (int bitIndex = startBitIndex + 1; bitIndex < endBitIndex(); bitIndex++) { // if (isSet(bitIndex)) { // return bitIndex; // } // } // return -1; // } // // public int previousSetBitBefore(int startBitIndex) { // for (int bitIndex = startBitIndex - 1; bitIndex >= 0; bitIndex--) { // if (isSet(bitIndex)) { // return bitIndex; // } // } // return -1; // } // // public int nextMarkAfter(int startBitIndex, MarkColor color) { // switch(color) { // case MARK_BLACK: // case MARK_GRAY: // for (int bitIndex = startBitIndex + 1; bitIndex < endBitIndex(); bitIndex++) { // // For BLACK and GRAY marks, we only have to check at locations where the first bit is set // if (isSet(bitIndex) && getMarkColor(bitIndex) == color) { // return bitIndex; // } // } // return -1; // case MARK_WHITE: // case MARK_INVALID: // for (int bitIndex = startBitIndex + 1; bitIndex < endBitIndex(); bitIndex++) { // if (getMarkColor(bitIndex) == color) { // return bitIndex; // } // } // return -1; // case MARK_UNAVAILABLE: // return -1; // } // return -1; // } // // public int previousMarkBefore(int startBitIndex, MarkColor color) { // switch(color) { // case MARK_BLACK: // case MARK_GRAY: // for (int bitIndex = startBitIndex - 1; bitIndex >= 0; bitIndex--) { // // For BLACK and GRAY marks, we only have to check at locations where the first bit is set // if (isSet(bitIndex) && getMarkColor(bitIndex) == color) { // return bitIndex; // } // } // return -1; // case MARK_WHITE: // case MARK_INVALID: // for (int bitIndex = startBitIndex - 1; bitIndex >= 0; bitIndex--) { // if (getMarkColor(bitIndex) == color) { // return bitIndex; // } // } // return -1; // case MARK_UNAVAILABLE: // return -1; // } // return -1; // } public RemoteObjectReferenceManager objectReferenceManager() { return objectReferenceManager; } public void printObjectSessionStats(PrintStream printStream, int indent, boolean verbose) { TeleWarning.unimplemented(); } // TODO do we need make this dynamic /** * Manager for object references for the unmanaged card table region, which contains, * once initialized, a singleton long array. */ private class CardTableObjectReferenceManager extends AbstractVmHolder implements RemoteObjectReferenceManager { // private final Address byteArrayOrigin; // private final ConstantRemoteReference byteArrayRef; protected CardTableObjectReferenceManager(TeleVM vm, Address start) { super(vm); // byteArrayOrigin = objects().layoutScheme().generalLayout.cellToOrigin(start.asPointer()); // byteArrayRef = new ConstantRemoteReference(vm(), byteArrayOrigin) { // // @Override // public ObjectStatus status() { // return ObjectStatus.LIVE; // } // // @Override // public ObjectStatus priorStatus() { // return null; // } // }; } /** * {@inheritDoc} * <p> * There is no GC cycle; the singleton byte array is neither relocated nor collected. */ public HeapPhase phase() { return HeapPhase.MUTATING; } public ObjectStatus objectStatusAt(Address origin) { // TeleError.check(memoryRegion().contains(origin), "Location is outside region"); // return origin.equals(byteArrayOrigin) ? ObjectStatus.LIVE : ObjectStatus.DEAD; return ObjectStatus.DEAD; } public boolean isForwardingAddress(Address forwardingAddress) { return false; } /** * {@inheritDoc} * <p> * The only reference possible is to the header of the array that holds the whole map in the region. */ public RemoteReference makeReference(Address origin) throws TeleError { // return objectStatusAt(origin).isLive() ? byteArrayRef : null; return null; } public RemoteReference makeQuasiReference(Address origin) { return null; } public void printObjectSessionStats(PrintStream printStream, int indent, boolean verbose) { TeleWarning.unimplemented(); } } }