/* * 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.utility; import org.mmtk.utility.gcspy.drivers.TreadmillDriver; import org.vmmagic.unboxed.*; import org.vmmagic.pragma.*; /** * FIXME The DoublyLinkedList class, upon which this depends, must be * re-written as it makes the assumption that the implementation * language (Java) and the language being implemented are the same. * This is true in the case of Jikes RVM, but it is not true for any * VM implementing a language other than Java. * * Each instance of this class is a doubly-linked list, in which * each item or node is a piece of memory. The first two words of each node * contains the forward and backward links. The third word contains * the treadmill. The remaining portion is the payload. * * The treadmill object itself must not be moved. * * Access to the instances may be synchronized depending on the constructor argument. */ @Uninterruptible public final class Treadmill implements Constants { /**************************************************************************** * * Instance variables */ private DoublyLinkedList fromSpace; private DoublyLinkedList toSpace; private DoublyLinkedList collectNursery; private DoublyLinkedList allocNursery; /**************************************************************************** * * Initialization */ /** * Constructor */ public Treadmill(int granularity, boolean shared) { fromSpace = new DoublyLinkedList(granularity, shared); toSpace = new DoublyLinkedList(granularity, shared); allocNursery = new DoublyLinkedList(granularity, shared); collectNursery = new DoublyLinkedList(granularity, shared); } /** * Add a node to the treadmill. This is usually performed on allocation. */ @Inline public void addToTreadmill(Address node, boolean nursery) { if (nursery) allocNursery.add(node); else toSpace.add(node); } /** * Remove a node from the nursery list. */ @Inline public Address popNursery() { return collectNursery.pop(); } /** * Remove a node from the mature list. */ @Inline public Address pop() { return fromSpace.pop(); } /** * Copy a node (during gc tracing). */ @Inline public void copy(Address node, boolean isInNursery) { if (isInNursery) { collectNursery.remove(node); } else { fromSpace.remove(node); } toSpace.add(node); } /** * Is the to-space empty? */ @Inline public boolean toSpaceEmpty() { return toSpace.isEmpty(); } /** * Is the from-space empty? */ @Inline public boolean fromSpaceEmpty() { return fromSpace.isEmpty(); } /** * Is the nursery empty? */ @Inline public boolean nurseryEmpty() { return collectNursery.isEmpty(); } /** * Flip the roles of the spaces in preparation for a collection. */ public void flip(boolean fullHeap) { DoublyLinkedList tmp = allocNursery; allocNursery = collectNursery; collectNursery = tmp; if (fullHeap) { tmp = fromSpace; fromSpace = toSpace; toSpace = tmp; } } /**************************************************************************** * * Misc header manipulation */ @Inline public static int headerSize() { return DoublyLinkedList.headerSize(); } @Inline public static Address nodeToPayload(Address payload) { return DoublyLinkedList.nodeToPayload(payload); } @Inline public static Address midPayloadToNode(Address payload) { return DoublyLinkedList.midPayloadToNode(payload); } /**************************************************************************** * * GCSpy */ /** * Gather data for GCSpy from the nursery * @param event the gc event * @param tmDriver the GCSpy space driver */ public void gcspyGatherData(int event, TreadmillDriver tmDriver) { this.allocNursery.gcspyGatherData(tmDriver); } /** * Gather data for GCSpy * @param event the gc event * @param tmDriver the GCSpy space driver * @param tospace gather from tospace? */ public void gcspyGatherData(int event, TreadmillDriver tmDriver, boolean tospace) { if (tospace) toSpace.gcspyGatherData(tmDriver); else fromSpace.gcspyGatherData(tmDriver); } }