| /* |
| * This file is part of the Jikes RVM project (http://jikesrvm.org). |
| * |
| * This file is licensed to You under the Eclipse Public License (EPL); |
| * You may not use this file except in compliance with the License. You |
| * may obtain a copy of the License at |
| * |
| * http://www.opensource.org/licenses/eclipse-1.0.php |
| * |
| * See the COPYRIGHT.txt file distributed with this work for information |
| * regarding copyright ownership. |
| */ |
| package org.mmtk.policy.immix; |
| |
| import org.mmtk.utility.ForwardingWord; |
| import org.mmtk.utility.HeaderByte; |
| import org.mmtk.vm.VM; |
| import org.vmmagic.pragma.Inline; |
| import org.vmmagic.pragma.Uninterruptible; |
| import org.vmmagic.unboxed.ObjectReference; |
| |
| @Uninterruptible |
| public class ObjectHeader { |
| /** number of header bits we may use */ |
| static final int AVAILABLE_LOCAL_BITS = 8 - HeaderByte.USED_GLOBAL_BITS; |
| |
| /* header requirements */ |
| public static final int LOCAL_GC_BITS_REQUIRED = AVAILABLE_LOCAL_BITS; |
| public static final int GLOBAL_GC_BITS_REQUIRED = 0; |
| public static final int GC_HEADER_WORDS_REQUIRED = 0; |
| |
| /* local status bits */ |
| static final byte NEW_OBJECT_MARK = 0; // using zero means no need for explicit initialization on allocation |
| |
| public static final int PINNED_BIT_NUMBER = ForwardingWord.FORWARDING_BITS; |
| public static final byte PINNED_BIT = 1<<PINNED_BIT_NUMBER; |
| |
| private static final int STRADDLE_BIT_NUMBER = PINNED_BIT_NUMBER + 1; |
| public static final byte STRADDLE_BIT = 1<<STRADDLE_BIT_NUMBER; |
| |
| /* mark bits */ |
| private static final int MARK_BASE = STRADDLE_BIT_NUMBER+1; |
| static final int MAX_MARKCOUNT_BITS = AVAILABLE_LOCAL_BITS-MARK_BASE; |
| private static final byte MARK_INCREMENT = 1<<MARK_BASE; |
| public static final byte MARK_MASK = (byte) (((1<<MAX_MARKCOUNT_BITS)-1)<<MARK_BASE); |
| private static final byte MARK_AND_FORWARDING_MASK = (byte) (MARK_MASK | ForwardingWord.FORWARDING_MASK); |
| public static final byte MARK_BASE_VALUE = MARK_INCREMENT; |
| |
| |
| /**************************************************************************** |
| * |
| * Marking |
| */ |
| |
| /** |
| * Non-atomically test and set the mark bit of an object. Return true |
| * if successful, false if the mark bit was already set. |
| * |
| * @param object The object whose mark bit is to be written |
| * @param markState The value to which the mark bits will be set |
| */ |
| static byte testAndMark(ObjectReference object, byte markState) { |
| byte oldValue, newValue, oldMarkState; |
| |
| oldValue = VM.objectModel.readAvailableByte(object); |
| oldMarkState = (byte) (oldValue & MARK_MASK); |
| if (oldMarkState != markState) { |
| newValue = (byte) ((oldValue & ~MARK_MASK) | markState); |
| if (HeaderByte.NEEDS_UNLOGGED_BIT) |
| newValue |= HeaderByte.UNLOGGED_BIT; |
| VM.objectModel.writeAvailableByte(object, newValue); |
| } |
| return oldMarkState; |
| } |
| |
| static void setMarkStateUnlogAndUnlock(ObjectReference object, byte originalHeaderByte, byte markState) { |
| byte oldValue = originalHeaderByte; |
| byte newValue = (byte) ((oldValue & ~MARK_AND_FORWARDING_MASK) | markState); |
| if (HeaderByte.NEEDS_UNLOGGED_BIT) |
| newValue |= HeaderByte.UNLOGGED_BIT; |
| VM.objectModel.writeAvailableByte(object, newValue); |
| if (VM.VERIFY_ASSERTIONS) |
| VM.assertions._assert((oldValue & MARK_MASK) != markState); |
| } |
| |
| /** |
| * Return true if the mark count for an object has the given value. |
| * |
| * @param object The object whose mark bit is to be tested |
| * @param value The value against which the mark bit will be tested |
| * @return True if the mark bit for the object has the given value. |
| */ |
| static boolean testMarkState(ObjectReference object, byte value) { |
| if (VM.VERIFY_ASSERTIONS) VM.assertions._assert((value & MARK_MASK) == value); |
| return (VM.objectModel.readAvailableByte(object) & MARK_MASK) == value; |
| } |
| |
| static boolean testMarkState(byte forwardingWord, byte value) { |
| if (VM.VERIFY_ASSERTIONS) VM.assertions._assert((value & MARK_MASK) == value); |
| return (forwardingWord & MARK_MASK) == value; |
| } |
| |
| static boolean isNewObject(ObjectReference object) { |
| return (VM.objectModel.readAvailableByte(object) & MARK_AND_FORWARDING_MASK) == NEW_OBJECT_MARK; |
| } |
| |
| static boolean isMatureObject(ObjectReference object) { |
| byte status = (byte) (VM.objectModel.readAvailableByte(object) & MARK_AND_FORWARDING_MASK); |
| boolean unforwarded = (status & ForwardingWord.FORWARDING_MASK) == 0; |
| boolean newObj = (status == NEW_OBJECT_MARK); |
| return unforwarded && !newObj; |
| } |
| |
| @Inline |
| static void markAsStraddling(ObjectReference object) { |
| byte old = VM.objectModel.readAvailableByte(object); |
| VM.objectModel.writeAvailableByte(object, (byte) (old | STRADDLE_BIT)); |
| } |
| |
| @Inline |
| static boolean isStraddlingObject(ObjectReference object) { |
| return (VM.objectModel.readAvailableByte(object) & STRADDLE_BIT) == STRADDLE_BIT; |
| } |
| |
| @Inline |
| public static void pinObject(ObjectReference object) { |
| byte old = VM.objectModel.readAvailableByte(object); |
| VM.objectModel.writeAvailableByte(object, (byte) (old | PINNED_BIT)); |
| } |
| |
| @Inline |
| static boolean isPinnedObject(ObjectReference object) { |
| return (VM.objectModel.readAvailableByte(object) & PINNED_BIT) == PINNED_BIT; |
| } |
| |
| /** |
| * Write the allocState into the mark state fields of an object non-atomically. |
| * This is appropriate for collection time initialization. |
| * |
| * @param object The object whose mark state is to be written |
| * @param markState TODO: what am I? |
| * @param straddle TODO: what am I? |
| */ |
| static void writeMarkState(ObjectReference object, byte markState, boolean straddle) { |
| byte oldValue = VM.objectModel.readAvailableByte(object); |
| byte markValue = markState; |
| byte newValue = (byte) (oldValue & ~MARK_AND_FORWARDING_MASK); |
| if (HeaderByte.NEEDS_UNLOGGED_BIT) |
| newValue |= HeaderByte.UNLOGGED_BIT; |
| newValue |= markValue; |
| if (straddle) |
| newValue |= STRADDLE_BIT; |
| VM.objectModel.writeAvailableByte(object, newValue); |
| } |
| |
| static void returnToPriorStateAndEnsureUnlogged(ObjectReference object, byte status) { |
| if (HeaderByte.NEEDS_UNLOGGED_BIT) status |= HeaderByte.UNLOGGED_BIT; |
| VM.objectModel.writeAvailableByte(object, status); |
| } |
| |
| /** |
| * Return the mark state incremented or decremented by one. |
| * |
| * @param increment If true, then return the incremented value else return the decremented value |
| * @return the mark state incremented or decremented by one. |
| */ |
| static byte deltaMarkState(byte state, boolean increment) { |
| byte rtn = state; |
| do { |
| rtn = (byte) (increment ? rtn + MARK_INCREMENT : rtn - MARK_INCREMENT); |
| rtn &= MARK_MASK; |
| } while (rtn < MARK_BASE_VALUE); |
| if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(rtn != state); |
| return rtn; |
| } |
| } |