public static void EncodePgoData <TType>(IEnumerable <PgoSchemaElem> schemas, IPgoEncodedValueEmitter <TType> valueEmitter, bool emitAllElementsUnconditionally) { PgoSchemaElem prevSchema = default(PgoSchemaElem); TType prevEmittedType = default(TType); long prevEmittedIntData = 0; foreach (PgoSchemaElem schema in schemas) { int ilOffsetDiff = schema.ILOffset - prevSchema.ILOffset; int OtherDiff = schema.Other - prevSchema.Other; int CountDiff = schema.Count - prevSchema.Count; int TypeDiff = (int)schema.InstrumentationKind - (int)prevSchema.InstrumentationKind; InstrumentationDataProcessingState modifyMask = (InstrumentationDataProcessingState)0; if (!emitAllElementsUnconditionally) { if (ilOffsetDiff != 0) { modifyMask = modifyMask | InstrumentationDataProcessingState.ILOffset; } if (TypeDiff != 0) { modifyMask = modifyMask | InstrumentationDataProcessingState.Type; } if (CountDiff != 0) { modifyMask = modifyMask | InstrumentationDataProcessingState.Count; } if (OtherDiff != 0) { modifyMask = modifyMask | InstrumentationDataProcessingState.Other; } } else { modifyMask = InstrumentationDataProcessingState.ILOffset | InstrumentationDataProcessingState.Type | InstrumentationDataProcessingState.Count | InstrumentationDataProcessingState.Other; } Debug.Assert(modifyMask != InstrumentationDataProcessingState.Done); valueEmitter.EmitLong((long)modifyMask, 0); if ((modifyMask & InstrumentationDataProcessingState.ILOffset) == InstrumentationDataProcessingState.ILOffset) { valueEmitter.EmitLong(schema.ILOffset, prevSchema.ILOffset); } if ((modifyMask & InstrumentationDataProcessingState.Type) == InstrumentationDataProcessingState.Type) { valueEmitter.EmitLong((long)schema.InstrumentationKind, (long)prevSchema.InstrumentationKind); } if ((modifyMask & InstrumentationDataProcessingState.Count) == InstrumentationDataProcessingState.Count) { valueEmitter.EmitLong(schema.Count, prevSchema.Count); } if ((modifyMask & InstrumentationDataProcessingState.Other) == InstrumentationDataProcessingState.Other) { valueEmitter.EmitLong(schema.Other, prevSchema.Other); } for (int i = 0; i < schema.Count; i++) { switch (schema.InstrumentationKind & PgoInstrumentationKind.MarshalMask) { case PgoInstrumentationKind.None: break; case PgoInstrumentationKind.FourByte: { long valueToEmit; if (schema.Count == 1) { valueToEmit = schema.DataLong; } else { valueToEmit = ((int[])schema.DataObject)[i]; } valueEmitter.EmitLong(valueToEmit, prevEmittedIntData); prevEmittedIntData = valueToEmit; break; } case PgoInstrumentationKind.EightByte: { long valueToEmit; if (schema.Count == 1) { valueToEmit = schema.DataLong; } else { valueToEmit = ((long[])schema.DataObject)[i]; } valueEmitter.EmitLong(valueToEmit, prevEmittedIntData); prevEmittedIntData = valueToEmit; break; } case PgoInstrumentationKind.TypeHandle: { TType typeToEmit = ((TType[])schema.DataObject)[i]; valueEmitter.EmitType(typeToEmit, prevEmittedType); prevEmittedType = typeToEmit; break; } } } prevSchema = schema; } // Emit a "done" schema if (!valueEmitter.EmitDone()) { // If EmitDone returns true, no further data needs to be encoded. // Otherwise, emit a "Done" schema valueEmitter.EmitLong((long)InstrumentationDataProcessingState.Type, 0); valueEmitter.EmitLong((long)PgoInstrumentationKind.Done, (long)prevSchema.InstrumentationKind); } }
public static IEnumerable <PgoSchemaElem> ParsePgoData <TType>(IPgoSchemaDataLoader <TType> dataProvider, IEnumerable <long> inputDataStream, bool longsAreCompressed) { int dataCountToRead = 0; PgoSchemaElem curSchema = default(PgoSchemaElem); InstrumentationDataProcessingState processingState = InstrumentationDataProcessingState.UpdateProcessMaskFlag; long lastDataValue = 0; long lastTypeValue = 0; foreach (long value in inputDataStream) { if (dataCountToRead > 0) { if (curSchema.DataHeldInDataLong) { if (longsAreCompressed) { lastDataValue += value; } else { lastDataValue = value; } curSchema.DataLong = lastDataValue; } else { int dataIndex = curSchema.Count - dataCountToRead; switch (curSchema.InstrumentationKind & PgoInstrumentationKind.MarshalMask) { case PgoInstrumentationKind.FourByte: if (longsAreCompressed) { lastDataValue += value; } else { lastDataValue = value; } ((int[])curSchema.DataObject)[dataIndex] = checked ((int)lastDataValue); break; case PgoInstrumentationKind.EightByte: if (longsAreCompressed) { lastDataValue += value; } else { lastDataValue = value; } ((long[])curSchema.DataObject)[dataIndex] = lastDataValue; break; case PgoInstrumentationKind.TypeHandle: if (longsAreCompressed) { lastTypeValue += value; } else { lastTypeValue = value; } ((TType[])curSchema.DataObject)[dataIndex] = dataProvider.TypeFromLong(lastTypeValue); break; } } dataCountToRead--; if (dataCountToRead == 0) { yield return(curSchema); curSchema.DataLong = 0; curSchema.DataObject = null; } continue; } if (processingState == InstrumentationDataProcessingState.UpdateProcessMaskFlag) { processingState = (InstrumentationDataProcessingState)value; continue; } if ((processingState & InstrumentationDataProcessingState.ILOffset) == InstrumentationDataProcessingState.ILOffset) { if (longsAreCompressed) { curSchema.ILOffset = checked ((int)(value + (long)curSchema.ILOffset)); } else { curSchema.ILOffset = checked ((int)value); } processingState = processingState & ~InstrumentationDataProcessingState.ILOffset; } else if ((processingState & InstrumentationDataProcessingState.Type) == InstrumentationDataProcessingState.Type) { if (longsAreCompressed) { curSchema.InstrumentationKind = (PgoInstrumentationKind)(((int)(curSchema.InstrumentationKind)) + checked ((int)value)); } else { curSchema.InstrumentationKind = (PgoInstrumentationKind)value; } processingState = processingState & ~InstrumentationDataProcessingState.Type; } else if ((processingState & InstrumentationDataProcessingState.Count) == InstrumentationDataProcessingState.Count) { if (longsAreCompressed) { curSchema.Count = checked ((int)(value + (long)curSchema.Count)); } else { curSchema.Count = checked ((int)value); } processingState = processingState & ~InstrumentationDataProcessingState.Count; } else if ((processingState & InstrumentationDataProcessingState.Other) == InstrumentationDataProcessingState.Other) { if (longsAreCompressed) { curSchema.Other = checked ((int)(value + (long)curSchema.Other)); } else { curSchema.Other = checked ((int)value); } processingState = processingState & ~InstrumentationDataProcessingState.Other; } if (processingState == InstrumentationDataProcessingState.Done) { processingState = InstrumentationDataProcessingState.UpdateProcessMaskFlag; if (curSchema.InstrumentationKind == PgoInstrumentationKind.Done) { yield break; } switch (curSchema.InstrumentationKind & PgoInstrumentationKind.MarshalMask) { case PgoInstrumentationKind.None: yield return(curSchema); break; case PgoInstrumentationKind.FourByte: if (curSchema.Count > 1) { curSchema.DataObject = new int[curSchema.Count]; } dataCountToRead = curSchema.Count; break; case PgoInstrumentationKind.EightByte: if (curSchema.Count > 1) { curSchema.DataObject = new long[curSchema.Count]; } dataCountToRead = curSchema.Count; break; case PgoInstrumentationKind.TypeHandle: curSchema.DataObject = new TType[curSchema.Count]; dataCountToRead = curSchema.Count; break; default: throw new Exception("Unknown Type"); } } } throw new Exception("Partial Instrumentation Data"); }