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.plan.markcompact; 014 015import org.mmtk.plan.*; 016import org.mmtk.policy.MarkCompactSpace; 017import org.mmtk.policy.Space; 018import org.mmtk.utility.heap.VMRequest; 019import org.mmtk.utility.sanitychecker.SanityChecker; 020 021import org.vmmagic.pragma.*; 022import org.vmmagic.unboxed.ObjectReference; 023 024/** 025 * This class implements the global state of a simple sliding mark-compact 026 * collector.<p> 027 * 028 * FIXME Need algorithmic overview and references.<p> 029 * 030 * All plans make a clear distinction between <i>global</i> and 031 * <i>thread-local</i> activities, and divides global and local state 032 * into separate class hierarchies. Global activities must be 033 * synchronized, whereas no synchronization is required for 034 * thread-local activities. There is a single instance of Plan (or the 035 * appropriate sub-class), and a 1:1 mapping of PlanLocal to "kernel 036 * threads" (aka CPUs). Thus instance 037 * methods of PlanLocal allow fast, unsychronized access to functions such as 038 * allocation and collection.<p> 039 * 040 * The global instance defines and manages static resources 041 * (such as memory and virtual memory resources). This mapping of threads to 042 * instances is crucial to understanding the correctness and 043 * performance properties of MMTk plans. 044 */ 045@Uninterruptible public class MC extends StopTheWorld { 046 047 /**************************************************************************** 048 * Class variables 049 */ 050 051 /** The mark compact space itself */ 052 public static final MarkCompactSpace mcSpace = new MarkCompactSpace("mc", VMRequest.fraction(0.6f)); 053 054 /** The space descriptor */ 055 public static final int MARK_COMPACT = mcSpace.getDescriptor(); 056 057 /** Specialized method identifier for the MARK phase */ 058 public static final int SCAN_MARK = 0; 059 060 /** Specialized method identifier for the FORWARD phase */ 061 public static final int SCAN_FORWARD = 1; 062 063 /* Phases */ 064 public static final short PREPARE_FORWARD = Phase.createSimple("fw-prepare"); 065 public static final short FORWARD_CLOSURE = Phase.createSimple("fw-closure"); 066 public static final short RELEASE_FORWARD = Phase.createSimple("fw-release"); 067 068 /** Calculate forwarding pointers via a linear scan over the heap */ 069 public static final short CALCULATE_FP = Phase.createSimple("calc-fp"); 070 071 /** Perform compaction via a linear scan over the heap */ 072 public static final short COMPACT = Phase.createSimple("compact"); 073 074 // CHECKSTYLE:OFF 075 076 /** 077 * This is the phase that is executed to perform a mark-compact collection. 078 * 079 * FIXME: Far too much duplication and inside knowledge of StopTheWorld 080 */ 081 public short mcCollection = Phase.createComplex("collection", null, 082 Phase.scheduleComplex (initPhase), 083 Phase.scheduleComplex (rootClosurePhase), 084 Phase.scheduleComplex (refTypeClosurePhase), 085 Phase.scheduleComplex (completeClosurePhase), 086 Phase.scheduleCollector(CALCULATE_FP), 087 Phase.scheduleGlobal (PREPARE_FORWARD), 088 Phase.scheduleCollector(PREPARE_FORWARD), 089 Phase.scheduleMutator (PREPARE), 090 Phase.scheduleCollector(STACK_ROOTS), 091 Phase.scheduleCollector(ROOTS), 092 Phase.scheduleGlobal (ROOTS), 093 Phase.scheduleComplex (forwardPhase), 094 Phase.scheduleCollector(FORWARD_CLOSURE), 095 Phase.scheduleMutator (RELEASE), 096 Phase.scheduleCollector(RELEASE_FORWARD), 097 Phase.scheduleGlobal (RELEASE_FORWARD), 098 Phase.scheduleCollector(COMPACT), 099 Phase.scheduleComplex (finishPhase)); 100 101 // CHECKSTYLE:ON 102 103 /**************************************************************************** 104 * Instance variables 105 */ 106 107 /** This trace sets the mark bit in live objects */ 108 public final Trace markTrace; 109 110 /** This trace updates pointers with the forwarded references */ 111 public final Trace forwardTrace; 112 113 /** 114 * Constructor. 115 */ 116 public MC() { 117 markTrace = new Trace(metaDataSpace); 118 forwardTrace = new Trace(metaDataSpace); 119 collection = mcCollection; 120 } 121 122 /***************************************************************************** 123 * 124 * Collection 125 */ 126 127 128 /** 129 * {@inheritDoc} 130 */ 131 @Override 132 @Inline 133 public final void collectionPhase(short phaseId) { 134 if (phaseId == PREPARE) { 135 super.collectionPhase(phaseId); 136 markTrace.prepare(); 137 mcSpace.prepare(); 138 return; 139 } 140 if (phaseId == CLOSURE) { 141 markTrace.prepare(); 142 return; 143 } 144 if (phaseId == RELEASE) { 145 markTrace.release(); 146 mcSpace.release(); 147 super.collectionPhase(phaseId); 148 return; 149 } 150 151 if (phaseId == PREPARE_FORWARD) { 152 super.collectionPhase(PREPARE); 153 forwardTrace.prepare(); 154 mcSpace.prepare(); 155 return; 156 } 157 if (phaseId == RELEASE_FORWARD) { 158 forwardTrace.release(); 159 mcSpace.release(); 160 super.collectionPhase(RELEASE); 161 return; 162 } 163 164 super.collectionPhase(phaseId); 165 } 166 167 /***************************************************************************** 168 * 169 * Accounting 170 */ 171 172 /** 173 * {@inheritDoc} 174 * The superclass accounts for its spaces, we just 175 * augment this with the mark-sweep space's contribution. 176 */ 177 @Override 178 public int getPagesUsed() { 179 return (mcSpace.reservedPages() + super.getPagesUsed()); 180 } 181 182 @Override 183 public boolean willNeverMove(ObjectReference object) { 184 if (Space.isInSpace(MARK_COMPACT, object)) 185 return false; 186 return super.willNeverMove(object); 187 } 188 189 @Override 190 public int sanityExpectedRC(ObjectReference object, int sanityRootRC) { 191 Space space = Space.getSpaceForObject(object); 192 193 // Nursery 194 if (space == MC.mcSpace) { 195 // We are never sure about objects in MC. 196 // This is not very satisfying but allows us to use the sanity checker to 197 // detect dangling pointers. 198 return SanityChecker.UNSURE; 199 } 200 return super.sanityExpectedRC(object, sanityRootRC); 201 } 202 203 @Override 204 @Interruptible 205 protected void registerSpecializedMethods() { 206 TransitiveClosure.registerSpecializedScan(SCAN_MARK, MCMarkTraceLocal.class); 207 TransitiveClosure.registerSpecializedScan(SCAN_FORWARD, MCForwardTraceLocal.class); 208 super.registerSpecializedMethods(); 209 } 210}