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.plan.stickyms;
014
015 import org.mmtk.plan.TransitiveClosure;
016 import org.mmtk.plan.marksweep.MS;
017 import org.mmtk.policy.Space;
018 import org.mmtk.utility.Log;
019 import org.mmtk.utility.deque.SharedDeque;
020 import org.mmtk.utility.options.Options;
021 import org.mmtk.utility.sanitychecker.SanityChecker;
022 import org.mmtk.vm.VM;
023
024 import org.vmmagic.pragma.*;
025 import org.vmmagic.unboxed.ObjectReference;
026
027 /**
028 * This class implements the global state of a simple sticky mark bits collector,
029 * based a simple on mark-sweep collector. The sticky mark bits algorithm is
030 * due to Demmers et al. (http://doi.acm.org/10.1145/96709.96735), and allows
031 * generational collection to be performed in a non-moving heap by overloading
032 * the role of mark bits to also indicate whether an object is new (nursery) or
033 * not. Thus nursery objects are identified by a bit in their header, not by
034 * where they lie within the address space. While Demmers et al. did their work
035 * in a conservative collector, here we have an exact collector, so we can use
036 * a regular write barrier, and don't need to use page protection etc.
037 *
038 * All plans make a clear distinction between <i>global</i> and
039 * <i>thread-local</i> activities, and divides global and local state
040 * into separate class hierarchies. Global activities must be
041 * synchronized, whereas no synchronization is required for
042 * thread-local activities. There is a single instance of Plan (or the
043 * appropriate sub-class), and a 1:1 mapping of PlanLocal to "kernel
044 * threads" (aka CPUs or in Jikes RVM, Processors). Thus instance
045 * methods of PlanLocal allow fast, unsychronized access to functions such as
046 * allocation and collection.
047 *
048 * The global instance defines and manages static resources
049 * (such as memory and virtual memory resources). This mapping of threads to
050 * instances is crucial to understanding the correctness and
051 * performance properties of MMTk plans.
052 */
053 @Uninterruptible
054 public class StickyMS extends MS {
055
056 /****************************************************************************
057 * Constants
058 */
059 /** If true, then new PLOS objects are collected at each nursery GC */
060 static final boolean NURSERY_COLLECT_PLOS = true;
061 /** If true then we only do full heap GCs---so we're like MarkSweep (+ write barrier) */
062 static final boolean MAJOR_GC_ONLY = false;
063
064 /****************************************************************************
065 * Class variables
066 */
067
068 public static int SCAN_NURSERY = 1;
069
070 /****************************************************************************
071 * Instance variables
072 */
073 /* status fields */
074 /** will the next collection collect the whole heap? */
075 public boolean nextGCWholeHeap = false;
076 /** will this collection collect the whole heap */
077 public boolean collectWholeHeap = nextGCWholeHeap;
078
079 /* Remset pool */
080 public final SharedDeque modPool = new SharedDeque("msgen mod objects", metaDataSpace, 1);
081
082 /****************************************************************************
083 * Static initialization
084 */
085 {
086 msSpace.makeAgeSegregatedSpace(); /* this space is to be collected generationally */
087 }
088
089 /*****************************************************************************
090 *
091 * Collection
092 */
093
094 /**
095 * A user-triggered GC has been initiated.
096 */
097 public void userTriggeredGC() {
098 nextGCWholeHeap |= Options.fullHeapSystemGC.getValue();
099 }
100
101 /**
102 * Force the next collection to be full heap.
103 */
104 @Override
105 public void forceFullHeapCollection() {
106 nextGCWholeHeap = true;
107 }
108
109 /**
110 * Perform a (global) collection phase.
111 *
112 * @param phaseId Collection phase to execute.
113 */
114 @Inline
115 @Override
116 public final void collectionPhase(short phaseId) {
117
118 if (phaseId == INITIATE) {
119 collectWholeHeap = MAJOR_GC_ONLY || emergencyCollection || nextGCWholeHeap;
120 nextGCWholeHeap = false;
121 super.collectionPhase(phaseId);
122 return;
123 }
124
125 if (!collectWholeHeap) {
126 if (phaseId == PREPARE) {
127 msTrace.prepare();
128 msSpace.prepare(false);
129 return;
130 }
131
132 if (phaseId == RELEASE) {
133 msTrace.release();
134 msSpace.release();
135 modPool.reset();
136 nextGCWholeHeap = (getPagesAvail() < Options.nurserySize.getMinNursery());
137 return;
138 }
139 }
140
141 super.collectionPhase(phaseId);
142 }
143
144 /*****************************************************************************
145 *
146 * Accounting
147 */
148
149 /**
150 * Print pre-collection statistics. In this class we prefix the output
151 * indicating whether the collection was full heap or not.
152 */
153 @Override
154 public void printPreStats() {
155 if ((Options.verbose.getValue() >= 1) && (collectWholeHeap))
156 Log.write("[Full heap]");
157 super.printPreStats();
158 }
159
160 /**
161 * @return Is current GC only collecting objects allocated since last GC.
162 */
163 public final boolean isCurrentGCNursery() {
164 return !collectWholeHeap;
165 }
166
167 /**
168 * @return Is last GC a full collection?
169 */
170 public final boolean isLastGCFull() {
171 return collectWholeHeap;
172 }
173
174 /**
175 * Return the expected reference count. For non-reference counting
176 * collectors this becomes a true/false relationship.
177 * @param object The object to check.
178 * @param sanityRootRC The number of root references to the object.
179 *
180 * @return The expected (root excluded) reference count.
181 */
182 public int sanityExpectedRC(ObjectReference object, int sanityRootRC) {
183 Space space = Space.getSpaceForObject(object);
184
185 // Immortal spaces
186 if (space == StickyMS.immortalSpace || space == StickyMS.vmSpace) {
187 return space.isReachable(object) ? SanityChecker.ALIVE : SanityChecker.DEAD;
188 }
189
190 // Mature space (nursery collection)
191 if (VM.activePlan.global().isCurrentGCNursery() && space != StickyMS.msSpace) {
192 return SanityChecker.UNSURE;
193 }
194
195 return super.sanityExpectedRC(object, sanityRootRC);
196 }
197
198 /**
199 * Register specialized methods.
200 */
201 @Interruptible
202 protected void registerSpecializedMethods() {
203 TransitiveClosure.registerSpecializedScan(SCAN_NURSERY, StickyMSNurseryTraceLocal.class);
204 super.registerSpecializedMethods();
205 }
206 }