blob: 0ea4103e49bc45f69921a62d83c0947a04f7d846 [file] [log] [blame]
/*
* 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; }
}