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    }