| /* |
| * 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()); |
| } |
| } |