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 */
013 package org.mmtk.policy.immix;
014
015 import org.mmtk.utility.ForwardingWord;
016 import org.mmtk.utility.HeaderByte;
017 import org.mmtk.vm.VM;
018 import org.vmmagic.pragma.Inline;
019 import org.vmmagic.pragma.Uninterruptible;
020 import org.vmmagic.unboxed.ObjectReference;
021
022 @Uninterruptible
023 public 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 increment If {@code true}, then return the incremented value else return the decremented value
173 * @return the mark state incremented or decremented by one.
174 */
175 static byte deltaMarkState(byte state, boolean increment) {
176 byte rtn = state;
177 do {
178 rtn = (byte) (increment ? rtn + MARK_INCREMENT : rtn - MARK_INCREMENT);
179 rtn &= MARK_MASK;
180 } while (rtn < MARK_BASE_VALUE);
181 if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(rtn != state);
182 return rtn;
183 }
184 }