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.utility;
014    
015    import org.mmtk.vm.VM;
016    import org.vmmagic.pragma.Uninterruptible;
017    import org.vmmagic.unboxed.Address;
018    import org.vmmagic.unboxed.ObjectReference;
019    
020    /**
021     * This class provides generic support for operations over the GC byte
022     * within each object's header word. Specifically this class manages
023     * global status bits which cut across policies (for example the logging bit).<p>
024     *
025     * The general pattern for use of the GC byte is that the high order bits
026     * successively reserved for global use, as necessary.  Any GC policy may use
027     * those bits that are not reserved for global use.<p>
028     */
029    @Uninterruptible
030    public class HeaderByte {
031      private static final int TOTAL_BITS = 8;
032    
033      public static final boolean NEEDS_UNLOGGED_BIT = VM.activePlan.constraints().needsLogBitInHeader();
034      private static final int UNLOGGED_BIT_NUMBER = TOTAL_BITS - (NEEDS_UNLOGGED_BIT ? 1 : 0);
035      public static final byte UNLOGGED_BIT = (byte) (1<<UNLOGGED_BIT_NUMBER);
036      public static final int USED_GLOBAL_BITS = TOTAL_BITS - UNLOGGED_BIT_NUMBER;
037    
038    
039      /**
040       * Perform any required initialization of the GC portion of the header.
041       * Called for objects created at boot time.
042       *
043       * @param ref the object ref to the storage to be initialized
044       * @param typeRef the type reference for the instance being created
045       * @param size the number of bytes allocated by the GC system for
046       * this object.
047       * @param status the initial value of the status word
048       * @return The new value of the status word
049       */
050      public static byte setBuildTimeGCByte(Address object, ObjectReference typeRef, int size) {
051        byte status = 0;
052    
053        if (NEEDS_UNLOGGED_BIT)
054          status |= UNLOGGED_BIT;
055        return status;
056      }
057    
058    
059      public static void markAsUnlogged(ObjectReference object) {
060        byte value = VM.objectModel.readAvailableByte(object);
061        VM.objectModel.writeAvailableByte(object, (byte) (value | UNLOGGED_BIT));
062      }
063    
064      /**
065       * Mark an object as logged.  Since duplicate logging does
066       * not raise any correctness issues, we do <i>not</i> worry
067       * about synchronization and allow threads to race to log the
068       * object, potentially including it twice (unlike reference
069       * counting where duplicates would lead to incorrect reference
070       * counts).
071       *
072       * @param object The object to be marked as logged
073       */
074      public static void markAsLogged(ObjectReference object) {
075        byte value = VM.objectModel.readAvailableByte(object);
076        VM.objectModel.writeAvailableByte(object, (byte) (value & ~UNLOGGED_BIT));
077      }
078    
079      /**
080       * Return true if the specified object needs to be logged.
081       *
082       * @param object The object in question
083       * @return True if the object in question needs to be logged (remembered).
084       */
085      public static boolean isUnlogged(ObjectReference object) {
086        byte value = VM.objectModel.readAvailableByte(object);
087        return (value & UNLOGGED_BIT) == UNLOGGED_BIT;
088      }
089    }