blob: 9b73bb2bd58d9d9e410a004b151f48b331e302bd [file] [log] [blame]
/*
* This file is part of the Jikes RVM project (http://jikesrvm.org).
*
* This file is licensed to You under the Eclipse Public License (EPL);
* You may not use this file except in compliance with the License. You
* may obtain a copy of the License at
*
* http://www.opensource.org/licenses/eclipse-1.0.php
*
* See the COPYRIGHT.txt file distributed with this work for information
* regarding copyright ownership.
*/
package org.mmtk.utility.deque;
import org.mmtk.utility.Log;
import org.mmtk.utility.TracingConstants;
import org.mmtk.vm.VM;
import org.mmtk.utility.Constants;
import org.vmmagic.pragma.*;
import org.vmmagic.unboxed.*;
/**
* This supports <i>unsynchronized</i> enqueuing and dequeuing of tracing data
* and bulk processing of the buffer.
*/
@Uninterruptible public class TraceBuffer extends LocalQueue
implements Constants, TracingConstants {
/***********************************************************************
*
* Class based constants
*/
private static final Word TRACE_NEW_RECORD = Word.fromIntSignExtend(3);
private static final Word TRACE_ALLOC_SIZE = Word.fromIntSignExtend(5);
// private static final Word TRACE_ALLOC_NAME = Word.fromIntSignExtend(6);
private static final Word TRACE_ALLOC_FP = Word.fromIntSignExtend(7);
private static final Word TRACE_ALLOC_THREAD = Word.fromIntSignExtend(9);
private static final Word TRACE_TIB_VALUE = Word.fromIntSignExtend(10);
private static final Word TRACE_DEATH_TIME = Word.fromIntSignExtend(11);
private static final Word TRACE_FIELD_TARGET = Word.fromIntSignExtend(12);
private static final Word TRACE_ARRAY_TARGET = Word.fromIntSignExtend(13);
private static final Word TRACE_FIELD_SLOT = Word.fromIntSignExtend(14);
private static final Word TRACE_ARRAY_ELEMENT = Word.fromIntSignExtend(15);
private static final Word TRACE_STATIC_TARGET = Word.fromIntSignExtend(17);
private static final Word TRACE_BOOT_ALLOC_SIZE = Word.fromIntSignExtend(18);
/*
* Debugging and trace reducing constants
*/
public static final boolean OMIT_ALLOCS=false;
public static final boolean OMIT_UPDATES=false;
public static final boolean OMIT_BOOTALLOCS=false;
public static final boolean OMIT_UNREACHABLES=false;
public static final boolean OMIT_OTHERS=false;
public static final boolean OMIT_OUTPUT=OMIT_ALLOCS && OMIT_UPDATES &&
OMIT_OTHERS;
/***********************************************************************
*
* Public methods
*/
/**
* Constructor
*
* @param pool The shared queue to which this queue will append its
* buffers (when full or flushed) and from which it will aquire new
* buffers when it has exhausted its own.
*/
public TraceBuffer(SharedDeque pool) {
super(pool);
}
/**
* Push word onto the tracing queue.
*
* @param i The data to be pushed onto the tracing queue
*/
@Inline
public final void push(Word i) {
checkTailInsert(1);
uncheckedTailInsert(i.toAddress());
}
/**
* Process the data in the tracing buffer, output information as needed.
*/
public final void process() {
Word traceState = TRACE_NEW_RECORD;
int entriesNotFlushed = 0;
boolean loggedRecord = false;
/* First we must flush any remaining data */
if (!OMIT_OUTPUT) Log.writeln();
/* Process through the entire buffer. */
while (checkDequeue(1)) {
/* For speed and efficiency, we will actually process the data buffer by
buffer and not by dequeue-ing each entry. */
while (!bufferOffset(head).isZero()) {
head = head.minus(BYTES_IN_ADDRESS);
Word val = head.loadWord();
if (traceState.EQ(TRACE_NEW_RECORD)) {
loggedRecord = false;
if (val.EQ(TRACE_GCSTART)) {
if (!OMIT_OTHERS) {
Log.write('G');
Log.write('C');
Log.writeln('B', true);
}
} else if (val.EQ(TRACE_GCEND)) {
if (!OMIT_OTHERS) {
Log.write('G');
Log.write('C');
Log.writeln('E', true);
}
} else {
traceState = val;
}
} else {
if (traceState.EQ(TRACE_EXACT_ALLOC) ||
traceState.EQ(TRACE_ALLOC)) {
if (!OMIT_ALLOCS) {
Log.write((traceState.EQ(TRACE_EXACT_ALLOC)) ? 'A' : 'a');
Log.write(' ');
Log.write(val);
loggedRecord = true;
}
traceState = TRACE_ALLOC_SIZE;
} else if (traceState.EQ(TRACE_EXACT_IMMORTAL_ALLOC) ||
traceState.EQ(TRACE_IMMORTAL_ALLOC)) {
if (!OMIT_ALLOCS) {
Log.write((traceState.EQ(TRACE_EXACT_IMMORTAL_ALLOC)) ? 'I' : 'i');
Log.write(' ');
Log.write(val);
loggedRecord = true;
}
traceState = TRACE_ALLOC_SIZE;
} else if (traceState.EQ(TRACE_BOOT_ALLOC)) {
if (!OMIT_BOOTALLOCS) {
Log.write('B');
Log.write(' ');
Log.write(val);
loggedRecord = true;
}
traceState = TRACE_BOOT_ALLOC_SIZE;
} else if (traceState.EQ(TRACE_DEATH)) {
if (!OMIT_UNREACHABLES) {
Log.write('D');
Log.write(' ');
Log.write(val);
loggedRecord = true;
}
traceState = TRACE_DEATH_TIME;
} else if (traceState.EQ(TRACE_BOOT_ALLOC_SIZE)) {
if (!OMIT_BOOTALLOCS)
Log.write(val);
traceState = TRACE_NEW_RECORD;
} else if (traceState.EQ(TRACE_ALLOC_SIZE)) {
if (!OMIT_ALLOCS)
Log.write(val);
traceState = TRACE_ALLOC_FP;
} else if (traceState.EQ(TRACE_ALLOC_FP)) {
if (!OMIT_ALLOCS)
Log.write(val);
traceState = TRACE_ALLOC_THREAD;
} else if (traceState.EQ(TRACE_ALLOC_THREAD)) {
if (!OMIT_ALLOCS)
Log.write(val);
traceState = TRACE_NEW_RECORD;
} else if (traceState.EQ(TRACE_TIB_SET)) {
if (!OMIT_UPDATES) {
Log.write('T');
Log.write(' ');
Log.write(val);
loggedRecord = true;
}
traceState = TRACE_TIB_VALUE;
} else if (traceState.EQ(TRACE_STATIC_SET)) {
if (!OMIT_UPDATES) {
Log.write('S');
Log.write(' ');
Log.write(val);
loggedRecord = true;
}
traceState = TRACE_STATIC_TARGET;
} else if (traceState.EQ(TRACE_TIB_VALUE) ||
traceState.EQ(TRACE_STATIC_TARGET)) {
if (!OMIT_UPDATES)
Log.write(val);
traceState = TRACE_NEW_RECORD;
} else if (traceState.EQ(TRACE_DEATH_TIME)) {
if (!OMIT_UNREACHABLES)
Log.write(val);
traceState = TRACE_NEW_RECORD;
} else if (traceState.EQ(TRACE_FIELD_SET) ||
traceState.EQ(TRACE_ARRAY_SET)) {
if (!OMIT_UPDATES) {
Log.write('U');
Log.write(' ');
Log.write(val);
loggedRecord = true;
}
traceState = TRACE_FIELD_SLOT;
} else if (traceState.EQ(TRACE_FIELD_TARGET) ||
traceState.EQ(TRACE_ARRAY_TARGET)) {
if (!OMIT_UPDATES)
Log.write(val);
traceState = TRACE_NEW_RECORD;
} else if (traceState.EQ(TRACE_FIELD_SLOT) ||
traceState.EQ(TRACE_ARRAY_ELEMENT)) {
if (!OMIT_UPDATES)
Log.write(val);
traceState = TRACE_FIELD_TARGET;
} else {
VM.assertions.fail("Cannot understand directive!\n");
}
if (traceState.EQ(TRACE_NEW_RECORD) && loggedRecord) {
entriesNotFlushed++;
Log.writeln();
} else if (loggedRecord) {
Log.write(' ');
}
}
if (entriesNotFlushed == 10) {
if (!OMIT_OUTPUT)
Log.flush();
entriesNotFlushed = 0;
}
}
}
resetLocal();
}
}