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 public static final int LOCAL_GC_BITS_REQUIRED = AVAILABLE_LOCAL_BITS;
029 public static final int GLOBAL_GC_BITS_REQUIRED = 0;
030 public static final int GC_HEADER_WORDS_REQUIRED = 0;
031
032 /* local status bits */
033 static final byte NEW_OBJECT_MARK = 0; // using zero means no need for explicit initialization on allocation
034
035 public static final int PINNED_BIT_NUMBER = ForwardingWord.FORWARDING_BITS;
036 public static final byte PINNED_BIT = 1<<PINNED_BIT_NUMBER;
037
038 private static final int STRADDLE_BIT_NUMBER = PINNED_BIT_NUMBER + 1;
039 public static final byte STRADDLE_BIT = 1<<STRADDLE_BIT_NUMBER;
040
041 /* mark bits */
042 private static final int MARK_BASE = STRADDLE_BIT_NUMBER+1;
043 static final int MAX_MARKCOUNT_BITS = AVAILABLE_LOCAL_BITS-MARK_BASE;
044 private static final byte MARK_INCREMENT = 1<<MARK_BASE;
045 public static final byte MARK_MASK = (byte) (((1<<MAX_MARKCOUNT_BITS)-1)<<MARK_BASE);
046 private static final byte MARK_AND_FORWARDING_MASK = (byte) (MARK_MASK | ForwardingWord.FORWARDING_MASK);
047 public static final byte MARK_BASE_VALUE = MARK_INCREMENT;
048
049
050 /****************************************************************************
051 *
052 * Marking
053 */
054
055 /**
056 * Non-atomically test and set the mark bit of an object. Return true
057 * if successful, false if the mark bit was already set.
058 *
059 * @param object The object whose mark bit is to be written
060 * @param markState The value to which the mark bits will be set
061 */
062 static byte testAndMark(ObjectReference object, byte markState) {
063 byte oldValue, newValue, oldMarkState;
064
065 oldValue = VM.objectModel.readAvailableByte(object);
066 oldMarkState = (byte) (oldValue & MARK_MASK);
067 if (oldMarkState != markState) {
068 newValue = (byte) ((oldValue & ~MARK_MASK) | markState);
069 if (HeaderByte.NEEDS_UNLOGGED_BIT)
070 newValue |= HeaderByte.UNLOGGED_BIT;
071 VM.objectModel.writeAvailableByte(object, newValue);
072 }
073 return oldMarkState;
074 }
075
076 static void setMarkStateUnlogAndUnlock(ObjectReference object, byte originalHeaderByte, byte markState) {
077 byte oldValue = originalHeaderByte;
078 byte newValue = (byte) ((oldValue & ~MARK_AND_FORWARDING_MASK) | markState);
079 if (HeaderByte.NEEDS_UNLOGGED_BIT)
080 newValue |= HeaderByte.UNLOGGED_BIT;
081 VM.objectModel.writeAvailableByte(object, newValue);
082 if (VM.VERIFY_ASSERTIONS)
083 VM.assertions._assert((oldValue & MARK_MASK) != markState);
084 }
085
086 /**
087 * Return true if the mark count for an object has the given value.
088 *
089 * @param object The object whose mark bit is to be tested
090 * @param value The value against which the mark bit will be tested
091 * @return True if the mark bit for the object has the given value.
092 */
093 static boolean testMarkState(ObjectReference object, byte value) {
094 if (VM.VERIFY_ASSERTIONS) VM.assertions._assert((value & MARK_MASK) == value);
095 return (VM.objectModel.readAvailableByte(object) & MARK_MASK) == value;
096 }
097
098 static boolean testMarkState(byte forwardingWord, byte value) {
099 if (VM.VERIFY_ASSERTIONS) VM.assertions._assert((value & MARK_MASK) == value);
100 return (forwardingWord & MARK_MASK) == value;
101 }
102
103 static boolean isNewObject(ObjectReference object) {
104 return (VM.objectModel.readAvailableByte(object) & MARK_AND_FORWARDING_MASK) == NEW_OBJECT_MARK;
105 }
106
107 static boolean isMatureObject(ObjectReference object) {
108 byte status = (byte) (VM.objectModel.readAvailableByte(object) & MARK_AND_FORWARDING_MASK);
109 boolean unforwarded = (status & ForwardingWord.FORWARDING_MASK) == 0;
110 boolean newObj = (status == NEW_OBJECT_MARK);
111 return unforwarded && !newObj;
112 }
113
114 @Inline
115 static void markAsStraddling(ObjectReference object) {
116 byte old = VM.objectModel.readAvailableByte(object);
117 VM.objectModel.writeAvailableByte(object, (byte) (old | STRADDLE_BIT));
118 }
119
120 @Inline
121 static boolean isStraddlingObject(ObjectReference object) {
122 return (VM.objectModel.readAvailableByte(object) & STRADDLE_BIT) == STRADDLE_BIT;
123 }
124
125 @Inline
126 public static void pinObject(ObjectReference object) {
127 byte old = VM.objectModel.readAvailableByte(object);
128 VM.objectModel.writeAvailableByte(object, (byte) (old | PINNED_BIT));
129 }
130
131 @Inline
132 static boolean isPinnedObject(ObjectReference object) {
133 return (VM.objectModel.readAvailableByte(object) & PINNED_BIT) == PINNED_BIT;
134 }
135
136 /**
137 * Write the allocState into the mark state fields of an object non-atomically.
138 * This is appropriate for collection time initialization.
139 *
140 * @param object The object whose mark state is to be written
141 * @param markState TODO: what am I?
142 * @param straddle TODO: what am I?
143 */
144 static void writeMarkState(ObjectReference object, byte markState, boolean straddle) {
145 byte oldValue = VM.objectModel.readAvailableByte(object);
146 byte markValue = markState;
147 byte newValue = (byte) (oldValue & ~MARK_AND_FORWARDING_MASK);
148 if (HeaderByte.NEEDS_UNLOGGED_BIT)
149 newValue |= HeaderByte.UNLOGGED_BIT;
150 newValue |= markValue;
151 if (straddle)
152 newValue |= STRADDLE_BIT;
153 VM.objectModel.writeAvailableByte(object, newValue);
154 }
155
156 static void returnToPriorStateAndEnsureUnlogged(ObjectReference object, byte status) {
157 if (HeaderByte.NEEDS_UNLOGGED_BIT) status |= HeaderByte.UNLOGGED_BIT;
158 VM.objectModel.writeAvailableByte(object, status);
159 }
160
161 /**
162 * Return the mark state incremented or decremented by one.
163 *
164 * @param increment If true, then return the incremented value else return the decremented value
165 * @return the mark state incremented or decremented by one.
166 */
167 static byte deltaMarkState(byte state, boolean increment) {
168 byte rtn = state;
169 do {
170 rtn = (byte) (increment ? rtn + MARK_INCREMENT : rtn - MARK_INCREMENT);
171 rtn &= MARK_MASK;
172 } while (rtn < MARK_BASE_VALUE);
173 if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(rtn != state);
174 return rtn;
175 }
176 }