internal static unsafe BufferDescriptor Read(LogHeader logHeader, CachedBinaryReader reader, EventListener listener) { var pos = reader.Position; var header = BufferHeader.Read (reader); if (header == null) return null; if (!reader.LoadData (header.Length)) { reader.Position = pos; return null; } fixed (byte* buffer = reader.buffer) { // FIXME: unset the buffer pointer after this block! reader.SetBufferPointer (buffer); var result = new BufferDescriptor (pos, header); try { listener.ReadBufferEvents (logHeader, result, reader); } catch (Exception e) { Console.WriteLine ("error while reading event !"); Console.WriteLine (e); } return result; } }
internal void ReadBufferEvents(LogHeader logHeader, BufferDescriptor buffer, CachedBinaryReader reader) { CurrentBuffer = buffer; HandleBufferStartRead (); while (!reader.IsBufferEmpty) { byte info = reader.ReadByte (); var type = (byte)(info & 0xF); byte extendedInfo = (byte)(info & 0xF0); ulong timeDiff; switch (type) { case EventType.Method: { timeDiff = reader.ReadULeb128 (); Time += timeDiff; buffer.RecordTime (Time); switch (extendedInfo) { case TypeMethod.Leave: var method = reader.ReadSLeb128 (); MethodBase += method; HandleMethodLeave (); break; case TypeMethod.Enter: method = reader.ReadSLeb128 (); MethodBase += method; HandleMethodEnter (); break; case TypeMethod.ExcLeave: method = reader.ReadSLeb128 (); MethodBase += method; HandleMethodExcLeave (); break; case TypeMethod.Jit: method = reader.ReadSLeb128 (); MethodBase += method; var codeAddress = FixPointer (logHeader, buffer.Header.PtrBase + reader.ReadSLeb128 ()); var codeSize = reader.ReadULeb128 (); var name = reader.ReadNullTerminatedString (); HandleMethodJit (codeAddress, codeSize, name); break; default: throw new InvalidOperationException ("Unknown method event type:" + extendedInfo); } break; } case EventType.Alloc: { timeDiff = reader.ReadULeb128 (); Time += timeDiff; buffer.RecordTime (Time); var ptr = reader.ReadSLeb128 (); var obj = reader.ReadSLeb128 (); var size = reader.ReadULeb128 (); Backtrace backtrace; if ((extendedInfo & TypeAlloc.BacktraceBit) == TypeAlloc.BacktraceBit) { backtrace = Backtrace.Read (reader); } else { backtrace = null; } HandleAlloc (ptr, obj, size, backtrace); break; } case EventType.Gc: { timeDiff = reader.ReadULeb128 (); Time += timeDiff; buffer.RecordTime (Time); switch (extendedInfo) { case TypeGc.Event: var gcEventType = (MonoGCEvent)reader.ReadULeb128 (); var generation = reader.ReadULeb128 (); HandleGc (gcEventType, generation); break; case TypeGc.Resize: var heapSize = reader.ReadULeb128 (); HandleResizeGc (heapSize); break; case TypeGc.Move: ulong num = reader.ReadULeb128 (); var objAddr = new long[num]; for (ulong i = 0; i < num; i++) { objAddr [i] = reader.ReadSLeb128 (); } HandleMoveGc (objAddr); break; case TypeGc.HandleCreated: var handleType = (System.Runtime.InteropServices.GCHandleType)reader.ReadULeb128 (); var handle = reader.ReadULeb128 (); var obja = reader.ReadSLeb128 (); HandleHandleCreatedGc (handleType, handle, obja); break; case TypeGc.HandleDestroyed: handleType = (System.Runtime.InteropServices.GCHandleType)reader.ReadULeb128 (); handle = reader.ReadULeb128 (); HandleHandleDestroyedGc (handleType, handle); break; default: throw new InvalidOperationException ("unknown gc type:" + extendedInfo); } break; } case EventType.Metadata: { timeDiff = reader.ReadULeb128 (); Time += timeDiff; buffer.RecordTime (Time); byte mtype = reader.ReadByte (); long pointer = reader.ReadSLeb128 (); switch (mtype) { case TypeMetadata.Class: var image = reader.ReadSLeb128 (); var flags = reader.ReadULeb128 (); if (flags != 0) throw new Exception ("Flags should be 0"); var name = reader.ReadNullTerminatedString (); HandleMetaDataClass (pointer, image, name); break; case TypeMetadata.Image: flags = reader.ReadULeb128 (); if (flags != 0) throw new Exception ("Flags should be 0"); name = reader.ReadNullTerminatedString (); HandleMetaDataImage (pointer, name); break; case TypeMetadata.Thread: flags = reader.ReadULeb128 (); if (flags != 0) throw new Exception ("Flags should be 0"); name = reader.ReadNullTerminatedString (); HandleMetaDataThread (pointer, name); break; default: throw new InvalidOperationException ("Unknown metadata event type:" + type); } break; } case EventType.Exception: { timeDiff = reader.ReadULeb128 (); Time += timeDiff; buffer.RecordTime (Time); switch (extendedInfo & (TypeException.BacktraceBit - 1)) { case TypeException.Clause: var clauseType = reader.ReadULeb128 (); var clauseNum = reader.ReadULeb128 (); var method = reader.ReadSLeb128 (); MethodBase += method; HandleExceptionClause (clauseType, clauseNum); break; case TypeException.Throw: var obj = reader.ReadSLeb128 (); Backtrace backtrace; if ((extendedInfo & TypeException.BacktraceBit) == TypeException.BacktraceBit) { backtrace = Backtrace.Read (reader); } else { backtrace = null; } HandleExceptionThrow (obj, backtrace); break; default: throw new InvalidOperationException ("Unknown exception event type:" + (extendedInfo & (TypeException.BacktraceBit - 1))); } break; } case EventType.Monitor: { timeDiff = reader.ReadULeb128 (); Time += timeDiff; buffer.RecordTime (Time); var obj = reader.ReadSLeb128 (); byte ev = (byte)((extendedInfo >> 4) & 0x3); Backtrace backtrace; if (ev == TypeMonitor.ProfilerMonitorContention && (extendedInfo & TypeMonitor.BacktraceBit) == TypeMonitor.BacktraceBit) { backtrace = Backtrace.Read (reader); } else { backtrace = null; } HandleMonitor (obj, backtrace); break; } case EventType.Sample: switch (extendedInfo) { case TypeSample.Hit: var sampleType = (SampleType)reader.ReadULeb128 (); var timeStamp = reader.ReadULeb128 (); var count = reader.ReadULeb128 (); var instructionPointers = new long[count]; for (ulong i = 0; i < count; i++) { instructionPointers[i] = FixPointer (logHeader, buffer.Header.PtrBase + reader.ReadSLeb128 ()); } buffer.RecordTime (timeStamp); HandleSampleHit (sampleType, timeStamp, instructionPointers); break; case TypeSample.USym: var address = FixPointer (logHeader, buffer.Header.PtrBase + reader.ReadSLeb128 ()); var size = reader.ReadULeb128 (); var name = reader.ReadNullTerminatedString (); HandleSampleUSym (address, size, name); break; case TypeSample.UBin: timeDiff = reader.ReadULeb128 (); Time += timeDiff; buffer.RecordTime (Time); address = reader.ReadSLeb128 (); var offset = reader.ReadULeb128 (); size = reader.ReadULeb128 (); name = reader.ReadNullTerminatedString (); HandleSampleUBin (address, offset, size, name); break; case TypeSample.CountersDesc: var counters = new List<Tuple<ulong, string, ulong, ulong, ulong, ulong>> (); var len = reader.ReadULeb128 (); for (ulong i = 0; i < len; i++) { var csection = reader.ReadULeb128 (); var cname = reader.ReadNullTerminatedString (); var ctype = reader.ReadULeb128 (); var cunit = reader.ReadULeb128 (); var cvariance = reader.ReadULeb128 (); var cindex = reader.ReadULeb128 (); counters.Add (Tuple.Create<ulong, string, ulong, ulong, ulong, ulong> ( csection, cname, ctype, cunit, cvariance, cindex )); } HandleSampleCountersDesc (counters); break; case TypeSample.Counters: var samples = new List<Tuple<ulong, ulong, object>> (); var timestamp = reader.ReadULeb128 (); while (true) { var sindex = reader.ReadULeb128 (); if (sindex == 0) break; object sval; var stype = reader.ReadULeb128 (); switch (stype) { case TypeCountersSample.Int: case TypeCountersSample.Long: case TypeCountersSample.Word: case TypeCountersSample.TimeInterval: CountersSampleValues [sindex] = sval = reader.ReadSLeb128 () + (CountersSampleValues.ContainsKey (sindex) ? (long)(CountersSampleValues [sindex]) : 0); break; case TypeCountersSample.UInt: case TypeCountersSample.ULong: CountersSampleValues [sindex] = sval = reader.ReadULeb128 () + (CountersSampleValues.ContainsKey (sindex) ? (ulong)(CountersSampleValues [sindex]) : 0); break; case TypeCountersSample.Double: sval = reader.ReadDouble (); break; case TypeCountersSample.String: sval = reader.ReadULeb128 () == 1 ? reader.ReadNullTerminatedString () : null; break; default: throw new InvalidOperationException ("Unknown counter sample type:" + stype); } samples.Add (Tuple.Create<ulong, ulong, object> (sindex, stype, sval)); } HandleSampleCounters (timestamp, samples); break; default: throw new InvalidOperationException ("Unknown sample event:" + extendedInfo); } break; case EventType.Heap: { switch (extendedInfo) { case TypeHeap.Start: timeDiff = reader.ReadULeb128 (); Time += timeDiff; buffer.RecordTime (Time); HandleHeapStart (); break; case TypeHeap.End: timeDiff = reader.ReadULeb128 (); Time += timeDiff; buffer.RecordTime (Time); HandleHeapEnd (); break; case TypeHeap.Object: var obj = reader.ReadSLeb128 (); var cl = reader.ReadSLeb128 (); var size = reader.ReadULeb128 (); ulong num = reader.ReadULeb128 (); var objectRefs = new long[num]; var relOffsets = new ulong[num]; for (ulong i = 0; i < num; i++) { relOffsets [i] = reader.ReadULeb128 (); objectRefs [i] = reader.ReadSLeb128 (); } HandleHeapObject (obj, cl, size, relOffsets, objectRefs); break; case TypeHeap.Root: ulong numRoots = reader.ReadULeb128 (); var numGc = reader.ReadULeb128 (); var objects = new long [numRoots]; var rootTypes = new MonoProfileGCRootType [numRoots]; var extraInfos = new ulong [numRoots]; for (ulong i = 0; i < numRoots; i++) { objects[i] = reader.ReadSLeb128 (); rootTypes[i] = (MonoProfileGCRootType)reader.ReadULeb128 (); extraInfos[i] = reader.ReadULeb128 (); } HandleHeapRoot (numRoots, numGc, objects, rootTypes, extraInfos); break; default: throw new InvalidOperationException ("Unknown heap event type:" + extendedInfo); } break; } default: throw new InvalidOperationException ("invalid event type " + type); } } CurrentBuffer = null; HandleBufferEndRead (); }
public BufferDescriptor TryReadBuffer(BufferDescriptor bufferDescriptor, EventListener listener) { if (bufferDescriptor != null) Reader.Position = bufferDescriptor.FilePosition; return BufferDescriptor.Read (Header, Reader, listener); }