blob: aba8620d9215d2155669a2966dd776d1e9786d85 [file] [log] [blame]
/*
* 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;
}
}