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.semispace.gctrace;
014
015 import org.mmtk.plan.semispace.*;
016 import org.mmtk.policy.RawPageSpace;
017 import org.mmtk.utility.deque.SortTODSharedDeque;
018 import org.mmtk.utility.heap.VMRequest;
019 import org.mmtk.utility.TraceGenerator;
020 import org.mmtk.utility.options.Options;
021
022 import org.mmtk.vm.VM;
023
024 import org.vmmagic.pragma.*;
025
026 /**
027 * This plan has been modified slightly to perform the processing necessary
028 * for GC trace generation. To maximize performance, it attempts to remain
029 * as faithful as possible to semiSpace/Plan.java.
030 *
031 * The generated trace format is as follows:
032 * B 345678 12
033 * (Object 345678 was created in the boot image with a size of 12 bytes)
034 * U 59843 234 47298
035 * (Update object 59843 at the slot at offset 234 to refer to 47298)
036 * S 1233 12345
037 * (Update static slot 1233 to refer to 12345)
038 * T 4567 78924
039 * (The TIB of 4567 is set to refer to 78924)
040 * D 342789
041 * (Object 342789 became unreachable)
042 * A 6860 24 346648 3
043 * (Object 6860 was allocated, requiring 24 bytes, with fp 346648 on
044 * thread 3; this allocation has perfect knowledge)
045 * a 6884 24 346640 5
046 * (Object 6864 was allocated, requiring 24 bytes, with fp 346640 on
047 * thread 5; this allocation DOES NOT have perfect knowledge)
048 * I 6860 24 346648 3
049 * (Object 6860 was allocated into immortal space, requiring 24 bytes,
050 * with fp 346648 on thread 3; this allocation has perfect knowledge)
051 * i 6884 24 346640 5
052 * (Object 6864 was allocated into immortal space, requiring 24 bytes,
053 * with fp 346640 on thread 5; this allocation DOES NOT have perfect
054 * knowledge)
055 * 48954->[345]LObject;:blah()V:23 Ljava/lang/Foo;
056 * (Citation for: a) where the was allocated, fp of 48954,
057 * at the method with ID 345 -- or void Object.blah() -- and bytecode
058 * with offset 23; b) the object allocated is of type java.lang.Foo)
059 * D 342789 361460
060 * (Object 342789 became unreachable after 361460 was allocated)
061 *
062 * This class implements a simple semi-space collector. See the Jones
063 * & Lins GC book, section 2.2 for an overview of the basic
064 * algorithm. This implementation also includes a large object space
065 * (LOS), and an uncollected "immortal" space.<p>
066 *
067 * All plans make a clear distinction between <i>global</i> and
068 * <i>thread-local</i> activities. Global activities must be
069 * synchronized, whereas no synchronization is required for
070 * thread-local activities. Instances of Plan map 1:1 to "kernel
071 * threads" (aka CPUs). Thus instance
072 * methods allow fast, unsychronized access to Plan utilities such as
073 * allocation and collection. Each instance rests on static resources
074 * (such as memory and virtual memory resources) which are "global"
075 * and therefore "static" members of Plan. This mapping of threads to
076 * instances is crucial to understanding the correctness and
077 * performance proprties of this plan.
078 */
079 @Uninterruptible public class GCTrace extends SS {
080
081 /****************************************************************************
082 *
083 * Class variables
084 */
085
086 /* Spaces */
087 public static final RawPageSpace traceSpace = new RawPageSpace("trace", DEFAULT_POLL_FREQUENCY, VMRequest.create());
088 public static final int TRACE = traceSpace.getDescriptor();
089
090 /* GC state */
091 public static boolean lastGCWasTracing = false; // True when previous GC was for tracing
092 public static boolean traceInducedGC = false; // True if trace triggered GC
093 public static boolean deathScan = false;
094 public static boolean finalDead = false;
095
096 /****************************************************************************
097 *
098 * Initialization
099 */
100
101 /**
102 * Constructor
103 */
104 public GCTrace() {
105 SortTODSharedDeque workList = new SortTODSharedDeque("workList",traceSpace, 1);
106 SortTODSharedDeque traceBuf = new SortTODSharedDeque("traceBuf",traceSpace, 1);
107 workList.prepareNonBlocking();
108 traceBuf.prepareNonBlocking();
109 TraceGenerator.init(workList, traceBuf);
110 }
111
112 /**
113 * The postBoot method is called by the runtime immediately after
114 * command-line arguments are available.
115 */
116 @Interruptible
117 public void postBoot() {
118 Options.noFinalizer.setValue(true);
119 }
120
121 /**
122 * The planExit method is called at RVM termination to allow the
123 * trace process to finish.
124 */
125 @Interruptible
126 public final void notifyExit(int value) {
127 super.notifyExit(value);
128 finalDead = true;
129 traceInducedGC = false;
130 deathScan = true;
131 TraceGenerator.notifyExit(value);
132 }
133
134 /**
135 * This method controls the triggering of a GC. It is called periodically
136 * during allocation. Returns true to trigger a collection.
137 *
138 * @param spaceFull Space request failed, must recover pages within 'space'.
139 * @return True if a collection is requested by the plan.
140 */
141 public final boolean collectionRequired(boolean spaceFull) {
142 if (super.collectionRequired(spaceFull)) {
143 traceInducedGC = false;
144 return true;
145 }
146 return false;
147 }
148
149 /****************************************************************************
150 *
151 * Collection
152 */
153
154 public void collectionPhase(short phaseId) {
155 if (phaseId == PREPARE) {
156 lastGCWasTracing = traceInducedGC;
157 }
158 if (phaseId == RELEASE) {
159 if (traceInducedGC) {
160 /* Clean up following a trace-induced scan */
161 deathScan = false;
162 } else {
163 /* Finish the collection by calculating the unreachable times */
164 deathScan = true;
165 TraceGenerator.postCollection();
166 deathScan = false;
167 /* Perform the semispace collections. */
168 super.collectionPhase(phaseId);
169 }
170 } else if (!traceInducedGC ||
171 (phaseId == INITIATE) ||
172 (phaseId == PREPARE_STACKS) ||
173 (phaseId == ROOTS) ||
174 (phaseId == STACK_ROOTS) ||
175 (phaseId == COMPLETE)) {
176 /* Performing normal GC; sponge off of parent's work. */
177 super.collectionPhase(phaseId);
178 }
179 }
180
181
182 /****************************************************************************
183 *
184 * Space management
185 */
186
187 /**
188 * @return Since trace induced collections are not called to free up memory,
189 * their failure to return memory isn't cause for concern.
190 */
191 public boolean isLastGCFull() {
192 return !lastGCWasTracing;
193 }
194
195 /**
196 * @return the active PlanLocal as a GCTraceLocal
197 */
198 public static GCTraceCollector local() {
199 return ((GCTraceCollector) VM.activePlan.collector());
200 }
201
202 /**
203 * @return the active Plan as a GCTrace
204 */
205 public static GCTrace global() {
206 return ((GCTrace) VM.activePlan.global());
207 }
208 }