| /* |
| * This file is part of the Jikes RVM project (http://jikesrvm.org). |
| * |
| * This file is licensed to You under the Eclipse Public License (EPL); |
| * You may not use this file except in compliance with the License. You |
| * may obtain a copy of the License at |
| * |
| * http://www.opensource.org/licenses/eclipse-1.0.php |
| * |
| * See the COPYRIGHT.txt file distributed with this work for information |
| * regarding copyright ownership. |
| */ |
| package org.mmtk.plan; |
| |
| import org.mmtk.policy.ImmortalLocal; |
| import org.mmtk.utility.sanitychecker.SanityCheckerLocal; |
| import org.mmtk.utility.alloc.Allocator; |
| import org.mmtk.utility.alloc.BumpPointer; |
| import org.mmtk.utility.Constants; |
| |
| import org.mmtk.vm.VM; |
| |
| import org.vmmagic.pragma.*; |
| import org.vmmagic.unboxed.*; |
| |
| /** |
| * This class (and its sub-classes) implement <i>per-collector thread</i> |
| * behavior. We assume <i>N</i> collector threads and <i>M</i> |
| * mutator threads, where <i>N</i> is often equal to the number of |
| * available processors, P (for P-way parallelism at GC-time), and |
| * <i>M</i> may simply be the number of mutator (application) threads. |
| * Both <i>N</i> and <i>M</i> are determined by the VM, not MMTk. In |
| * the case where a VM uses posix threads (pthreads) for each mutator |
| * ("1:1" threading), <i>M</i> will typically be equal to the number of |
| * mutator threads. When a uses "green threads" or a hybrid threading |
| * scheme (such as Jikes RVM), <i>M</i> will typically be equal to the |
| * level of <i>true</i> parallelism (ie the number of underlying |
| * kernel threads).</p> |
| * |
| * <p>Collector operations are separated into <i>per-collector thread</i> |
| * operations (the bulk of the GC), and <i>per-mutator thread</i> operations |
| * (important in flushing and restoring per-mutator state such as allocator |
| * state and write buffer/remset state). {@link SimplePhase} |
| * ensures that per-collector thread GC phases are performed by each |
| * collector thread, and that the <i>M</i> per-mutator thread operations |
| * are multiplexed across the <i>N</i> active collector threads.</p> |
| * |
| * <p>MMTk assumes that the VM instantiates instances of {@link CollectorContext} |
| * in thread local storage (TLS) for each thread participating in |
| * collection. Accesses to this state are therefore assumed to be |
| * low-cost at GC time.<p> |
| * |
| * <p>MMTk explicitly separates thread-local (this class) and global |
| * operations (See {@link Plan}), so that syncrhonization is localized |
| * and explicit, and thus hopefully minimized (See {@link Plan}). Global (Plan) |
| * and per-thread (this class) state are also explicitly separated. |
| * Operations in this class (and its children) are therefore strictly |
| * local to each collector thread, and synchronized operations always |
| * happen via access to explicitly global classes such as Plan and its |
| * children.</p> |
| * |
| * <p>This class (and its children) therefore typically implement per-collector |
| * thread structures such as collection work queues.</p> |
| * |
| * @see MutatorContext |
| * @see org.mmtk.vm.ActivePlan |
| * @see Plan |
| */ |
| @Uninterruptible public abstract class CollectorContext implements Constants { |
| |
| /**************************************************************************** |
| * Instance fields |
| */ |
| /** Unique collector identifier */ |
| private int id; |
| |
| /** Per-collector allocator into the immortal space */ |
| protected final BumpPointer immortal = new ImmortalLocal(Plan.immortalSpace); |
| |
| /** Used for aborting concurrent phases pre-empted by stop the world collection */ |
| protected boolean resetConcurrentWork; |
| |
| /** Used for sanity checking */ |
| protected final SanityCheckerLocal sanityLocal = new SanityCheckerLocal(); |
| |
| /**************************************************************************** |
| * |
| * Initialization |
| */ |
| protected CollectorContext() { |
| } |
| |
| /** |
| * Notify that the collector context is registered and ready to execute. |
| * |
| * @param id The id of this collector context. |
| */ |
| public void initCollector(int id) { |
| this.id = id; |
| } |
| |
| /**************************************************************************** |
| * Collection-time allocation. |
| */ |
| |
| /** |
| * Allocate memory when copying an object. |
| * |
| * @param original The object that is being copied. |
| * @param bytes The number of bytes required for the copy. |
| * @param align Required alignment for the copy. |
| * @param offset Offset associated with the alignment. |
| * @param allocator The allocator associated with this request. |
| * @return The address of the newly allocated region. |
| */ |
| public Address allocCopy(ObjectReference original, int bytes, |
| int align, int offset, int allocator) { |
| VM.assertions.fail("Collector has not implemented allocCopy"); |
| return Address.max(); |
| } |
| |
| /** |
| * Perform any post-copy actions. |
| * |
| * @param ref The newly allocated object. |
| * @param typeRef the type reference for the instance being created. |
| * @param bytes The size of the space to be allocated (in bytes). |
| * @param allocator The allocator statically assigned to this allocation. |
| */ |
| public void postCopy(ObjectReference ref, ObjectReference typeRef, |
| int bytes, int allocator) { |
| VM.assertions.fail("Collector has not implemented postCopy"); |
| } |
| |
| /** |
| * Run-time check of the allocator to use for a given copy allocation |
| * |
| * At the moment this method assumes that allocators will use the simple |
| * (worst) method of aligning to determine if the object is a large object |
| * to ensure that no objects are larger than other allocators can handle. |
| * |
| * @param from The object that is being copied. |
| * @param bytes The number of bytes to be allocated. |
| * @param align The requested alignment. |
| * @param allocator The allocator statically assigned to this allocation. |
| * @return The allocator dyncamically assigned to this allocation. |
| */ |
| @Inline |
| public int copyCheckAllocator(ObjectReference from, int bytes, |
| int align, int allocator) { |
| boolean large = Allocator.getMaximumAlignedSize(bytes, align) > Plan.MAX_NON_LOS_COPY_BYTES; |
| return large ? Plan.ALLOC_LOS : allocator; |
| } |
| |
| /**************************************************************************** |
| * Collection. |
| */ |
| |
| /** Perform a garbage collection */ |
| public abstract void collect(); |
| |
| /** Perform some concurrent garbage collection */ |
| public abstract void concurrentCollect(); |
| |
| /** |
| * Perform a (local) collection phase. |
| * |
| * @param phaseId The unique phase identifier |
| * @param primary Should this thread be used to execute any single-threaded |
| * local operations? |
| */ |
| public abstract void collectionPhase(short phaseId, boolean primary); |
| |
| /** |
| * Perform some concurrent collection work. |
| * |
| * @param phaseId The unique phase identifier |
| */ |
| public abstract void concurrentCollectionPhase(short phaseId); |
| |
| /** @return The current trace instance. */ |
| public abstract TraceLocal getCurrentTrace(); |
| |
| /** |
| * Abort concurrent work due to pre-empt by stop the world collection. |
| */ |
| protected void resetConcurrentWork() { |
| resetConcurrentWork = true; |
| } |
| |
| /** |
| * Allow concurrent work to continue. |
| */ |
| protected void clearResetConcurrentWork() { |
| resetConcurrentWork = false; |
| } |
| |
| /**************************************************************************** |
| * Miscellaneous. |
| */ |
| |
| /** @return the unique identifier for this collector context. */ |
| @Inline |
| public int getId() { return id; } |
| } |