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