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.<p>
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.<p>
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.<p>
052 */
053 @Uninterruptible
054 public class StickyMS extends MS {
055
056 /****************************************************************************
057 * Constants
058 */
059
060 /** If {@code true}, then new PLOS objects are collected at each nursery GC */
061 static final boolean NURSERY_COLLECT_PLOS = true;
062 /** If {@code true} then we only do full heap GCs---so we're like MarkSweep (+ write barrier) */
063 static final boolean MAJOR_GC_ONLY = false;
064
065 /****************************************************************************
066 * Class variables
067 */
068
069 /**
070 *
071 */
072 public static int SCAN_NURSERY = 1;
073
074 /****************************************************************************
075 * Instance variables
076 */
077
078 /* status fields */
079
080 /** will the next collection collect the whole heap? */
081 public boolean nextGCWholeHeap = false;
082 /** will this collection collect the whole heap */
083 public boolean collectWholeHeap = nextGCWholeHeap;
084
085 /** Remset pool */
086 public final SharedDeque modPool = new SharedDeque("msgen mod objects", metaDataSpace, 1);
087
088 /****************************************************************************
089 * Static initialization
090 */
091 {
092 msSpace.makeAgeSegregatedSpace(); /* this space is to be collected generationally */
093 }
094
095 /*****************************************************************************
096 *
097 * Collection
098 */
099
100 /**
101 * A user-triggered GC has been initiated.
102 */
103 public void userTriggeredGC() {
104 nextGCWholeHeap |= Options.fullHeapSystemGC.getValue();
105 }
106
107 @Override
108 public void forceFullHeapCollection() {
109 nextGCWholeHeap = true;
110 }
111
112 @Inline
113 @Override
114 public final void collectionPhase(short phaseId) {
115
116 if (phaseId == INITIATE) {
117 collectWholeHeap = MAJOR_GC_ONLY || emergencyCollection || nextGCWholeHeap;
118 nextGCWholeHeap = false;
119 super.collectionPhase(phaseId);
120 return;
121 }
122
123 if (!collectWholeHeap) {
124 if (phaseId == PREPARE) {
125 msTrace.prepare();
126 msSpace.prepare(false);
127 return;
128 }
129
130 if (phaseId == RELEASE) {
131 msTrace.release();
132 msSpace.release();
133 modPool.reset();
134 nextGCWholeHeap = (getPagesAvail() < Options.nurserySize.getMinNursery());
135 return;
136 }
137 }
138
139 super.collectionPhase(phaseId);
140 }
141
142 /*****************************************************************************
143 *
144 * Accounting
145 */
146
147 /**
148 * {@inheritDoc}
149 * In this class we prefix the output
150 * indicating whether the collection was full heap or not.
151 */
152 @Override
153 public void printPreStats() {
154 if ((Options.verbose.getValue() >= 1) && (collectWholeHeap))
155 Log.write("[Full heap]");
156 super.printPreStats();
157 }
158
159 @Override
160 public final boolean isCurrentGCNursery() {
161 return !collectWholeHeap;
162 }
163
164 /**
165 * @return Is last GC a full collection?
166 */
167 public final boolean isLastGCFull() {
168 return collectWholeHeap;
169 }
170
171 @Override
172 public int sanityExpectedRC(ObjectReference object, int sanityRootRC) {
173 Space space = Space.getSpaceForObject(object);
174
175 // Immortal spaces
176 if (space == StickyMS.immortalSpace || space == StickyMS.vmSpace) {
177 return space.isReachable(object) ? SanityChecker.ALIVE : SanityChecker.DEAD;
178 }
179
180 // Mature space (nursery collection)
181 if (VM.activePlan.global().isCurrentGCNursery() && space != StickyMS.msSpace) {
182 return SanityChecker.UNSURE;
183 }
184
185 return super.sanityExpectedRC(object, sanityRootRC);
186 }
187
188 @Override
189 @Interruptible
190 protected void registerSpecializedMethods() {
191 TransitiveClosure.registerSpecializedScan(SCAN_NURSERY, StickyMSNurseryTraceLocal.class);
192 super.registerSpecializedMethods();
193 }
194 }