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 */ 013package org.mmtk.policy; 014 015import static org.mmtk.utility.Constants.*; 016 017import org.mmtk.plan.Plan; 018import org.mmtk.plan.TransitiveClosure; 019import org.mmtk.utility.heap.MonotonePageResource; 020import org.mmtk.utility.heap.VMRequest; 021import org.mmtk.utility.HeaderByte; 022 023import org.mmtk.vm.VM; 024 025import org.vmmagic.unboxed.*; 026import org.vmmagic.pragma.*; 027 028/** 029 * This class implements tracing for a simple immortal collection 030 * policy. Under this policy all that is required is for the 031 * "collector" to propagate marks in a liveness trace. It does not 032 * actually collect. This class does not hold any state, all methods 033 * are static. 034 */ 035@Uninterruptible public final class ImmortalSpace extends Space { 036 037 /**************************************************************************** 038 * 039 * Class variables 040 */ 041 042 /** 043 * 044 */ 045 static final byte GC_MARK_BIT_MASK = 1; 046 private static final int META_DATA_PAGES_PER_REGION = CARD_META_PAGES_PER_REGION; 047 048 /**************************************************************************** 049 * 050 * Instance variables 051 */ 052 053 /** 054 * 055 */ 056 private byte markState = 0; // when GC off, the initialization value 057 058 /**************************************************************************** 059 * 060 * Initialization 061 */ 062 063 /** 064 * The caller specifies the region of virtual memory to be used for 065 * this space. If this region conflicts with an existing space, 066 * then the constructor will fail. 067 * 068 * @param name The name of this space (used when printing error messages etc) 069 * @param vmRequest An object describing the virtual memory requested. 070 */ 071 public ImmortalSpace(String name, VMRequest vmRequest) { 072 this(name, true, vmRequest); 073 } 074 075 /** 076 * The caller specifies the region of virtual memory to be used for 077 * this space. If this region conflicts with an existing space, 078 * then the constructor will fail. 079 * 080 * @param name The name of this space (used when printing error messages etc) 081 * @param zeroed if true, allocations return zeroed memory. 082 * @param vmRequest An object describing the virtual memory requested. 083 */ 084 public ImmortalSpace(String name, boolean zeroed, VMRequest vmRequest) { 085 super(name, false, true, zeroed, vmRequest); 086 if (vmRequest.isDiscontiguous()) { 087 pr = new MonotonePageResource(this, META_DATA_PAGES_PER_REGION); 088 } else { 089 pr = new MonotonePageResource(this, start, extent, META_DATA_PAGES_PER_REGION); 090 } 091 } 092 093 /** @return the current mark state */ 094 @Inline 095 public Word getMarkState() { 096 return Word.fromIntZeroExtend(markState); 097 } 098 099 /**************************************************************************** 100 * 101 * Object header manipulations 102 */ 103 104 /** 105 * Initialize the object header post-allocation. We need to set the mark state 106 * correctly and set the logged bit if necessary. 107 * 108 * @param object The newly allocated object instance whose header we are initializing 109 */ 110 public void initializeHeader(ObjectReference object) { 111 byte oldValue = VM.objectModel.readAvailableByte(object); 112 byte newValue = (byte) ((oldValue & GC_MARK_BIT_MASK) | markState); 113 if (HeaderByte.NEEDS_UNLOGGED_BIT) newValue |= HeaderByte.UNLOGGED_BIT; 114 VM.objectModel.writeAvailableByte(object, newValue); 115 } 116 117 /** 118 * Used to mark boot image objects during a parallel scan of objects during GC. 119 * 120 * @param object the object to mark 121 * @param value the mark value 122 * @return {@code true} if marking was done. 123 */ 124 @Inline 125 private static boolean testAndMark(ObjectReference object, byte value) { 126 Word oldValue; 127 do { 128 oldValue = VM.objectModel.prepareAvailableBits(object); 129 byte markBit = (byte) (oldValue.toInt() & GC_MARK_BIT_MASK); 130 if (markBit == value) return false; 131 } while (!VM.objectModel.attemptAvailableBits(object, oldValue, 132 oldValue.xor(Word.fromIntZeroExtend(GC_MARK_BIT_MASK)))); 133 return true; 134 } 135 136 /** 137 * Trace a reference to an object under an immortal collection 138 * policy. If the object is not already marked, enqueue the object 139 * for subsequent processing. The object is marked as (an atomic) 140 * side-effect of checking whether already marked. 141 * 142 * @param trace The trace being conducted. 143 * @param object The object to be traced. 144 */ 145 @Override 146 @Inline 147 public ObjectReference traceObject(TransitiveClosure trace, ObjectReference object) { 148 if (testAndMark(object, markState)) 149 trace.processNode(object); 150 return object; 151 } 152 153 /** 154 * Prepare for a new collection increment. For the immortal 155 * collector we must flip the state of the mark bit between 156 * collections. 157 */ 158 public void prepare() { 159 markState = (byte) (GC_MARK_BIT_MASK - markState); 160 } 161 162 public void release() {} 163 164 /** 165 * Release an allocated page or pages. In this case we do nothing 166 * because we only release pages enmasse. 167 * 168 * @param start The address of the start of the page or pages 169 */ 170 @Override 171 @Inline 172 public void release(Address start) { 173 if (VM.VERIFY_ASSERTIONS) 174 VM.assertions._assert(false); // this policy only releases pages enmasse 175 } 176 177 @Override 178 @Inline 179 public boolean isLive(ObjectReference object) { 180 return true; 181 } 182 183 /** 184 * Returns if the object in question is currently thought to be reachable. 185 * This is done by comparing the mark bit to the current mark state. For the 186 * immortal collector reachable and live are different, making this method 187 * necessary. 188 * 189 * @param object The address of an object in immortal space to test 190 * @return <code>true</code> if <code>ref</code> may be a reachable object (e.g., having 191 * the current mark state). While all immortal objects are live, 192 * some may be unreachable. 193 */ 194 @Override 195 public boolean isReachable(ObjectReference object) { 196 if (Plan.SCAN_BOOT_IMAGE && this == Plan.vmSpace) 197 return true; // ignore boot image "reachabilty" if we're not tracing it 198 else 199 return (VM.objectModel.readAvailableByte(object) & GC_MARK_BIT_MASK) == markState; 200 } 201}