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.stickyms; 014 015import org.mmtk.plan.TransitiveClosure; 016import org.mmtk.plan.marksweep.MS; 017import org.mmtk.policy.Space; 018import org.mmtk.utility.Log; 019import org.mmtk.utility.deque.SharedDeque; 020import org.mmtk.utility.options.Options; 021import org.mmtk.utility.sanitychecker.SanityChecker; 022import org.mmtk.vm.VM; 023 024import org.vmmagic.pragma.*; 025import org.vmmagic.unboxed.ObjectReference; 026 027/** 028 * This class implements the global state of a simple sticky mark bits collector, 029 * based a simple on mark-sweep collector. The sticky mark bits algorithm is 030 * due to Demmers et al. (http://doi.acm.org/10.1145/96709.96735), and allows 031 * generational collection to be performed in a non-moving heap by overloading 032 * the role of mark bits to also indicate whether an object is new (nursery) or 033 * not. Thus nursery objects are identified by a bit in their header, not by 034 * where they lie within the address space. While Demmers et al. did their work 035 * in a conservative collector, here we have an exact collector, so we can use 036 * a regular write barrier, and don't need to use page protection etc.<p> 037 * 038 * All plans make a clear distinction between <i>global</i> and 039 * <i>thread-local</i> activities, and divides global and local state 040 * into separate class hierarchies. Global activities must be 041 * synchronized, whereas no synchronization is required for 042 * thread-local activities. There is a single instance of Plan (or the 043 * appropriate sub-class), and a 1:1 mapping of PlanLocal to "kernel 044 * threads" (aka CPUs or in Jikes RVM, Processors). Thus instance 045 * methods of PlanLocal allow fast, unsychronized access to functions such as 046 * allocation and collection.<p> 047 * 048 * The global instance defines and manages static resources 049 * (such as memory and virtual memory resources). This mapping of threads to 050 * instances is crucial to understanding the correctness and 051 * performance properties of MMTk plans. 052 */ 053@Uninterruptible 054public class StickyMS extends MS { 055 056 /**************************************************************************** 057 * Constants 058 */ 059 060 /** If {@code true}, then new PLOS objects are collected at each nursery GC */ 061 static final boolean NURSERY_COLLECT_PLOS = true; 062 /** If {@code true} then we only do full heap GCs---so we're like MarkSweep (+ write barrier) */ 063 static final boolean MAJOR_GC_ONLY = false; 064 065 /**************************************************************************** 066 * Class variables 067 */ 068 069 /** 070 * 071 */ 072 public static int SCAN_NURSERY = 1; 073 074 /**************************************************************************** 075 * Instance variables 076 */ 077 078 /* status fields */ 079 080 /** will the next collection collect the whole heap? */ 081 public boolean nextGCWholeHeap = false; 082 /** will this collection collect the whole heap */ 083 public boolean collectWholeHeap = nextGCWholeHeap; 084 085 /** Remset pool */ 086 public final SharedDeque modPool = new SharedDeque("msgen mod objects", metaDataSpace, 1); 087 088 /**************************************************************************** 089 * Static initialization 090 */ 091 { 092 msSpace.makeAgeSegregatedSpace(); /* this space is to be collected generationally */ 093 } 094 095 /***************************************************************************** 096 * 097 * Collection 098 */ 099 100 /** 101 * A user-triggered GC has been initiated. 102 */ 103 public void userTriggeredGC() { 104 nextGCWholeHeap |= Options.fullHeapSystemGC.getValue(); 105 } 106 107 @Override 108 public void forceFullHeapCollection() { 109 nextGCWholeHeap = true; 110 } 111 112 @Inline 113 @Override 114 public final void collectionPhase(short phaseId) { 115 116 if (phaseId == INITIATE) { 117 collectWholeHeap = MAJOR_GC_ONLY || emergencyCollection || nextGCWholeHeap; 118 nextGCWholeHeap = false; 119 super.collectionPhase(phaseId); 120 return; 121 } 122 123 if (!collectWholeHeap) { 124 if (phaseId == PREPARE) { 125 msTrace.prepare(); 126 msSpace.prepare(false); 127 return; 128 } 129 130 if (phaseId == RELEASE) { 131 msTrace.release(); 132 msSpace.release(); 133 modPool.reset(); 134 nextGCWholeHeap = (getPagesAvail() < Options.nurserySize.getMinNursery()); 135 return; 136 } 137 } 138 139 super.collectionPhase(phaseId); 140 } 141 142 /***************************************************************************** 143 * 144 * Accounting 145 */ 146 147 /** 148 * {@inheritDoc} 149 * In this class we prefix the output 150 * indicating whether the collection was full heap or not. 151 */ 152 @Override 153 public void printPreStats() { 154 if ((Options.verbose.getValue() >= 1) && (collectWholeHeap)) 155 Log.write("[Full heap]"); 156 super.printPreStats(); 157 } 158 159 @Override 160 public final boolean isCurrentGCNursery() { 161 return !collectWholeHeap; 162 } 163 164 /** 165 * @return Is last GC a full collection? 166 */ 167 public final boolean isLastGCFull() { 168 return collectWholeHeap; 169 } 170 171 @Override 172 public int sanityExpectedRC(ObjectReference object, int sanityRootRC) { 173 Space space = Space.getSpaceForObject(object); 174 175 // Immortal spaces 176 if (space == StickyMS.immortalSpace || space == StickyMS.vmSpace) { 177 return space.isReachable(object) ? SanityChecker.ALIVE : SanityChecker.DEAD; 178 } 179 180 // Mature space (nursery collection) 181 if (VM.activePlan.global().isCurrentGCNursery() && space != StickyMS.msSpace) { 182 return SanityChecker.UNSURE; 183 } 184 185 return super.sanityExpectedRC(object, sanityRootRC); 186 } 187 188 @Override 189 @Interruptible 190 protected void registerSpecializedMethods() { 191 TransitiveClosure.registerSpecializedScan(SCAN_NURSERY, StickyMSNurseryTraceLocal.class); 192 super.registerSpecializedMethods(); 193 } 194}