| /* |
| * 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.utility; |
| |
| import org.mmtk.vm.VM; |
| import org.vmmagic.pragma.Uninterruptible; |
| import org.vmmagic.unboxed.Address; |
| import org.vmmagic.unboxed.ObjectReference; |
| |
| /** |
| * This class provides generic support for operations over the GC byte |
| * within each object's header word. Specifically this class manages |
| * global status bits which cut across policies (for example the logging bit).<p> |
| * |
| * The general pattern for use of the GC byte is that the high order bits |
| * successively reserved for global use, as necessary. Any GC policy may use |
| * those bits that are not reserved for global use.<p> |
| */ |
| @Uninterruptible |
| public class HeaderByte { |
| private static final int TOTAL_BITS = 8; |
| |
| public static final boolean NEEDS_UNLOGGED_BIT = VM.activePlan.constraints().needsLogBitInHeader(); |
| private static final int UNLOGGED_BIT_NUMBER = TOTAL_BITS - (NEEDS_UNLOGGED_BIT ? 1 : 0); |
| public static final byte UNLOGGED_BIT = (byte) (1<<UNLOGGED_BIT_NUMBER); |
| public static final int USED_GLOBAL_BITS = TOTAL_BITS - UNLOGGED_BIT_NUMBER; |
| |
| |
| /** |
| * Perform any required initialization of the GC portion of the header. |
| * Called for objects created at boot time. |
| * |
| * @param ref the object ref to the storage to be initialized |
| * @param typeRef the type reference for the instance being created |
| * @param size the number of bytes allocated by the GC system for |
| * this object. |
| * @param status the initial value of the status word |
| * @return The new value of the status word |
| */ |
| public static byte setBuildTimeGCByte(Address object, ObjectReference typeRef, int size) { |
| byte status = 0; |
| |
| if (NEEDS_UNLOGGED_BIT) |
| status |= UNLOGGED_BIT; |
| return status; |
| } |
| |
| |
| public static void markAsUnlogged(ObjectReference object) { |
| byte value = VM.objectModel.readAvailableByte(object); |
| VM.objectModel.writeAvailableByte(object, (byte) (value | UNLOGGED_BIT)); |
| } |
| |
| /** |
| * Mark an object as logged. Since duplicate logging does |
| * not raise any correctness issues, we do <i>not</i> worry |
| * about synchronization and allow threads to race to log the |
| * object, potentially including it twice (unlike reference |
| * counting where duplicates would lead to incorrect reference |
| * counts). |
| * |
| * @param object The object to be marked as logged |
| */ |
| public static void markAsLogged(ObjectReference object) { |
| byte value = VM.objectModel.readAvailableByte(object); |
| VM.objectModel.writeAvailableByte(object, (byte) (value & ~UNLOGGED_BIT)); |
| } |
| |
| /** |
| * Return true if the specified object needs to be logged. |
| * |
| * @param object The object in question |
| * @return True if the object in question needs to be logged (remembered). |
| */ |
| public static boolean isUnlogged(ObjectReference object) { |
| byte value = VM.objectModel.readAvailableByte(object); |
| return (value & UNLOGGED_BIT) == UNLOGGED_BIT; |
| } |
| } |