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 }