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