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.stickyimmix; 014 015 import org.mmtk.plan.TransitiveClosure; 016 import org.mmtk.plan.immix.Immix; 017 import org.mmtk.policy.Space; 018 import org.mmtk.utility.Log; 019 import org.mmtk.utility.deque.SharedDeque; 020 import org.mmtk.utility.options.Options; 021 import org.mmtk.utility.statistics.BooleanCounter; 022 import org.mmtk.utility.statistics.Stats; 023 024 import org.vmmagic.pragma.*; 025 026 /** 027 * This class implements the global state of a simple sticky mark bits collector, 028 * based on an immix collector. The sticky mark bits algorithm is 029 * due to Demmers et al. (http://doi.acm.org/10.1145/96709.96735), and allows 030 * generational collection to be performed in a non-moving heap by overloading 031 * the role of mark bits to also indicate whether an object is new (nursery) or 032 * not. Thus nursery objects are identified by a bit in their header, not by 033 * where they lie within the address space. While Demmers et al. did their work 034 * in a conservative collector, here we have an exact collector, so we can use 035 * a regular write barrier, and don't need to use page protection etc.<p> 036 * 037 * See the PLDI'08 paper by Blackburn and McKinley for a description 038 * of the algorithm: http://doi.acm.org/10.1145/1375581.1375586<p> 039 * 040 * All plans make a clear distinction between <i>global</i> and 041 * <i>thread-local</i> activities, and divides global and local state 042 * into separate class hierarchies. Global activities must be 043 * synchronized, whereas no synchronization is required for 044 * thread-local activities. There is a single instance of Plan (or the 045 * appropriate sub-class), and a 1:1 mapping of PlanLocal to "kernel 046 * threads" (aka CPUs or in Jikes RVM, Processors). Thus instance 047 * methods of PlanLocal allow fast, unsychronized access to functions such as 048 * allocation and collection.<p> 049 * 050 * The global instance defines and manages static resources 051 * (such as memory and virtual memory resources). This mapping of threads to 052 * instances is crucial to understanding the correctness and 053 * performance properties of MMTk plans.<p> 054 */ 055 @Uninterruptible 056 public class StickyImmix extends Immix { 057 058 /**************************************************************************** 059 * Constants 060 */ 061 062 /** If true, then new PLOS objects are collected at each nursery GC */ 063 static final boolean NURSERY_COLLECT_PLOS = true; 064 /** If true then we only do full heap GCs---so we're like MarkSweep (+ write barrier) */ 065 static final boolean MAJOR_GC_ONLY = false; 066 /** estimated collection yield */ 067 protected static final float SURVIVAL_ESTIMATE = (float) 0.8; 068 069 public static int SCAN_NURSERY = 2; 070 071 /**************************************************************************** 072 * Class variables 073 */ 074 075 /** 076 * TODO: this field is unused, somebody with MMTk knowledge needs to look at it 077 */ 078 private static int lastCommittedImmixPages = 0; 079 080 /* statistics */ 081 public static BooleanCounter fullHeap = new BooleanCounter("majorGC", true, true); 082 083 /**************************************************************************** 084 * Instance variables 085 */ 086 087 /** Remset pool */ 088 public final SharedDeque modPool = new SharedDeque("msgen mod objects", metaDataSpace, 1); 089 090 /** 091 * Constructor. 092 * 093 */ 094 public StickyImmix() { 095 collectWholeHeap = nextGCWholeHeap = false; 096 } 097 098 /***************************************************************************** 099 * 100 * Collection 101 */ 102 103 /** 104 * A user-triggered GC has been initiated. 105 */ 106 public void userTriggeredGC() { 107 nextGCWholeHeap |= Options.fullHeapSystemGC.getValue(); 108 } 109 110 @Override 111 public void forceFullHeapCollection() { 112 nextGCWholeHeap = true; 113 } 114 115 @Inline 116 @Override 117 public final void collectionPhase(short phaseId) { 118 119 if (phaseId == SET_COLLECTION_KIND) { 120 super.collectionPhase(phaseId); 121 collectWholeHeap = requiresFullHeapCollection(); 122 if (Stats.gatheringStats() && collectWholeHeap) fullHeap.set(); 123 return; 124 } 125 126 if (!collectWholeHeap && phaseId == PREPARE) { 127 immixTrace.prepare(); 128 immixSpace.prepare(false); 129 return; 130 } 131 132 if (phaseId == RELEASE) { 133 if (collectWholeHeap) { 134 super.collectionPhase(RELEASE); 135 } else { 136 immixTrace.release(); 137 lastGCWasDefrag = immixSpace.release(false); 138 } 139 modPool.reset(); 140 lastCommittedImmixPages = immixSpace.committedPages(); 141 nextGCWholeHeap = (getPagesAvail() < Options.nurserySize.getMinNursery()); 142 return; 143 } 144 145 super.collectionPhase(phaseId); 146 } 147 148 /***************************************************************************** 149 * 150 * Accounting 151 */ 152 153 /** 154 * {@inheritDoc} 155 */ 156 @Override 157 public final boolean collectionRequired(boolean spaceFull, Space space) { 158 boolean nurseryFull = immixSpace.getPagesAllocated() > Options.nurserySize.getMaxNursery(); 159 if (spaceFull && space != immixSpace) nextGCWholeHeap = true; 160 return super.collectionRequired(spaceFull, space) || nurseryFull; 161 } 162 163 /** 164 * Determine whether this GC should be a full heap collection. 165 * 166 * @return True if this GC should be a full heap collection. 167 */ 168 protected boolean requiresFullHeapCollection() { 169 if (userTriggeredCollection && Options.fullHeapSystemGC.getValue()) { 170 return true; 171 } 172 173 if (nextGCWholeHeap || collectionAttempt > 1) { 174 // Forces full heap collection 175 return true; 176 } 177 178 return false; 179 } 180 181 @Override 182 public int getCollectionReserve() { 183 return super.getCollectionReserve() + immixSpace.defragHeadroomPages(); 184 } 185 186 /** 187 * {@inheritDoc} 188 * In this class we prefix the output 189 * indicating whether the collection was full heap or not. 190 */ 191 @Override 192 public void printPreStats() { 193 if ((Options.verbose.getValue() >= 1) && (collectWholeHeap)) 194 Log.write("[Full heap]"); 195 super.printPreStats(); 196 } 197 198 @Override 199 public final boolean isCurrentGCNursery() { 200 return !collectWholeHeap; 201 } 202 203 public final boolean isLastGCFull() { 204 return collectWholeHeap; 205 } 206 207 @Override 208 @Interruptible 209 protected void registerSpecializedMethods() { 210 TransitiveClosure.registerSpecializedScan(SCAN_NURSERY, StickyImmixNurseryTraceLocal.class); 211 super.registerSpecializedMethods(); 212 } 213 }