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