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.utility; 014 015import org.mmtk.utility.gcspy.drivers.TreadmillDriver; 016 017import org.vmmagic.unboxed.*; 018import org.vmmagic.pragma.*; 019 020/** 021 * FIXME The DoublyLinkedList class, upon which this depends, must be 022 * re-written as it makes the assumption that the implementation 023 * language (Java) and the language being implemented are the same. 024 * This is true in the case of Jikes RVM, but it is not true for any 025 * VM implementing a language other than Java.<p> 026 * 027 * Each instance of this class is a doubly-linked list, in which 028 * each item or node is a piece of memory. The first two words of each node 029 * contains the forward and backward links. The third word contains 030 * the treadmill. The remaining portion is the payload.<p> 031 * 032 * The treadmill object itself must not be moved.<p> 033 * 034 * Access to the instances may be synchronized depending on the constructor argument. 035 */ 036@Uninterruptible 037public final class Treadmill { 038 039 /**************************************************************************** 040 * 041 * Instance variables 042 */ 043 044 /** 045 * 046 */ 047 private DoublyLinkedList fromSpace; 048 private DoublyLinkedList toSpace; 049 private DoublyLinkedList collectNursery; 050 private DoublyLinkedList allocNursery; 051 052 /**************************************************************************** 053 * 054 * Initialization 055 */ 056 057 /** 058 * @param granularity TODO needs documentation 059 * @param shared <code>true</code> if the created instance will be shared between threads. If it is shared, accesses will be synchronized using locks. 060 */ 061 public Treadmill(int granularity, boolean shared) { 062 fromSpace = new DoublyLinkedList(granularity, shared); 063 toSpace = new DoublyLinkedList(granularity, shared); 064 allocNursery = new DoublyLinkedList(granularity, shared); 065 collectNursery = new DoublyLinkedList(granularity, shared); 066 } 067 068 /** 069 * Adds a node to the treadmill. This is usually performed on allocation. 070 * 071 * @param node the node to add 072 * @param nursery whether to add to the nursery or to the to-space 073 */ 074 @Inline 075 public void addToTreadmill(Address node, boolean nursery) { 076 if (nursery) 077 allocNursery.add(node); 078 else 079 toSpace.add(node); 080 } 081 082 /** 083 * Removes a node from the nursery list. 084 * 085 * @return the removed node 086 */ 087 @Inline 088 public Address popNursery() { 089 return collectNursery.pop(); 090 } 091 092 /** 093 * Removes a node from the mature list. 094 * 095 * @return the removed node 096 */ 097 @Inline 098 public Address pop() { 099 return fromSpace.pop(); 100 } 101 102 /** 103 * Copies a node (during gc tracing). 104 * 105 * @param node the node to copy 106 * @param isInNursery whether the node is in the nursery or the 107 * from-space 108 */ 109 @Inline 110 public void copy(Address node, boolean isInNursery) { 111 if (isInNursery) { 112 collectNursery.remove(node); 113 } else { 114 fromSpace.remove(node); 115 } 116 toSpace.add(node); 117 } 118 119 /** 120 * @return whether the to-space is empty 121 */ 122 @Inline 123 public boolean toSpaceEmpty() { 124 return toSpace.isEmpty(); 125 } 126 127 /** 128 * @return whether the from-space is empty 129 */ 130 @Inline 131 public boolean fromSpaceEmpty() { 132 return fromSpace.isEmpty(); 133 } 134 135 /** 136 * @return whether the nursery is empty 137 */ 138 @Inline 139 public boolean nurseryEmpty() { 140 return collectNursery.isEmpty(); 141 } 142 143 /** 144 * Flips the roles of the spaces in preparation for a collection. 145 * 146 * @param fullHeap whether the collection is full heap 147 */ 148 public void flip(boolean fullHeap) { 149 DoublyLinkedList tmp = allocNursery; 150 allocNursery = collectNursery; 151 collectNursery = tmp; 152 if (fullHeap) { 153 tmp = fromSpace; 154 fromSpace = toSpace; 155 toSpace = tmp; 156 } 157 } 158 159 /**************************************************************************** 160 * 161 * Misc header manipulation 162 */ 163 164 /** 165 * @return the header size 166 */ 167 @Inline 168 public static int headerSize() { 169 return DoublyLinkedList.headerSize(); 170 } 171 172 @Inline 173 public static Address nodeToPayload(Address payload) { 174 return DoublyLinkedList.nodeToPayload(payload); 175 } 176 177 @Inline 178 public static Address midPayloadToNode(Address payload) { 179 return DoublyLinkedList.midPayloadToNode(payload); 180 } 181 182 /**************************************************************************** 183 * 184 * GCSpy 185 */ 186 187 /** 188 * Gather data for GCSpy from the nursery 189 * @param event the gc event 190 * @param tmDriver the GCSpy space driver 191 */ 192 public void gcspyGatherData(int event, TreadmillDriver tmDriver) { 193 this.allocNursery.gcspyGatherData(tmDriver); 194 } 195 196 /** 197 * Gather data for GCSpy 198 * @param event the gc event 199 * @param tmDriver the GCSpy space driver 200 * @param tospace gather from tospace? 201 */ 202 public void gcspyGatherData(int event, TreadmillDriver tmDriver, boolean tospace) { 203 if (tospace) 204 toSpace.gcspyGatherData(tmDriver); 205 else 206 fromSpace.gcspyGatherData(tmDriver); 207 } 208}