/* * This file is part of the Jikes RVM project (http://jikesrvm.org). * * This file is licensed to You under the Eclipse Public License (EPL); * You may not use this file except in compliance with the License. You * may obtain a copy of the License at * * http://www.opensource.org/licenses/eclipse-1.0.php * * See the COPYRIGHT.txt file distributed with this work for information * regarding copyright ownership. */ package org.mmtk.plan.semispace.gctrace; import org.mmtk.plan.semispace.*; import org.mmtk.policy.RawPageSpace; import org.mmtk.utility.deque.SortTODSharedDeque; import org.mmtk.utility.heap.VMRequest; import org.mmtk.utility.TraceGenerator; import org.mmtk.utility.options.Options; import org.mmtk.vm.VM; import org.vmmagic.pragma.*; /** * This plan has been modified slightly to perform the processing necessary * for GC trace generation. To maximize performance, it attempts to remain * as faithful as possible to semiSpace/Plan.java. * * The generated trace format is as follows: * B 345678 12 * (Object 345678 was created in the boot image with a size of 12 bytes) * U 59843 234 47298 * (Update object 59843 at the slot at offset 234 to refer to 47298) * S 1233 12345 * (Update static slot 1233 to refer to 12345) * T 4567 78924 * (The TIB of 4567 is set to refer to 78924) * D 342789 * (Object 342789 became unreachable) * A 6860 24 346648 3 * (Object 6860 was allocated, requiring 24 bytes, with fp 346648 on * thread 3; this allocation has perfect knowledge) * a 6884 24 346640 5 * (Object 6864 was allocated, requiring 24 bytes, with fp 346640 on * thread 5; this allocation DOES NOT have perfect knowledge) * I 6860 24 346648 3 * (Object 6860 was allocated into immortal space, requiring 24 bytes, * with fp 346648 on thread 3; this allocation has perfect knowledge) * i 6884 24 346640 5 * (Object 6864 was allocated into immortal space, requiring 24 bytes, * with fp 346640 on thread 5; this allocation DOES NOT have perfect * knowledge) * 48954->[345]LObject;:blah()V:23 Ljava/lang/Foo; * (Citation for: a) where the was allocated, fp of 48954, * at the method with ID 345 -- or void Object.blah() -- and bytecode * with offset 23; b) the object allocated is of type java.lang.Foo) * D 342789 361460 * (Object 342789 became unreachable after 361460 was allocated) * * This class implements a simple semi-space collector. See the Jones * & Lins GC book, section 2.2 for an overview of the basic * algorithm. This implementation also includes a large object space * (LOS), and an uncollected "immortal" space.<p> * * All plans make a clear distinction between <i>global</i> and * <i>thread-local</i> activities. Global activities must be * synchronized, whereas no synchronization is required for * thread-local activities. Instances of Plan map 1:1 to "kernel * threads" (aka CPUs). Thus instance * methods allow fast, unsychronized access to Plan utilities such as * allocation and collection. Each instance rests on static resources * (such as memory and virtual memory resources) which are "global" * and therefore "static" members of Plan. This mapping of threads to * instances is crucial to understanding the correctness and * performance proprties of this plan. */ @Uninterruptible public class GCTrace extends SS { /**************************************************************************** * * Class variables */ /* Spaces */ public static final RawPageSpace traceSpace = new RawPageSpace("trace", DEFAULT_POLL_FREQUENCY, VMRequest.create()); public static final int TRACE = traceSpace.getDescriptor(); /* GC state */ public static boolean lastGCWasTracing = false; // True when previous GC was for tracing public static boolean traceInducedGC = false; // True if trace triggered GC public static boolean deathScan = false; public static boolean finalDead = false; /**************************************************************************** * * Initialization */ /** * Constructor */ public GCTrace() { SortTODSharedDeque workList = new SortTODSharedDeque("workList",traceSpace, 1); SortTODSharedDeque traceBuf = new SortTODSharedDeque("traceBuf",traceSpace, 1); workList.prepareNonBlocking(); traceBuf.prepareNonBlocking(); TraceGenerator.init(workList, traceBuf); } /** * The postBoot method is called by the runtime immediately after * command-line arguments are available. */ @Interruptible public void postBoot() { Options.noFinalizer.setValue(true); } /** * The planExit method is called at RVM termination to allow the * trace process to finish. */ @Interruptible public final void notifyExit(int value) { super.notifyExit(value); finalDead = true; traceInducedGC = false; deathScan = true; TraceGenerator.notifyExit(value); } /** * This method controls the triggering of a GC. It is called periodically * during allocation. Returns true to trigger a collection. * * @param spaceFull Space request failed, must recover pages within 'space'. * @return True if a collection is requested by the plan. */ public final boolean collectionRequired(boolean spaceFull) { if (super.collectionRequired(spaceFull)) { traceInducedGC = false; return true; } return false; } /**************************************************************************** * * Collection */ public void collectionPhase(short phaseId) { if (phaseId == PREPARE) { lastGCWasTracing = traceInducedGC; } if (phaseId == RELEASE) { if (traceInducedGC) { /* Clean up following a trace-induced scan */ deathScan = false; } else { /* Finish the collection by calculating the unreachable times */ deathScan = true; TraceGenerator.postCollection(); deathScan = false; /* Perform the semispace collections. */ super.collectionPhase(phaseId); } } else if (!traceInducedGC || (phaseId == INITIATE) || (phaseId == PREPARE_STACKS) || (phaseId == ROOTS) || (phaseId == STACK_ROOTS) || (phaseId == COMPLETE)) { /* Performing normal GC; sponge off of parent's work. */ super.collectionPhase(phaseId); } } /**************************************************************************** * * Space management */ /** * @return Since trace induced collections are not called to free up memory, * their failure to return memory isn't cause for concern. */ public boolean isLastGCFull() { return !lastGCWasTracing; } /** * @return the active PlanLocal as a GCTraceLocal */ public static GCTraceCollector local() { return ((GCTraceCollector) VM.activePlan.collector()); } /** * @return the active Plan as a GCTrace */ public static GCTrace global() { return ((GCTrace) VM.activePlan.global()); } }