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.deque;
014
015 import org.mmtk.utility.Log;
016 import org.mmtk.utility.TracingConstants;
017 import org.mmtk.vm.VM;
018 import org.mmtk.utility.Constants;
019
020 import org.vmmagic.pragma.*;
021 import org.vmmagic.unboxed.*;
022
023 /**
024 * This supports <i>unsynchronized</i> enqueuing and dequeuing of tracing data
025 * and bulk processing of the buffer.
026 */
027 @Uninterruptible public class TraceBuffer extends LocalQueue
028 implements Constants, TracingConstants {
029
030 /***********************************************************************
031 *
032 * Class based constants
033 */
034
035 /**
036 *
037 */
038 private static final Word TRACE_NEW_RECORD = Word.fromIntSignExtend(3);
039 private static final Word TRACE_ALLOC_SIZE = Word.fromIntSignExtend(5);
040 // private static final Word TRACE_ALLOC_NAME = Word.fromIntSignExtend(6);
041 private static final Word TRACE_ALLOC_FP = Word.fromIntSignExtend(7);
042 private static final Word TRACE_ALLOC_THREAD = Word.fromIntSignExtend(9);
043 private static final Word TRACE_TIB_VALUE = Word.fromIntSignExtend(10);
044 private static final Word TRACE_DEATH_TIME = Word.fromIntSignExtend(11);
045 private static final Word TRACE_FIELD_TARGET = Word.fromIntSignExtend(12);
046 private static final Word TRACE_ARRAY_TARGET = Word.fromIntSignExtend(13);
047 private static final Word TRACE_FIELD_SLOT = Word.fromIntSignExtend(14);
048 private static final Word TRACE_ARRAY_ELEMENT = Word.fromIntSignExtend(15);
049 private static final Word TRACE_STATIC_TARGET = Word.fromIntSignExtend(17);
050 private static final Word TRACE_BOOT_ALLOC_SIZE = Word.fromIntSignExtend(18);
051
052 /*
053 * Debugging and trace reducing constants
054 */
055 public static final boolean OMIT_ALLOCS=false;
056 public static final boolean OMIT_UPDATES=false;
057 public static final boolean OMIT_BOOTALLOCS=false;
058 public static final boolean OMIT_UNREACHABLES=false;
059 public static final boolean OMIT_OTHERS=false;
060 public static final boolean OMIT_OUTPUT=OMIT_ALLOCS && OMIT_UPDATES &&
061 OMIT_OTHERS;
062
063
064 /***********************************************************************
065 *
066 * Public methods
067 */
068
069 /**
070 * Constructor
071 *
072 * @param pool The shared queue to which this queue will append its
073 * buffers (when full or flushed) and from which it will aquire new
074 * buffers when it has exhausted its own.
075 */
076 public TraceBuffer(SharedDeque pool) {
077 super(pool);
078 }
079
080 /**
081 * Push word onto the tracing queue.
082 *
083 * @param i The data to be pushed onto the tracing queue
084 */
085 @Inline
086 public final void push(Word i) {
087 checkTailInsert(1);
088 uncheckedTailInsert(i.toAddress());
089 }
090
091 /**
092 * Process the data in the tracing buffer, output information as needed.
093 */
094 public final void process() {
095 Word traceState = TRACE_NEW_RECORD;
096 int entriesNotFlushed = 0;
097 boolean loggedRecord = false;
098 /* First we must flush any remaining data */
099 if (!OMIT_OUTPUT) Log.writeln();
100
101 /* Process through the entire buffer. */
102 while (checkDequeue(1)) {
103 /* For speed and efficiency, we will actually process the data buffer by
104 buffer and not by dequeue-ing each entry. */
105 while (!bufferOffset(head).isZero()) {
106 head = head.minus(BYTES_IN_ADDRESS);
107 Word val = head.loadWord();
108 if (traceState.EQ(TRACE_NEW_RECORD)) {
109 loggedRecord = false;
110 if (val.EQ(TRACE_GCSTART)) {
111 if (!OMIT_OTHERS) {
112 Log.write('G');
113 Log.write('C');
114 Log.writeln('B', true);
115 }
116 } else if (val.EQ(TRACE_GCEND)) {
117 if (!OMIT_OTHERS) {
118 Log.write('G');
119 Log.write('C');
120 Log.writeln('E', true);
121 }
122 } else {
123 traceState = val;
124 }
125 } else {
126 if (traceState.EQ(TRACE_EXACT_ALLOC) ||
127 traceState.EQ(TRACE_ALLOC)) {
128 if (!OMIT_ALLOCS) {
129 Log.write((traceState.EQ(TRACE_EXACT_ALLOC)) ? 'A' : 'a');
130 Log.write(' ');
131 Log.write(val);
132 loggedRecord = true;
133 }
134 traceState = TRACE_ALLOC_SIZE;
135 } else if (traceState.EQ(TRACE_EXACT_IMMORTAL_ALLOC) ||
136 traceState.EQ(TRACE_IMMORTAL_ALLOC)) {
137 if (!OMIT_ALLOCS) {
138 Log.write((traceState.EQ(TRACE_EXACT_IMMORTAL_ALLOC)) ? 'I' : 'i');
139 Log.write(' ');
140 Log.write(val);
141 loggedRecord = true;
142 }
143 traceState = TRACE_ALLOC_SIZE;
144 } else if (traceState.EQ(TRACE_BOOT_ALLOC)) {
145 if (!OMIT_BOOTALLOCS) {
146 Log.write('B');
147 Log.write(' ');
148 Log.write(val);
149 loggedRecord = true;
150 }
151 traceState = TRACE_BOOT_ALLOC_SIZE;
152 } else if (traceState.EQ(TRACE_DEATH)) {
153 if (!OMIT_UNREACHABLES) {
154 Log.write('D');
155 Log.write(' ');
156 Log.write(val);
157 loggedRecord = true;
158 }
159 traceState = TRACE_DEATH_TIME;
160 } else if (traceState.EQ(TRACE_BOOT_ALLOC_SIZE)) {
161 if (!OMIT_BOOTALLOCS)
162 Log.write(val);
163 traceState = TRACE_NEW_RECORD;
164 } else if (traceState.EQ(TRACE_ALLOC_SIZE)) {
165 if (!OMIT_ALLOCS)
166 Log.write(val);
167 traceState = TRACE_ALLOC_FP;
168 } else if (traceState.EQ(TRACE_ALLOC_FP)) {
169 if (!OMIT_ALLOCS)
170 Log.write(val);
171 traceState = TRACE_ALLOC_THREAD;
172 } else if (traceState.EQ(TRACE_ALLOC_THREAD)) {
173 if (!OMIT_ALLOCS)
174 Log.write(val);
175 traceState = TRACE_NEW_RECORD;
176 } else if (traceState.EQ(TRACE_TIB_SET)) {
177 if (!OMIT_UPDATES) {
178 Log.write('T');
179 Log.write(' ');
180 Log.write(val);
181 loggedRecord = true;
182 }
183 traceState = TRACE_TIB_VALUE;
184 } else if (traceState.EQ(TRACE_STATIC_SET)) {
185 if (!OMIT_UPDATES) {
186 Log.write('S');
187 Log.write(' ');
188 Log.write(val);
189 loggedRecord = true;
190 }
191 traceState = TRACE_STATIC_TARGET;
192 } else if (traceState.EQ(TRACE_TIB_VALUE) ||
193 traceState.EQ(TRACE_STATIC_TARGET)) {
194 if (!OMIT_UPDATES)
195 Log.write(val);
196 traceState = TRACE_NEW_RECORD;
197 } else if (traceState.EQ(TRACE_DEATH_TIME)) {
198 if (!OMIT_UNREACHABLES)
199 Log.write(val);
200 traceState = TRACE_NEW_RECORD;
201 } else if (traceState.EQ(TRACE_FIELD_SET) ||
202 traceState.EQ(TRACE_ARRAY_SET)) {
203 if (!OMIT_UPDATES) {
204 Log.write('U');
205 Log.write(' ');
206 Log.write(val);
207 loggedRecord = true;
208 }
209 traceState = TRACE_FIELD_SLOT;
210 } else if (traceState.EQ(TRACE_FIELD_TARGET) ||
211 traceState.EQ(TRACE_ARRAY_TARGET)) {
212 if (!OMIT_UPDATES)
213 Log.write(val);
214 traceState = TRACE_NEW_RECORD;
215 } else if (traceState.EQ(TRACE_FIELD_SLOT) ||
216 traceState.EQ(TRACE_ARRAY_ELEMENT)) {
217 if (!OMIT_UPDATES)
218 Log.write(val);
219 traceState = TRACE_FIELD_TARGET;
220 } else {
221 VM.assertions.fail("Cannot understand directive!\n");
222 }
223 if (traceState.EQ(TRACE_NEW_RECORD) && loggedRecord) {
224 entriesNotFlushed++;
225 Log.writeln();
226 } else if (loggedRecord) {
227 Log.write(' ');
228 }
229 }
230 if (entriesNotFlushed == 10) {
231 if (!OMIT_OUTPUT)
232 Log.flush();
233 entriesNotFlushed = 0;
234 }
235 }
236 }
237 resetLocal();
238 }
239 }