/* * 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.<p> * * 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.<p> * * The treadmill object itself must not be moved.<p> * * Access to the instances may be synchronized depending on the constructor argument. */ @Uninterruptible public final class Treadmill { /**************************************************************************** * * Instance variables */ /** * */ private DoublyLinkedList fromSpace; private DoublyLinkedList toSpace; private DoublyLinkedList collectNursery; private DoublyLinkedList allocNursery; /**************************************************************************** * * Initialization */ /** * @param granularity TODO needs documentation * @param shared <code>true</code> if the created instance will be shared between threads. If it is shared, accesses will be synchronized using locks. */ 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); } /** * Adds a node to the treadmill. This is usually performed on allocation. * * @param node the node to add * @param nursery whether to add to the nursery or to the to-space */ @Inline public void addToTreadmill(Address node, boolean nursery) { if (nursery) allocNursery.add(node); else toSpace.add(node); } /** * Removes a node from the nursery list. * * @return the removed node */ @Inline public Address popNursery() { return collectNursery.pop(); } /** * Removes a node from the mature list. * * @return the removed node */ @Inline public Address pop() { return fromSpace.pop(); } /** * Copies a node (during gc tracing). * * @param node the node to copy * @param isInNursery whether the node is in the nursery or the * from-space */ @Inline public void copy(Address node, boolean isInNursery) { if (isInNursery) { collectNursery.remove(node); } else { fromSpace.remove(node); } toSpace.add(node); } /** * @return whether the to-space is empty */ @Inline public boolean toSpaceEmpty() { return toSpace.isEmpty(); } /** * @return whether the from-space is empty */ @Inline public boolean fromSpaceEmpty() { return fromSpace.isEmpty(); } /** * @return whether the nursery is empty */ @Inline public boolean nurseryEmpty() { return collectNursery.isEmpty(); } /** * Flips the roles of the spaces in preparation for a collection. * * @param fullHeap whether the collection is full heap */ public void flip(boolean fullHeap) { DoublyLinkedList tmp = allocNursery; allocNursery = collectNursery; collectNursery = tmp; if (fullHeap) { tmp = fromSpace; fromSpace = toSpace; toSpace = tmp; } } /**************************************************************************** * * Misc header manipulation */ /** * @return the header size */ @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); } }