Пример #1
0
        // ...
        /// <summary>
        /// Emit a global method "MibcConfig" that will contain key-value settings in the following format:
        ///   ldstr "key1"
        ///   ldstr "value1"
        ///   pop
        ///   pop
        ///   ldstr "key2"
        ///   ldstr "value2"
        ///   pop
        ///   pop
        ///   ...
        /// </summary>
        public static void GenerateConfigData(MibcConfig config, TypeSystemMetadataEmitter emitter)
        {
            var buffer = new BlobBuilder();
            var il     = new InstructionEncoder(buffer);

            foreach (FieldInfo mibcCfgField in typeof(MibcConfig).GetFields())
            {
                Debug.Assert(!mibcCfgField.IsStatic && mibcCfgField.FieldType == typeof(string));
                il.LoadString(emitter.GetUserStringHandle(mibcCfgField.Name));
                il.LoadString(emitter.GetUserStringHandle((string)mibcCfgField.GetValue(config) ?? ""));
                il.OpCode(ILOpCode.Pop);
                il.OpCode(ILOpCode.Pop);
            }
            il.OpCode(ILOpCode.Ret);
            emitter.AddGlobalMethod(nameof(MibcConfig), il, 8);
        }
Пример #2
0
        static int GenerateMibcFile(TraceTypeSystemContext tsc, FileInfo outputFileName, ICollection <ProcessedMethodData> methodsToAttemptToPlaceIntoProfileData, bool validate)
        {
            TypeSystemMetadataEmitter emitter = new TypeSystemMetadataEmitter(new AssemblyName(outputFileName.Name), tsc);

            SortedDictionary <string, MIbcGroup> groups     = new SortedDictionary <string, MIbcGroup>();
            StringBuilder    mibcGroupNameBuilder           = new StringBuilder();
            HashSet <string> assembliesAssociatedWithMethod = new HashSet <string>();

            foreach (var entry in methodsToAttemptToPlaceIntoProfileData)
            {
                MethodDesc method = entry.Method;
                assembliesAssociatedWithMethod.Clear();
                AddAssembliesAssociatedWithMethod(method, assembliesAssociatedWithMethod, out string definingAssembly);

                string[] assemblyNames = new string[assembliesAssociatedWithMethod.Count];
                int      i             = 1;
                assemblyNames[0] = definingAssembly;

                foreach (string s in assembliesAssociatedWithMethod)
                {
                    if (s.Equals(definingAssembly))
                    {
                        continue;
                    }
                    assemblyNames[i++] = s;
                }

                // Always keep the defining assembly as the first name
                Array.Sort(assemblyNames, 1, assemblyNames.Length - 1);
                mibcGroupNameBuilder.Clear();
                foreach (string s in assemblyNames)
                {
                    mibcGroupNameBuilder.Append(s);
                    mibcGroupNameBuilder.Append(';');
                }

                string mibcGroupName = mibcGroupNameBuilder.ToString();
                if (!groups.TryGetValue(mibcGroupName, out MIbcGroup mibcGroup))
                {
                    mibcGroup = new MIbcGroup(mibcGroupName, emitter);
                    groups.Add(mibcGroupName, mibcGroup);
                }
                mibcGroup.AddProcessedMethodData(entry);
            }

            var buffer = new BlobBuilder();
            var il     = new InstructionEncoder(buffer);

            foreach (var entry in groups)
            {
                il.LoadString(emitter.GetUserStringHandle(entry.Key));
                il.OpCode(ILOpCode.Ldtoken);
                il.Token(entry.Value.EmitMethod());
                il.OpCode(ILOpCode.Pop);
            }

            emitter.AddGlobalMethod("AssemblyDictionary", il, 8);
            MemoryStream peFile = new MemoryStream();

            emitter.SerializeToStream(peFile);
            peFile.Position = 0;

            if (outputFileName.Exists)
            {
                outputFileName.Delete();
            }

            using (ZipArchive file = ZipFile.Open(outputFileName.FullName, ZipArchiveMode.Create))
            {
                var entry = file.CreateEntry(outputFileName.Name + ".dll", CompressionLevel.Optimal);
                using (Stream archiveStream = entry.Open())
                {
                    peFile.CopyTo(archiveStream);
                }
            }

            Console.WriteLine($"Generated {outputFileName.FullName}");
            if (validate)
            {
                return(ValidateMIbcData(tsc, outputFileName, peFile.ToArray(), methodsToAttemptToPlaceIntoProfileData));
            }
            else
            {
                return(0);
            }
        }
Пример #3
0
            public void AddProcessedMethodData(MethodProfileData processedMethodData)
            {
                MethodDesc method = processedMethodData.Method;

                // Format is
                // ldtoken method
                // variable amount of extra metadata about the method, Extension data is encoded via ldstr "id"
                // pop

                // Extensions generated by this emitter:
                //
                // ldstr "ExclusiveWeight"
                // Any ldc.i4 or ldc.r4 or ldc.r8 instruction to indicate the exclusive weight
                //
                // ldstr "WeightedCallData"
                // ldc.i4 <Count of methods called>
                // Repeat <Count of methods called times>
                //  ldtoken <Method called from this method>
                //  ldc.i4 <Weight associated with calling the <Method called from this method>>
                //
                // ldstr "InstrumentationDataStart"
                // Encoded ints and longs, using ldc.i4, and ldc.i8 instructions as well as ldtoken <type> instructions
                // ldstr "InstrumentationDataEnd" as a terminator
                try
                {
                    EntityHandle methodHandle = _emitter.GetMethodRef(method);
                    _il.OpCode(ILOpCode.Ldtoken);
                    _il.Token(methodHandle);
                    if (processedMethodData.ExclusiveWeight != 0)
                    {
                        _il.LoadString(_emitter.GetUserStringHandle("ExclusiveWeight"));
                        if (((double)(int)processedMethodData.ExclusiveWeight) == processedMethodData.ExclusiveWeight)
                        {
                            _il.LoadConstantI4((int)processedMethodData.ExclusiveWeight);
                        }
                        else
                        {
                            _il.LoadConstantR8(processedMethodData.ExclusiveWeight);
                        }
                    }
                    if ((processedMethodData.CallWeights != null) && processedMethodData.CallWeights.Count > 0)
                    {
                        _il.LoadString(_emitter.GetUserStringHandle("WeightedCallData"));
                        _il.LoadConstantI4(processedMethodData.CallWeights.Count);
                        foreach (var entry in processedMethodData.CallWeights)
                        {
                            EntityHandle calledMethod = _emitter.GetMethodRef(entry.Key);
                            _il.OpCode(ILOpCode.Ldtoken);
                            _il.Token(calledMethod);
                            _il.LoadConstantI4(entry.Value);
                        }
                    }
                    if (processedMethodData.SchemaData != null)
                    {
                        _il.LoadString(_emitter.GetUserStringHandle("InstrumentationDataStart"));
                        PgoProcessor.EncodePgoData <TypeSystemEntityOrUnknown, TypeSystemEntityOrUnknown>(processedMethodData.SchemaData, this, true);
                    }
                    _il.OpCode(ILOpCode.Pop);
                }
                catch (Exception ex)
                {
                    Program.PrintWarning($"Exception {ex} while attempting to generate method lists");
                }
            }