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.<p>
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<p>
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.<p>
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
056 /**
057 *
058 */
059 public static final ImmixSpace immixSpace = new ImmixSpace("immix", VMRequest.create());
060 public static final int IMMIX = immixSpace.getDescriptor();
061
062 public static final int SCAN_IMMIX = 0;
063 public static final int SCAN_DEFRAG = 1;
064
065 /****************************************************************************
066 * Instance variables
067 */
068
069 /**
070 *
071 */
072 public final Trace immixTrace = new Trace(metaDataSpace);
073 /** will the next collection collect the whole heap? */
074 public boolean nextGCWholeHeap = true;
075 /** will this collection collect the whole heap */
076 public boolean collectWholeHeap = nextGCWholeHeap;
077 protected boolean lastGCWasDefrag = false;
078
079 /**
080 * Constructor.
081 *
082 */
083 public Immix() {
084 }
085
086 /*****************************************************************************
087 *
088 * Collection
089 */
090
091 /**
092 * {@inheritDoc}
093 */
094 @Override
095 @Inline
096 public void collectionPhase(short phaseId) {
097 if (phaseId == SET_COLLECTION_KIND) {
098 super.collectionPhase(phaseId);
099 immixSpace.decideWhetherToDefrag(emergencyCollection, collectWholeHeap, collectionAttempt, userTriggeredCollection);
100 return;
101 }
102
103 if (phaseId == PREPARE) {
104 super.collectionPhase(phaseId);
105 immixTrace.prepare();
106 immixSpace.prepare(true);
107 return;
108 }
109
110 if (phaseId == CLOSURE) {
111 immixTrace.prepare();
112 return;
113 }
114
115 if (phaseId == RELEASE) {
116 immixTrace.release();
117 lastGCWasDefrag = immixSpace.release(true);
118 super.collectionPhase(phaseId);
119 return;
120 }
121
122 super.collectionPhase(phaseId);
123 }
124
125 @Override
126 public boolean lastCollectionWasExhaustive() {
127 return lastGCWasDefrag;
128 }
129
130 /*****************************************************************************
131 *
132 * Accounting
133 */
134
135 /**
136 * Return the number of pages reserved for use given the pending
137 * allocation. The superclass accounts for its spaces, we just
138 * augment this with the mark-sweep space's contribution.
139 */
140 @Override
141 public int getPagesUsed() {
142 return immixSpace.reservedPages() + super.getPagesUsed();
143 }
144
145 /**
146 * Return the number of pages reserved for collection.
147 */
148 @Override
149 public int getCollectionReserve() {
150 return super.getCollectionReserve() + immixSpace.defragHeadroomPages();
151 }
152
153 @Override
154 public boolean willNeverMove(ObjectReference object) {
155 if (Space.isInSpace(IMMIX, object)) {
156 ObjectHeader.pinObject(object);
157 return true;
158 } else
159 return super.willNeverMove(object);
160 }
161
162 @Override
163 @Interruptible
164 protected void registerSpecializedMethods() {
165 TransitiveClosure.registerSpecializedScan(SCAN_IMMIX, ImmixTraceLocal.class);
166 TransitiveClosure.registerSpecializedScan(SCAN_DEFRAG, ImmixDefragTraceLocal.class);
167 super.registerSpecializedMethods();
168 }
169 }