/* * Copyright (c) 2009, 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; import com.oracle.max.cri.intrinsics.*; import com.sun.max.annotate.*; import com.sun.max.program.*; import com.sun.max.unsafe.*; import com.sun.max.vm.heap.debug.*; import com.sun.max.vm.object.*; import com.sun.max.vm.reference.*; import com.sun.max.vm.runtime.*; /** * The special region describing the heap in the boot image. */ public final class BootHeapRegion extends LinearAllocatorRegion { @INSPECTED private byte[] referenceMapBytes; private java.lang.ref.Reference[] specialReferences = {}; public BootHeapRegion(Address start, Size size, String description) { super(start, size, description); } @HOSTED_ONLY public void init(byte[] refMap, java.lang.ref.Reference[] specialRefs) { ProgramError.check(Address.fromInt(refMap.length).isWordAligned(), "Boot heap reference map must have word-aligned size"); this.referenceMapBytes = refMap; this.specialReferences = specialRefs; } @INLINE public void discoverSpecialReference() { for (java.lang.ref.Reference specialReference : specialReferences) { SpecialReferenceManager.discoverSpecialReference(Reference.fromJava(specialReference).toOrigin()); } } public void visitReferences(PointerIndexVisitor pointerIndexVisitor) { final int referenceMapWords = UnsignedMath.divide(referenceMapBytes.length, Word.size()); if (Heap.logRootScanning()) { Heap.rootScanLogger.logScanningBootHeap(this, start().plus(referenceMapBytes.length)); scanReferenceMap(pointerIndexVisitor, referenceMapBytes, referenceMapWords, true); } else { scanReferenceMap(pointerIndexVisitor, referenceMapBytes, referenceMapWords, false); } discoverSpecialReference(); } /** * Visit references comprised in the specified range within the boot heap region. * @param start first address (inclusive) of the range * @param end last address (exclusive) of the range * @param pointerIndexVisitor */ public void visitReferences(Address start, Address end, PointerIndexVisitor pointerIndexVisitor) { FatalError.check(contains(start) && contains(end), "range not in boot heap region"); if (Heap.logRootScanning()) { scanReferences(pointerIndexVisitor, referenceMapBytes, start, end, true); } else { scanReferences(pointerIndexVisitor, referenceMapBytes, start, end, false); } } public int referenceMapIndex(Address referenceLocation) { if (contains(referenceLocation)) { return referenceLocation.minus(start).unsignedShiftedRight(Word.widthValue().log2numberOfBytes).toInt(); } return -1; } /** * Return the address to the top most mutable location in the boot region. * @return an address in the boot region */ public Address lastMutableReferenceAddress() { final Pointer referenceMap = ArrayAccess.elementPointer(referenceMapBytes, 0); final int lastWordIndex = (referenceMapBytes.length >> Word.widthValue().log2numberOfBytes) - 1; final Word lastRefMapWord = referenceMap.getWord(lastWordIndex).asPointer(); final int bitIndex = lastRefMapWord.mostSignificantBitSet(); final int lastBitIndex = bitIndex + (lastWordIndex << Word.widthValue().log2numberOfBits); return start.plus(lastBitIndex << Word.widthValue().log2numberOfBytes); } public boolean isMutableReference(Address referenceLocation) { if (contains(referenceLocation)) { final Pointer referenceMap = ArrayAccess.elementPointer(referenceMapBytes, 0); final int bitIndex = referenceLocation.minus(start).unsignedShiftedRight(Word.widthValue().log2numberOfBytes).toInt(); final int wordIndex = bitIndex >> Word.widthValue().log2numberOfBits; final Address refmapWord = referenceMap.getWord(wordIndex).asAddress(); final Address bitmask = Address.fromLong(1L).shiftedLeft(bitIndex); return refmapWord.and(bitmask).isNotZero(); } return false; } public void visitCells(CellVisitor cellVisitor) { final Pointer firstCell = start().asPointer(); final Pointer lastCell = mark(); Pointer cell = firstCell; while (cell.isNotZero() && cell.lessThan(lastCell)) { cell = DebugHeap.checkDebugCellTag(firstCell, cell); cell = cellVisitor.visitCell(cell); } } }