/* * 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.vm.heap.gcx; import static com.sun.max.vm.heap.gcx.HeapRegionInfo.Flag.*; import com.sun.max.annotate.*; import com.sun.max.collect.*; import com.sun.max.vm.*; import com.sun.max.vm.runtime.*; public enum HeapRegionState { EMPTY_REGION(0), ALLOCATING_REGION(IS_ALLOCATING.or(0)), FULL_REGION(IS_ITERABLE.or(0)), FREE_CHUNKS_REGION(IS_ITERABLE.or(HAS_FREE_CHUNK.or(0))), LARGE_HEAD(IS_ITERABLE.or(IS_LARGE.or(IS_HEAD.or(0)))), LARGE_BODY(IS_ITERABLE.or(IS_LARGE.or(0))), LARGE_FULL_TAIL(IS_ITERABLE.or(IS_LARGE.or(IS_TAIL.or(0)))), LARGE_TAIL(IS_ITERABLE.or(IS_LARGE.or(IS_TAIL.or(HAS_FREE_CHUNK.or(0))))), LARGE_ALLOCATING_TAIL(IS_ALLOCATING.or(IS_LARGE.or(IS_TAIL.or(0)))); private static final boolean [][] validStateTransitions = new boolean[HeapRegionState.values().length][HeapRegionState.values().length]; private static final IntHashMap<HeapRegionState> allValidStates = new IntHashMap<HeapRegionState>(values().length); /** * Initialize valid heap region state transitions. * @param fromState the state the heap region transitions from. * @param toStates the valid states the heap region may transition to. */ @HOSTED_ONLY static void initialize(HeapRegionState fromState, HeapRegionState [] toStates) { boolean [] stateTransitions = validStateTransitions[fromState.ordinal()]; for (HeapRegionState toState : toStates) { stateTransitions[toState.ordinal()] = true; } } static { for (HeapRegionState state : values()) { allValidStates.put(state.flags, state); } // Initialize the valid state transitions. // FIXME: may want to introduce a special "SWEPT" state to distinguish between valid empty->state transitions that correspond to sweeping transitions from the empty -> allocating // transitions. initialize(EMPTY_REGION, new HeapRegionState [] {EMPTY_REGION, ALLOCATING_REGION, FULL_REGION, FREE_CHUNKS_REGION, LARGE_HEAD, LARGE_BODY, LARGE_FULL_TAIL, LARGE_TAIL}); initialize(ALLOCATING_REGION, new HeapRegionState [] {FULL_REGION, FREE_CHUNKS_REGION}); initialize(FULL_REGION, new HeapRegionState [] {EMPTY_REGION, FREE_CHUNKS_REGION}); initialize(FREE_CHUNKS_REGION, new HeapRegionState [] {EMPTY_REGION, ALLOCATING_REGION, FREE_CHUNKS_REGION}); initialize(LARGE_HEAD, new HeapRegionState [] {EMPTY_REGION, FREE_CHUNKS_REGION}); initialize(LARGE_BODY, new HeapRegionState [] {EMPTY_REGION, FREE_CHUNKS_REGION}); initialize(LARGE_FULL_TAIL, new HeapRegionState [] {EMPTY_REGION, FREE_CHUNKS_REGION, LARGE_TAIL}); initialize(LARGE_TAIL, new HeapRegionState [] {EMPTY_REGION, LARGE_ALLOCATING_TAIL}); initialize(LARGE_ALLOCATING_TAIL, new HeapRegionState [] {LARGE_FULL_TAIL, LARGE_TAIL}); } static public boolean isValidTransition(HeapRegionState from, HeapRegionState to) { return validStateTransitions[from.ordinal()][to.ordinal()]; } /** * Return the HeapRegionState for the specified set of HeapRegionInfo flags, or null if the specified flags don't represent a valid state. * @param flags * @return a HeapRegionState, or null */ static HeapRegionState toHeapRegionState(int flags) { return allValidStates.get(flags); } final int flags; HeapRegionState(int flags) { this.flags = flags; } public final boolean isInState(HeapRegionInfo rinfo) { return rinfo.flags == flags; } private static void checkStateTransition(HeapRegionInfo rinfo, HeapRegionState to) { HeapRegionState from = toHeapRegionState(rinfo.flags); FatalError.check(from != null && to != null, "invalid heap state(s)"); if (!validStateTransitions[from.ordinal()][to.ordinal()]) { Log.print("Region #"); Log.print(RegionTable.theRegionTable().regionID(rinfo)); Log.print(" "); Log.print(from.toString()); Log.print(" -> "); Log.print(to.toString()); FatalError.unexpected(": not a valid HeapRegionInfo state transition"); } } public final void setState(HeapRegionInfo rinfo) { if (MaxineVM.isDebug()) { checkStateTransition(rinfo, this); } rinfo.flags = flags; } public static void toAllocatingState(HeapRegionInfo rinfo) { int flags = IS_ALLOCATING.or(HAS_FREE_CHUNK.clear(IS_ITERABLE.clear(rinfo.flags))); if (MaxineVM.isDebug()) { checkStateTransition(rinfo, toHeapRegionState(flags)); } rinfo.flags = flags; } public static void toFullState(HeapRegionInfo rinfo) { int flags = IS_ITERABLE.or(IS_ALLOCATING.clear(rinfo.flags)); if (MaxineVM.isDebug()) { checkStateTransition(rinfo, toHeapRegionState(flags)); } rinfo.flags = flags; } public static void toFreeChunkState(HeapRegionInfo rinfo) { int flags = IS_ITERABLE.or(HAS_FREE_CHUNK.or(IS_ALLOCATING.clear(rinfo.flags))); if (MaxineVM.isDebug()) { checkStateTransition(rinfo, toHeapRegionState(flags)); } rinfo.flags = flags; } }