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    }