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 object the Address representing 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 * @return The new value of the status word 048 */ 049 public static byte setBuildTimeGCByte(Address object, ObjectReference typeRef, int size) { 050 byte status = 0; 051 052 if (NEEDS_UNLOGGED_BIT) 053 status |= UNLOGGED_BIT; 054 return status; 055 } 056 057 058 public static void markAsUnlogged(ObjectReference object) { 059 byte value = VM.objectModel.readAvailableByte(object); 060 VM.objectModel.writeAvailableByte(object, (byte) (value | UNLOGGED_BIT)); 061 } 062 063 /** 064 * Mark an object as logged. Since duplicate logging does 065 * not raise any correctness issues, we do <i>not</i> worry 066 * about synchronization and allow threads to race to log the 067 * object, potentially including it twice (unlike reference 068 * counting where duplicates would lead to incorrect reference 069 * counts). 070 * 071 * @param object The object to be marked as logged 072 */ 073 public static void markAsLogged(ObjectReference object) { 074 byte value = VM.objectModel.readAvailableByte(object); 075 VM.objectModel.writeAvailableByte(object, (byte) (value & ~UNLOGGED_BIT)); 076 } 077 078 /** 079 * Return {@code true} if the specified object needs to be logged. 080 * 081 * @param object The object in question 082 * @return {@code true} if the object in question needs to be logged (remembered). 083 */ 084 public static boolean isUnlogged(ObjectReference object) { 085 byte value = VM.objectModel.readAvailableByte(object); 086 return (value & UNLOGGED_BIT) == UNLOGGED_BIT; 087 } 088 }