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 }