/* * Copyright (c) 2011, 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 static com.sun.max.vm.heap.gcx.HeapRegionConstants.*; import com.sun.max.tele.*; import com.sun.max.tele.reference.*; import com.sun.max.unsafe.*; import com.sun.max.vm.heap.gcx.*; // TODO (mlvdv) recast this as a descendant of TeleObject, register it in REmoteRegionBasedHeapScheme. /** * Inspector's surrogate for the heap region table used by region based GC (currently, MSE heap scheme). * @see RegionTable */ public class TeleRegionTable extends AbstractVmHolder { static TeleRegionTable theTeleRegionTable; public static synchronized TeleRegionTable makeTheTeleRegionTable(TeleVM vm) { if (theTeleRegionTable == null) { theTeleRegionTable = new TeleRegionTable(vm); } return theTeleRegionTable; } public static TeleRegionTable theTeleRegionTable() { assert theTeleRegionTable != null; return theTeleRegionTable; } private boolean initializing; private RegionTable regionTable; private Address regionTableAddress = Address.zero(); private TeleRegionTable(TeleVM vm) { super(vm); } private boolean isInitialized() { return regionTable != null; } private void initialize() { if (isInitialized()) { return; } initializing(); } private synchronized void initializing() { if (initializing) { return; } initializing = true; RemoteReference theRegionTableReference = vm().fields().RegionTable_theRegionTable.readRemoteReference(vm()); if (theRegionTableReference.isZero()) { return; } int numRegions = vm().fields().RegionTable_length.readInt(theRegionTableReference); if (numRegions == 0) { return; } // The VM's region table is initialized. We build a local instance of RegionTable based on the values of the VM's instance. // The local copy will be identical, except for its address. This allows to use many function of RegionTable directly. HeapRegionConstants.initializeWithConstants(vm().fields().HeapRegionConstants_regionSizeInBytes.readInt(vm())); Address start = vm().fields().RegionTable_regionPoolStart.readWord(theRegionTableReference).asAddress(); Address end = vm().fields().RegionTable_regionPoolEnd.readWord(theRegionTableReference).asAddress(); int infoSize = vm().fields().RegionTable_regionInfoSize.readInt(theRegionTableReference); regionTable = new RegionTable(start, end, numRegions, infoSize); regionTableAddress = theRegionTableReference.toOrigin(); initializing = false; } public boolean isValidRegionID(int regionID) { return regionTable.isValidRegionID(regionID); } public Address regionInfo(int regionID) { assert regionTable.isValidRegionID(regionID); return regionTableAddress.plus(regionTable.regionInfoOffset(regionID)); } public Address regionStart(int regionID) { return regionTable.regionAddress(regionID); } public Address regionEnd(int regionID) { return regionStart(regionID + 1); } public int toRegionID(Address regionInfo) { assert isInitialized(); if (regionInfo.lessThan(regionTableAddress)) { // May reach here when trying to create the nullHeapRegionInfo return INVALID_REGION_ID; } final int offsetFromTableAddress = regionInfo.minus(regionTableAddress).toInt(); return regionTable.regionIDFromRegionInfoOffset(offsetFromTableAddress); } /** * Return the region ID of the heap region containing the location specified by the address. * @param address an address in the heap * @return a region ID */ public int regionID(Address address) { if (!isInitialized()) { initialize(); if (!isInitialized()) { return INVALID_REGION_ID; } } return regionTable.regionID(address); } }