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