001/* 002 * This file is part of the Jikes RVM project (http://jikesrvm.org). 003 * 004 * This file is licensed to You under the Eclipse Public License (EPL); 005 * You may not use this file except in compliance with the License. You 006 * may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/eclipse-1.0.php 009 * 010 * See the COPYRIGHT.txt file distributed with this work for information 011 * regarding copyright ownership. 012 */ 013package org.mmtk.policy.immix; 014 015import org.mmtk.utility.ForwardingWord; 016import org.mmtk.utility.HeaderByte; 017import org.mmtk.vm.VM; 018import org.vmmagic.pragma.Inline; 019import org.vmmagic.pragma.Uninterruptible; 020import org.vmmagic.unboxed.ObjectReference; 021 022@Uninterruptible 023public class ObjectHeader { 024 /** number of header bits we may use */ 025 static final int AVAILABLE_LOCAL_BITS = 8 - HeaderByte.USED_GLOBAL_BITS; 026 027 /* header requirements */ 028 029 /** 030 * 031 */ 032 public static final int LOCAL_GC_BITS_REQUIRED = AVAILABLE_LOCAL_BITS; 033 public static final int GLOBAL_GC_BITS_REQUIRED = 0; 034 public static final int GC_HEADER_WORDS_REQUIRED = 0; 035 036 /* local status bits */ 037 static final byte NEW_OBJECT_MARK = 0; // using zero means no need for explicit initialization on allocation 038 039 public static final int PINNED_BIT_NUMBER = ForwardingWord.FORWARDING_BITS; 040 public static final byte PINNED_BIT = 1 << PINNED_BIT_NUMBER; 041 042 private static final int STRADDLE_BIT_NUMBER = PINNED_BIT_NUMBER + 1; 043 public static final byte STRADDLE_BIT = 1 << STRADDLE_BIT_NUMBER; 044 045 /* mark bits */ 046 047 /** 048 * 049 */ 050 private static final int MARK_BASE = STRADDLE_BIT_NUMBER + 1; 051 static final int MAX_MARKCOUNT_BITS = AVAILABLE_LOCAL_BITS - MARK_BASE; 052 private static final byte MARK_INCREMENT = 1 << MARK_BASE; 053 public static final byte MARK_MASK = (byte) (((1 << MAX_MARKCOUNT_BITS) - 1) << MARK_BASE); 054 private static final byte MARK_AND_FORWARDING_MASK = (byte) (MARK_MASK | ForwardingWord.FORWARDING_MASK); 055 public static final byte MARK_BASE_VALUE = MARK_INCREMENT; 056 057 058 /**************************************************************************** 059 * 060 * Marking 061 */ 062 063 /** 064 * Non-atomically test and set the mark bit of an object. 065 * 066 * @param object The object whose mark bit is to be written 067 * @param markState The value to which the mark bits will be set 068 * @return the old mark state 069 */ 070 static byte testAndMark(ObjectReference object, byte markState) { 071 byte oldValue, newValue, oldMarkState; 072 073 oldValue = VM.objectModel.readAvailableByte(object); 074 oldMarkState = (byte) (oldValue & MARK_MASK); 075 if (oldMarkState != markState) { 076 newValue = (byte) ((oldValue & ~MARK_MASK) | markState); 077 if (HeaderByte.NEEDS_UNLOGGED_BIT) 078 newValue |= HeaderByte.UNLOGGED_BIT; 079 VM.objectModel.writeAvailableByte(object, newValue); 080 } 081 return oldMarkState; 082 } 083 084 static void setMarkStateUnlogAndUnlock(ObjectReference object, byte gcByte, byte markState) { 085 byte oldGCByte = gcByte; 086 byte newGCByte = (byte) ((oldGCByte & ~MARK_AND_FORWARDING_MASK) | markState); 087 if (HeaderByte.NEEDS_UNLOGGED_BIT) 088 newGCByte |= HeaderByte.UNLOGGED_BIT; 089 VM.objectModel.writeAvailableByte(object, newGCByte); 090 if (VM.VERIFY_ASSERTIONS) 091 VM.assertions._assert((oldGCByte & MARK_MASK) != markState); 092 } 093 094 /** 095 * Return {@code true} if the mark count for an object has the given value. 096 * 097 * @param object The object whose mark bit is to be tested 098 * @param value The value against which the mark bit will be tested 099 * @return {@code true} if the mark bit for the object has the given value. 100 */ 101 static boolean testMarkState(ObjectReference object, byte value) { 102 if (VM.VERIFY_ASSERTIONS) VM.assertions._assert((value & MARK_MASK) == value); 103 return (VM.objectModel.readAvailableByte(object) & MARK_MASK) == value; 104 } 105 106 static boolean testMarkState(byte gcByte, byte value) { 107 if (VM.VERIFY_ASSERTIONS) VM.assertions._assert((value & MARK_MASK) == value); 108 return (gcByte & MARK_MASK) == value; 109 } 110 111 static boolean isNewObject(ObjectReference object) { 112 return (VM.objectModel.readAvailableByte(object) & MARK_AND_FORWARDING_MASK) == NEW_OBJECT_MARK; 113 } 114 115 static boolean isMatureObject(ObjectReference object) { 116 byte status = (byte) (VM.objectModel.readAvailableByte(object) & MARK_AND_FORWARDING_MASK); 117 boolean unforwarded = (status & ForwardingWord.FORWARDING_MASK) == 0; 118 boolean newObj = (status == NEW_OBJECT_MARK); 119 return unforwarded && !newObj; 120 } 121 122 @Inline 123 static void markAsStraddling(ObjectReference object) { 124 byte old = VM.objectModel.readAvailableByte(object); 125 VM.objectModel.writeAvailableByte(object, (byte) (old | STRADDLE_BIT)); 126 } 127 128 @Inline 129 static boolean isStraddlingObject(ObjectReference object) { 130 return (VM.objectModel.readAvailableByte(object) & STRADDLE_BIT) == STRADDLE_BIT; 131 } 132 133 @Inline 134 public static void pinObject(ObjectReference object) { 135 byte old = VM.objectModel.readAvailableByte(object); 136 VM.objectModel.writeAvailableByte(object, (byte) (old | PINNED_BIT)); 137 } 138 139 @Inline 140 static boolean isPinnedObject(ObjectReference object) { 141 return (VM.objectModel.readAvailableByte(object) & PINNED_BIT) == PINNED_BIT; 142 } 143 144 /** 145 * Write the allocState into the mark state fields of an object non-atomically. 146 * This is appropriate for collection time initialization. 147 * 148 * @param object The object whose mark state is to be written 149 * @param markState TODO: what am I? 150 * @param straddle TODO: what am I? 151 */ 152 static void writeMarkState(ObjectReference object, byte markState, boolean straddle) { 153 byte oldValue = VM.objectModel.readAvailableByte(object); 154 byte markValue = markState; 155 byte newValue = (byte) (oldValue & ~MARK_AND_FORWARDING_MASK); 156 if (HeaderByte.NEEDS_UNLOGGED_BIT) 157 newValue |= HeaderByte.UNLOGGED_BIT; 158 newValue |= markValue; 159 if (straddle) 160 newValue |= STRADDLE_BIT; 161 VM.objectModel.writeAvailableByte(object, newValue); 162 } 163 164 static void returnToPriorStateAndEnsureUnlogged(ObjectReference object, byte status) { 165 if (HeaderByte.NEEDS_UNLOGGED_BIT) status |= HeaderByte.UNLOGGED_BIT; 166 VM.objectModel.writeAvailableByte(object, status); 167 } 168 169 /** 170 * Return the mark state incremented or decremented by one. 171 * 172 * @param state the mark state 173 * @param increment If {@code true}, then return the incremented value else return the decremented value 174 * @return the mark state incremented or decremented by one. 175 */ 176 static byte deltaMarkState(byte state, boolean increment) { 177 byte rtn = state; 178 do { 179 rtn = (byte) (increment ? rtn + MARK_INCREMENT : rtn - MARK_INCREMENT); 180 rtn &= MARK_MASK; 181 } while (rtn < MARK_BASE_VALUE); 182 if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(rtn != state); 183 return rtn; 184 } 185}