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.immix;
014
015 import org.mmtk.plan.*;
016 import org.mmtk.policy.Space;
017 import org.mmtk.policy.immix.ImmixSpace;
018 import org.mmtk.policy.immix.ObjectHeader;
019 import org.mmtk.utility.heap.VMRequest;
020
021 import org.vmmagic.pragma.*;
022 import org.vmmagic.unboxed.*;
023
024 /**
025 * This class implements the global state of an immix collector.
026 *
027 * See the PLDI'08 paper by Blackburn and McKinley for a description
028 * of the algorithm: http://doi.acm.org/10.1145/1375581.1375586
029 *
030 * All plans make a clear distinction between <i>global</i> and
031 * <i>thread-local</i> activities, and divides global and local state
032 * into separate class hierarchies. Global activities must be
033 * synchronized, whereas no synchronization is required for
034 * thread-local activities. There is a single instance of Plan (or the
035 * appropriate sub-class), and a 1:1 mapping of PlanLocal to "kernel
036 * threads" (aka CPUs or in Jikes RVM, Processors). Thus instance
037 * methods of PlanLocal allow fast, unsychronized access to functions such as
038 * allocation and collection.
039 *
040 * The global instance defines and manages static resources
041 * (such as memory and virtual memory resources). This mapping of threads to
042 * instances is crucial to understanding the correctness and
043 * performance properties of MMTk plans.
044 */
045 @Uninterruptible
046 public class Immix extends StopTheWorld {
047
048 /****************************************************************************
049 * Constants
050 */
051
052 /****************************************************************************
053 * Class variables
054 */
055 public static final ImmixSpace immixSpace = new ImmixSpace("immix", DEFAULT_POLL_FREQUENCY, VMRequest.create());
056 public static final int IMMIX = immixSpace.getDescriptor();
057
058 public static final int SCAN_IMMIX = 0;
059 public static final int SCAN_DEFRAG = 1;
060
061 /****************************************************************************
062 * Instance variables
063 */
064
065 public final Trace immixTrace = new Trace(metaDataSpace);
066 /** will the next collection collect the whole heap? */
067 public boolean nextGCWholeHeap = true;
068 /** will this collection collect the whole heap */
069 public boolean collectWholeHeap = nextGCWholeHeap;
070 protected boolean lastGCWasDefrag = false;
071
072 /**
073 * Constructor.
074 *
075 */
076 public Immix() {
077 }
078
079 /*****************************************************************************
080 *
081 * Collection
082 */
083
084 /**
085 * Perform a (global) collection phase.
086 *
087 * @param phaseId Collection phase to execute.
088 */
089 @Inline
090 public void collectionPhase(short phaseId) {
091 if (phaseId == SET_COLLECTION_KIND) {
092 super.collectionPhase(phaseId);
093 immixSpace.decideWhetherToDefrag(emergencyCollection, collectWholeHeap, collectionAttempt, collectionTrigger);
094 return;
095 }
096
097 if (phaseId == PREPARE) {
098 super.collectionPhase(phaseId);
099 immixTrace.prepare();
100 immixSpace.prepare(true);
101 return;
102 }
103
104 if (phaseId == CLOSURE) {
105 immixTrace.prepare();
106 return;
107 }
108
109 if (phaseId == RELEASE) {
110 immixTrace.release();
111 lastGCWasDefrag = immixSpace.release(true);
112 super.collectionPhase(phaseId);
113 return;
114 }
115
116 super.collectionPhase(phaseId);
117 }
118
119 /**
120 * @return Whether last GC was an exhaustive attempt to collect the heap. For many collectors this is the same as asking whether the last GC was a full heap collection.
121 */
122 @Override
123 public boolean lastCollectionWasExhaustive() {
124 return lastGCWasDefrag;
125 }
126
127 /*****************************************************************************
128 *
129 * Accounting
130 */
131
132 /**
133 * Return the number of pages reserved for use given the pending
134 * allocation. The superclass accounts for its spaces, we just
135 * augment this with the mark-sweep space's contribution.
136 *
137 * @return The number of pages reserved given the pending
138 * allocation, excluding space reserved for copying.
139 */
140 public int getPagesUsed() {
141 return immixSpace.reservedPages() + super.getPagesUsed();
142 }
143
144 /**
145 * Calculate the number of pages a collection is required to free to satisfy
146 * outstanding allocation requests.
147 *
148 * @return the number of pages a collection is required to free to satisfy
149 * outstanding allocation requests.
150 */
151 public int getPagesRequired() {
152 return super.getPagesRequired() + immixSpace.requiredPages();
153 }
154
155 /**
156 * @see org.mmtk.plan.Plan#willNeverMove
157 *
158 * @param object Object in question
159 * @return True if the object will never move
160 */
161 @Override
162 public boolean willNeverMove(ObjectReference object) {
163 if (Space.isInSpace(IMMIX, object)) {
164 ObjectHeader.pinObject(object);
165 return true;
166 } else
167 return super.willNeverMove(object);
168 }
169
170 /**
171 * Register specialized methods.
172 */
173 @Interruptible
174 protected void registerSpecializedMethods() {
175 TransitiveClosure.registerSpecializedScan(SCAN_IMMIX, ImmixTraceLocal.class);
176 TransitiveClosure.registerSpecializedScan(SCAN_DEFRAG, ImmixDefragTraceLocal.class);
177 super.registerSpecializedMethods();
178 }
179 }