| /* |
| * 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.generational.copying; |
| |
| import org.mmtk.policy.CopySpace; |
| import org.mmtk.policy.Space; |
| import org.mmtk.plan.generational.*; |
| import org.mmtk.plan.Trace; |
| import org.mmtk.plan.TransitiveClosure; |
| import org.mmtk.utility.heap.VMRequest; |
| import org.mmtk.vm.VM; |
| |
| import org.vmmagic.pragma.*; |
| |
| /** |
| * This class implements the functionality of a standard |
| * two-generation copying collector. Nursery collections occur when |
| * either the heap is full or the nursery is full. The nursery size |
| * is determined by an optional command line argument. If undefined, |
| * the nursery size is "infinite", so nursery collections only occur |
| * when the heap is full (this is known as a flexible-sized nursery |
| * collector). Thus both fixed and flexible nursery sizes are |
| * supported. Full heap collections occur when the nursery size has |
| * dropped to a statically defined threshold, |
| * <code>NURSERY_THRESHOLD</code><p> |
| * |
| * See the Jones & Lins GC book, chapter 7 for a detailed discussion |
| * of generational collection and section 7.3 for an overview of the |
| * flexible nursery behavior ("The Standard ML of New Jersey |
| * collector"), or go to Appel's paper "Simple generational garbage |
| * collection and fast allocation." SP&E 19(2):171--183, 1989.<p> |
| * |
| * All plans make a clear distinction between <i>global</i> and |
| * <i>thread-local</i> activities. Global activities must be |
| * synchronized, whereas no synchronization is required for |
| * thread-local activities. Instances of Plan map 1:1 to "kernel |
| * threads" (aka CPUs). Thus instance |
| * methods allow fast, unsychronized access to Plan utilities such as |
| * allocation and collection. Each instance rests on static resources |
| * (such as memory and virtual memory resources) which are "global" |
| * and therefore "static" members of Plan. This mapping of threads to |
| * instances is crucial to understanding the correctness and |
| * performance proprties of this plan. |
| */ |
| @Uninterruptible public class GenCopy extends Gen { |
| |
| /**************************************************************************** |
| * |
| * Class variables |
| */ |
| |
| // GC state |
| static boolean hi = false; // True if copying to "higher" semispace |
| |
| /** |
| * The low half of the copying mature space. We allocate into this space |
| * when <code>hi</code> is <code>false</code>. |
| */ |
| static CopySpace matureSpace0 = new CopySpace("ss0", DEFAULT_POLL_FREQUENCY, false, VMRequest.create()); |
| static final int MS0 = matureSpace0.getDescriptor(); |
| |
| /** |
| * The high half of the copying mature space. We allocate into this space |
| * when <code>hi</code> is <code>true</code>. |
| */ |
| static CopySpace matureSpace1 = new CopySpace("ss1", DEFAULT_POLL_FREQUENCY, true, VMRequest.create()); |
| static final int MS1 = matureSpace1.getDescriptor(); |
| |
| |
| /**************************************************************************** |
| * |
| * Instance fields |
| */ |
| final Trace matureTrace; |
| |
| /** |
| * Constructor |
| */ |
| public GenCopy() { |
| super(); |
| if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!IGNORE_REMSETS); // Not supported for GenCopy |
| matureTrace = new Trace(metaDataSpace); |
| } |
| |
| /** |
| * @return Does the mature space do copying ? |
| */ |
| protected boolean copyMature() { |
| return true; |
| } |
| |
| /** |
| * @return The semispace we are currently allocating into |
| */ |
| static CopySpace toSpace() { |
| return hi ? matureSpace1 : matureSpace0; |
| } |
| |
| /** |
| * @return Space descriptor for to-space. |
| */ |
| static int toSpaceDesc() { return hi ? MS1 : MS0; } |
| |
| /** |
| * @return The semispace we are currently copying from |
| * (or copied from at last major GC) |
| */ |
| static CopySpace fromSpace() { |
| return hi ? matureSpace0 : matureSpace1; |
| } |
| |
| /** |
| * @return Space descriptor for from-space |
| */ |
| static int fromSpaceDesc() { return hi ? MS0 : MS1; } |
| |
| /**************************************************************************** |
| * |
| * Collection |
| */ |
| |
| /** |
| * Perform a phase of the currently active collection. |
| * |
| * @param phaseId Collection phase to process |
| */ |
| @Inline |
| public void collectionPhase(short phaseId) { |
| if (traceFullHeap()) { |
| if (phaseId == PREPARE) { |
| super.collectionPhase(phaseId); |
| hi = !hi; // flip the semi-spaces |
| matureSpace0.prepare(hi); |
| matureSpace1.prepare(!hi); |
| matureTrace.prepare(); |
| return; |
| } |
| if (phaseId == CLOSURE) { |
| matureTrace.prepare(); |
| return; |
| } |
| if (phaseId == RELEASE) { |
| matureTrace.release(); |
| fromSpace().release(); |
| super.collectionPhase(phaseId); |
| return; |
| } |
| } |
| super.collectionPhase(phaseId); |
| } |
| |
| /***************************************************************************** |
| * |
| * Accounting |
| */ |
| |
| /** |
| * Return the number of pages reserved for use given the pending |
| * allocation. |
| * |
| * @return The number of pages reserved given the pending |
| * allocation, excluding space reserved for copying. |
| */ |
| @Inline |
| public int getPagesUsed() { |
| return toSpace().reservedPages() + super.getPagesUsed(); |
| } |
| |
| /** |
| * Return the number of pages reserved for copying. |
| * |
| * @return the number of pages reserved for copying. |
| */ |
| public final int getCollectionReserve() { |
| // we must account for the number of pages required for copying, |
| // which equals the number of semi-space pages reserved |
| return toSpace().reservedPages() + super.getCollectionReserve(); |
| } |
| |
| /** |
| * Calculate the number of pages a collection is required to free to satisfy |
| * outstanding allocation requests. |
| * |
| * @return the number of pages a collection is required to free to satisfy |
| * outstanding allocation requests. |
| */ |
| public int getPagesRequired() { |
| return super.getPagesRequired() + (toSpace().requiredPages() << 1); |
| } |
| |
| /** |
| * Return the number of pages available for allocation into the mature |
| * space. |
| * |
| * @return The number of pages available for allocation into the mature |
| * space. |
| */ |
| public int getMaturePhysicalPagesAvail() { |
| return toSpace().availablePhysicalPages() >> 1; |
| } |
| |
| /************************************************************************** |
| * Miscellaneous methods |
| */ |
| |
| /** |
| * @return The mature space we are currently allocating into |
| */ |
| @Inline |
| public Space activeMatureSpace() { |
| return toSpace(); |
| } |
| |
| /** |
| * Register specialized methods. |
| */ |
| @Interruptible |
| protected void registerSpecializedMethods() { |
| TransitiveClosure.registerSpecializedScan(SCAN_MATURE, GenCopyMatureTraceLocal.class); |
| super.registerSpecializedMethods(); |
| } |
| } |