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.policy; 014 015 import org.mmtk.plan.Plan; 016 import org.mmtk.plan.TransitiveClosure; 017 import org.mmtk.utility.heap.MonotonePageResource; 018 import org.mmtk.utility.heap.VMRequest; 019 import org.mmtk.utility.Constants; 020 import org.mmtk.utility.HeaderByte; 021 022 import org.mmtk.vm.VM; 023 024 import org.vmmagic.unboxed.*; 025 import org.vmmagic.pragma.*; 026 027 /** 028 * This class implements tracing for a simple immortal collection 029 * policy. Under this policy all that is required is for the 030 * "collector" to propagate marks in a liveness trace. It does not 031 * actually collect. This class does not hold any state, all methods 032 * are static. 033 */ 034 @Uninterruptible public final class ImmortalSpace extends Space 035 implements Constants { 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() { return Word.fromIntZeroExtend(markState); } 096 097 /**************************************************************************** 098 * 099 * Object header manipulations 100 */ 101 102 /** 103 * Initialize the object header post-allocation. We need to set the mark state 104 * correctly and set the logged bit if necessary. 105 * 106 * @param object The newly allocated object instance whose header we are initializing 107 */ 108 public void initializeHeader(ObjectReference object) { 109 byte oldValue = VM.objectModel.readAvailableByte(object); 110 byte newValue = (byte) ((oldValue & GC_MARK_BIT_MASK) | markState); 111 if (HeaderByte.NEEDS_UNLOGGED_BIT) newValue |= HeaderByte.UNLOGGED_BIT; 112 VM.objectModel.writeAvailableByte(object, newValue); 113 } 114 115 /** 116 * Used to mark boot image objects during a parallel scan of objects during GC 117 * Returns {@code true} if marking was done. 118 */ 119 @Inline 120 private static boolean testAndMark(ObjectReference object, byte value) { 121 Word oldValue; 122 do { 123 oldValue = VM.objectModel.prepareAvailableBits(object); 124 byte markBit = (byte) (oldValue.toInt() & GC_MARK_BIT_MASK); 125 if (markBit == value) return false; 126 } while (!VM.objectModel.attemptAvailableBits(object, oldValue, 127 oldValue.xor(Word.fromIntZeroExtend(GC_MARK_BIT_MASK)))); 128 return true; 129 } 130 131 /** 132 * Trace a reference to an object under an immortal collection 133 * policy. If the object is not already marked, enqueue the object 134 * for subsequent processing. The object is marked as (an atomic) 135 * side-effect of checking whether already marked. 136 * 137 * @param trace The trace being conducted. 138 * @param object The object to be traced. 139 */ 140 @Override 141 @Inline 142 public ObjectReference traceObject(TransitiveClosure trace, ObjectReference object) { 143 if (testAndMark(object, markState)) 144 trace.processNode(object); 145 return object; 146 } 147 148 /** 149 * Prepare for a new collection increment. For the immortal 150 * collector we must flip the state of the mark bit between 151 * collections. 152 */ 153 public void prepare() { 154 markState = (byte) (GC_MARK_BIT_MASK - markState); 155 } 156 157 public void release() {} 158 159 /** 160 * Release an allocated page or pages. In this case we do nothing 161 * because we only release pages enmasse. 162 * 163 * @param start The address of the start of the page or pages 164 */ 165 @Override 166 @Inline 167 public void release(Address start) { 168 if (VM.VERIFY_ASSERTIONS) 169 VM.assertions._assert(false); // this policy only releases pages enmasse 170 } 171 172 @Override 173 @Inline 174 public boolean isLive(ObjectReference object) { 175 return true; 176 } 177 178 /** 179 * Returns if the object in question is currently thought to be reachable. 180 * This is done by comparing the mark bit to the current mark state. For the 181 * immortal collector reachable and live are different, making this method 182 * necessary. 183 * 184 * @param object The address of an object in immortal space to test 185 * @return <code>true</code> if <code>ref</code> may be a reachable object (e.g., having 186 * the current mark state). While all immortal objects are live, 187 * some may be unreachable. 188 */ 189 @Override 190 public boolean isReachable(ObjectReference object) { 191 if (Plan.SCAN_BOOT_IMAGE && this == Plan.vmSpace) 192 return true; // ignore boot image "reachabilty" if we're not tracing it 193 else 194 return (VM.objectModel.readAvailableByte(object) & GC_MARK_BIT_MASK) == markState; 195 } 196 }