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