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;
014
015 import org.mmtk.policy.ImmortalLocal;
016 import org.mmtk.utility.sanitychecker.SanityCheckerLocal;
017 import org.mmtk.utility.alloc.Allocator;
018 import org.mmtk.utility.alloc.BumpPointer;
019 import org.mmtk.utility.Constants;
020
021 import org.mmtk.vm.VM;
022
023 import org.vmmagic.pragma.*;
024 import org.vmmagic.unboxed.*;
025
026 /**
027 * This class (and its sub-classes) implement <i>per-collector thread</i>
028 * behavior. We assume <i>N</i> collector threads and <i>M</i>
029 * mutator threads, where <i>N</i> is often equal to the number of
030 * available processors, P (for P-way parallelism at GC-time), and
031 * <i>M</i> may simply be the number of mutator (application) threads.
032 * Both <i>N</i> and <i>M</i> are determined by the VM, not MMTk. In
033 * the case where a VM uses posix threads (pthreads) for each mutator
034 * ("1:1" threading), <i>M</i> will typically be equal to the number of
035 * mutator threads. When a uses "green threads" or a hybrid threading
036 * scheme (such as Jikes RVM), <i>M</i> will typically be equal to the
037 * level of <i>true</i> parallelism (ie the number of underlying
038 * kernel threads).</p>
039 *
040 * <p>Collector operations are separated into <i>per-collector thread</i>
041 * operations (the bulk of the GC), and <i>per-mutator thread</i> operations
042 * (important in flushing and restoring per-mutator state such as allocator
043 * state and write buffer/remset state). {@link SimplePhase}
044 * ensures that per-collector thread GC phases are performed by each
045 * collector thread, and that the <i>M</i> per-mutator thread operations
046 * are multiplexed across the <i>N</i> active collector threads.</p>
047 *
048 * <p>MMTk assumes that the VM instantiates instances of {@link CollectorContext}
049 * in thread local storage (TLS) for each thread participating in
050 * collection. Accesses to this state are therefore assumed to be
051 * low-cost at GC time.<p>
052 *
053 * <p>MMTk explicitly separates thread-local (this class) and global
054 * operations (See {@link Plan}), so that syncrhonization is localized
055 * and explicit, and thus hopefully minimized (See {@link Plan}). Global (Plan)
056 * and per-thread (this class) state are also explicitly separated.
057 * Operations in this class (and its children) are therefore strictly
058 * local to each collector thread, and synchronized operations always
059 * happen via access to explicitly global classes such as Plan and its
060 * children.</p>
061 *
062 * <p>This class (and its children) therefore typically implement per-collector
063 * thread structures such as collection work queues.</p>
064 *
065 * @see MutatorContext
066 * @see org.mmtk.vm.ActivePlan
067 * @see Plan
068 */
069 @Uninterruptible public abstract class CollectorContext implements Constants {
070
071 /****************************************************************************
072 * Instance fields
073 */
074 /** Unique collector identifier */
075 private int id;
076
077 /** Per-collector allocator into the immortal space */
078 protected final BumpPointer immortal = new ImmortalLocal(Plan.immortalSpace);
079
080 /** Used for aborting concurrent phases pre-empted by stop the world collection */
081 protected boolean resetConcurrentWork;
082
083 /** Used for sanity checking */
084 protected final SanityCheckerLocal sanityLocal = new SanityCheckerLocal();
085
086 /****************************************************************************
087 *
088 * Initialization
089 */
090 protected CollectorContext() {
091 }
092
093 /**
094 * Notify that the collector context is registered and ready to execute.
095 *
096 * @param id The id of this collector context.
097 */
098 public void initCollector(int id) {
099 this.id = id;
100 }
101
102 /****************************************************************************
103 * Collection-time allocation.
104 */
105
106 /**
107 * Allocate memory when copying an object.
108 *
109 * @param original The object that is being copied.
110 * @param bytes The number of bytes required for the copy.
111 * @param align Required alignment for the copy.
112 * @param offset Offset associated with the alignment.
113 * @param allocator The allocator associated with this request.
114 * @return The address of the newly allocated region.
115 */
116 public Address allocCopy(ObjectReference original, int bytes,
117 int align, int offset, int allocator) {
118 VM.assertions.fail("Collector has not implemented allocCopy");
119 return Address.max();
120 }
121
122 /**
123 * Perform any post-copy actions.
124 *
125 * @param ref The newly allocated object.
126 * @param typeRef the type reference for the instance being created.
127 * @param bytes The size of the space to be allocated (in bytes).
128 * @param allocator The allocator statically assigned to this allocation.
129 */
130 public void postCopy(ObjectReference ref, ObjectReference typeRef,
131 int bytes, int allocator) {
132 VM.assertions.fail("Collector has not implemented postCopy");
133 }
134
135 /**
136 * Run-time check of the allocator to use for a given copy allocation
137 *
138 * At the moment this method assumes that allocators will use the simple
139 * (worst) method of aligning to determine if the object is a large object
140 * to ensure that no objects are larger than other allocators can handle.
141 *
142 * @param from The object that is being copied.
143 * @param bytes The number of bytes to be allocated.
144 * @param align The requested alignment.
145 * @param allocator The allocator statically assigned to this allocation.
146 * @return The allocator dyncamically assigned to this allocation.
147 */
148 @Inline
149 public int copyCheckAllocator(ObjectReference from, int bytes,
150 int align, int allocator) {
151 boolean large = Allocator.getMaximumAlignedSize(bytes, align) > Plan.MAX_NON_LOS_COPY_BYTES;
152 return large ? Plan.ALLOC_LOS : allocator;
153 }
154
155 /****************************************************************************
156 * Collection.
157 */
158
159 /** Perform a garbage collection */
160 public abstract void collect();
161
162 /** Perform some concurrent garbage collection */
163 public abstract void concurrentCollect();
164
165 /**
166 * Perform a (local) collection phase.
167 *
168 * @param phaseId The unique phase identifier
169 * @param primary Should this thread be used to execute any single-threaded
170 * local operations?
171 */
172 public abstract void collectionPhase(short phaseId, boolean primary);
173
174 /**
175 * Perform some concurrent collection work.
176 *
177 * @param phaseId The unique phase identifier
178 */
179 public abstract void concurrentCollectionPhase(short phaseId);
180
181 /** @return The current trace instance. */
182 public abstract TraceLocal getCurrentTrace();
183
184 /**
185 * Abort concurrent work due to pre-empt by stop the world collection.
186 */
187 protected void resetConcurrentWork() {
188 resetConcurrentWork = true;
189 }
190
191 /**
192 * Allow concurrent work to continue.
193 */
194 protected void clearResetConcurrentWork() {
195 resetConcurrentWork = false;
196 }
197
198 /****************************************************************************
199 * Miscellaneous.
200 */
201
202 /** @return the unique identifier for this collector context. */
203 @Inline
204 public int getId() { return id; }
205 }