/* * Copyright (c) 2010, 2011, 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.unsafe.*; import com.sun.max.vm.heap.gcx.TricolorHeapMarker.*; /** * Recovery from marking stack overflow using a linear scan of the mark bitmap. * Flush the marking stack, marking all objects referenced from it grey, and iterate over * the mark-bitmap from the mark of the leftmost flushed reference up to the forward scan finger. * As with a forward scan, a rescan finger is maintained: references before the rescan finger are pushed * on the marking stack, those after aren't since they'll be iterated over and found. */ final class OverflowLinearScanState extends OverflowScanState { /** * Start of the next scan of the color map to recover from secondary marking stack overflow. */ Address startOfNextOverflowScan; private final DeepMarkingStackFlusher deepMarkStackFlusher; private final BaseMarkingStackFlusher shallowMarkStackFlusher; OverflowLinearScanState(TricolorHeapMarker heapMarker) { super(heapMarker); deepMarkStackFlusher = new DeepMarkingStackFlusher(heapMarker); shallowMarkStackFlusher = new BaseMarkingStackFlusher(); } private void visitGreyObjects() { if (regionsRanges != null) { visitGreyObjects(regionsRanges); } else { int rightmostBitmapWordIndex = rightmostBitmapWordIndex(); int fingerBitmapWordIndex = heapMarker.bitmapWordIndex(finger); visitGreyObjectsToEndOfScan(fingerBitmapWordIndex, rightmostBitmapWordIndex); } // The overflow rescan may have ended with a finger before the end of scan position as the finger is updated only when // visiting grey cell. Before draining the marking stack, we set it to the end of scan position so draining // operates with the marking stack only. finger = endOfScan; // There might be some objects left in the marking stack. Drain it. heapMarker.markingStack.drain(); } @Override void initialize() { setMarkingStackFlusher(TricolorHeapMarker.UseDeepMarkStackFlush ? deepMarkStackFlusher : shallowMarkStackFlusher); super.initialize(); } @Override void recoverFromOverflow() { // First, flush the marking stack, greying all objects referenced from it, // and tracking the left most grey from which the rescan will start. Address leftmostFlushed = markingStackFlusher.flushMarkingStack(); // Next, initiate the scan to recover from overflow. This consists of // visiting all grey objects between the leftmost flushed mark and the forward scan finger. // The rescan iterate over the mark bitmap, as the forward scan, except that it uses its own finger. // // As for a normal scan, any reference pointing after the "rescan" finger are marked grey and not visited, they // will be visited as the rescan finger pass over them. // Any reference before the finger are marked grey and pushed on the marking stack. // The scan stops when reaching the forward scan finger (which act // as the rightmost bound for this scan). // If the marking stack overflow again, we flush the stack again and write down the leftmost mark // for the next scan. if (!isRecovering()) { beginRecovery(); startOfNextOverflowScan = leftmostFlushed; final Address forwardScanFinger = endOfScan; do { verifyHasNoGreyMarks(startOfNextOverflowScan); finger = startOfNextOverflowScan; startOfNextOverflowScan = forwardScanFinger; visitGreyObjects(); } while (startOfNextOverflowScan.lessThan(forwardScanFinger)); endRecovery(); numMarkinkgStackOverflow = 0; } else if (leftmostFlushed.lessThan(startOfNextOverflowScan)) { numMarkinkgStackOverflow++; // Schedule another rescan if the leftmost flushed cell is before the // currently visited cell. startOfNextOverflowScan = leftmostFlushed; } } }