/* * 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.vm.heap.gcx; import static com.sun.max.vm.heap.gcx.HeapRegionConstants.*; import com.sun.max.annotate.*; /** * An iterator over a {@link HeapRegionList}. * The iterator return ranges of contiguous regions in the order of the list. * By default, ranges only comprise {@link HeapRegionInfo.Flag#IS_ITERABLE} regions. * The default can be changed to return ranges of regions whose state matches any {@link HeapRegionInfo.Flag} from a set * specified using the {@link #clearMatchingFlags()} and {@link #addMatchingFlags(com.sun.max.vm.heap.gcx.HeapRegionInfo.Flag)}. */ public final class HeapRegionRangeIterable extends HeapRegionListIterable { int matchingFlags; public HeapRegionRangeIterable() { resetMatchingFlags(); } public void resetMatchingFlags() { matchingFlags = HeapRegionInfo.Flag.IS_ITERABLE.or(0); } public void clearMatchingFlags() { matchingFlags = 0; } public void addMatchingFlags(HeapRegionInfo.Flag flag) { this.matchingFlags = flag.or(matchingFlags); } public RegionRange next() { final int firstRegion = cursor; int endRange = cursor + 1; int next = regionList.next(cursor); while (next == endRange) { endRange++; next = regionList.next(next); } final int numRegions = endRange - firstRegion; cursor = next; return RegionRange.from(firstRegion, numRegions); } /** * Reset the iterator to the first iterable region if any. * @see HeapRegionInfo#isIterable() */ public void resetToFirstIterable() { reset(); nextIterable(); } @INLINE private boolean isIterable(HeapRegionInfo rinfo) { return (rinfo.flags & matchingFlags) != 0; } @INLINE private boolean isIterable(HeapRegionInfo rinfo, int tag) { return rinfo.tag == tag && (rinfo.flags & matchingFlags) != 0; } private void nextIterable() { final RegionTable theRegionTable = RegionTable.theRegionTable(); while (cursor != INVALID_REGION_ID) { if (isIterable(theRegionTable.regionInfo(cursor))) { return; } cursor = regionList.next(cursor); } } public RegionRange nextIterableRange() { final int firstRegion = cursor; int endRange = cursor + 1; int next = regionList.next(cursor); final RegionTable theRegionTable = RegionTable.theRegionTable(); while (next == endRange) { if (!isIterable(theRegionTable.regionInfo(next))) { break; } endRange++; next = regionList.next(next); } final int numRegions = endRange - firstRegion; cursor = next; nextIterable(); return RegionRange.from(firstRegion, numRegions); } /** * Reset the iterator to the first iterable region if any. * @see HeapRegionInfo#isIterable() */ public void resetToFirstIterable(int tag) { reset(); nextIterable(tag); } private void nextIterable(int tag) { final RegionTable theRegionTable = RegionTable.theRegionTable(); while (cursor != INVALID_REGION_ID) { if (isIterable(theRegionTable.regionInfo(cursor), tag)) { return; } cursor = regionList.next(cursor); } } public RegionRange nextIterableRange(int tag) { final int firstRegion = cursor; int endRange = cursor + 1; int next = regionList.next(cursor); final RegionTable theRegionTable = RegionTable.theRegionTable(); while (next == endRange) { if (!isIterable(theRegionTable.regionInfo(next), tag)) { break; } endRange++; next = regionList.next(next); } final int numRegions = endRange - firstRegion; cursor = next; nextIterable(tag); return RegionRange.from(firstRegion, numRegions); } }