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.utility; 014 015 import org.mmtk.utility.gcspy.drivers.TreadmillDriver; 016 017 import org.vmmagic.unboxed.*; 018 import 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 037 public final class Treadmill implements Constants { 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 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 */ 062 public Treadmill(int granularity, boolean shared) { 063 fromSpace = new DoublyLinkedList(granularity, shared); 064 toSpace = new DoublyLinkedList(granularity, shared); 065 allocNursery = new DoublyLinkedList(granularity, shared); 066 collectNursery = new DoublyLinkedList(granularity, shared); 067 } 068 069 /** 070 * Add a node to the treadmill. This is usually performed on allocation. 071 */ 072 @Inline 073 public void addToTreadmill(Address node, boolean nursery) { 074 if (nursery) 075 allocNursery.add(node); 076 else 077 toSpace.add(node); 078 } 079 080 /** 081 * Remove a node from the nursery list. 082 */ 083 @Inline 084 public Address popNursery() { 085 return collectNursery.pop(); 086 } 087 088 /** 089 * Remove a node from the mature list. 090 */ 091 @Inline 092 public Address pop() { 093 return fromSpace.pop(); 094 } 095 096 /** 097 * Copy a node (during gc tracing). 098 */ 099 @Inline 100 public void copy(Address node, boolean isInNursery) { 101 if (isInNursery) { 102 collectNursery.remove(node); 103 } else { 104 fromSpace.remove(node); 105 } 106 toSpace.add(node); 107 } 108 109 /** 110 * Is the to-space empty? 111 */ 112 @Inline 113 public boolean toSpaceEmpty() { 114 return toSpace.isEmpty(); 115 } 116 117 /** 118 * Is the from-space empty? 119 */ 120 @Inline 121 public boolean fromSpaceEmpty() { 122 return fromSpace.isEmpty(); 123 } 124 125 /** 126 * Is the nursery empty? 127 */ 128 @Inline 129 public boolean nurseryEmpty() { 130 return collectNursery.isEmpty(); 131 } 132 133 /** 134 * Flip the roles of the spaces in preparation for a collection. 135 */ 136 public void flip(boolean fullHeap) { 137 DoublyLinkedList tmp = allocNursery; 138 allocNursery = collectNursery; 139 collectNursery = tmp; 140 if (fullHeap) { 141 tmp = fromSpace; 142 fromSpace = toSpace; 143 toSpace = tmp; 144 } 145 } 146 147 /**************************************************************************** 148 * 149 * Misc header manipulation 150 */ 151 152 /** 153 * 154 */ 155 @Inline 156 public static int headerSize() { 157 return DoublyLinkedList.headerSize(); 158 } 159 160 @Inline 161 public static Address nodeToPayload(Address payload) { 162 return DoublyLinkedList.nodeToPayload(payload); 163 } 164 165 @Inline 166 public static Address midPayloadToNode(Address payload) { 167 return DoublyLinkedList.midPayloadToNode(payload); 168 } 169 170 /**************************************************************************** 171 * 172 * GCSpy 173 */ 174 175 /** 176 * Gather data for GCSpy from the nursery 177 * @param event the gc event 178 * @param tmDriver the GCSpy space driver 179 */ 180 public void gcspyGatherData(int event, TreadmillDriver tmDriver) { 181 this.allocNursery.gcspyGatherData(tmDriver); 182 } 183 184 /** 185 * Gather data for GCSpy 186 * @param event the gc event 187 * @param tmDriver the GCSpy space driver 188 * @param tospace gather from tospace? 189 */ 190 public void gcspyGatherData(int event, TreadmillDriver tmDriver, boolean tospace) { 191 if (tospace) 192 toSpace.gcspyGatherData(tmDriver); 193 else 194 fromSpace.gcspyGatherData(tmDriver); 195 } 196 }