public ProfileData ParseIBCDataFromModule(EcmaModule ecmaModule) { ResourceData peResources = new ResourceData(ecmaModule); byte[] ibcDataSection = peResources.FindResource("PROFILE_DATA", "IBC", 0); if (ibcDataSection == null) { // If we don't have profile data, return empty ProfileData object return(EmptyProfileData.Singleton); } var reader = new IBCDataReader(); int pos = 0; bool basicBlocksOnly = false; AssemblyData parsedData = reader.Read(ibcDataSection, ref pos, out bool minified); if (parsedData.FormatMajorVersion == 1) { throw new Exception("Unsupported V1 IBC Format"); } Dictionary <IBCBlobKey, BlobEntry> blobs = GetIBCBlobs(parsedData.BlobStream, out HashSet <uint> ignoredIbcMethodSpecTokens); List <MethodProfileData> methodProfileData = new List <MethodProfileData>(); IBCModule ibcModule = new IBCModule(ecmaModule, blobs); // Parse the token lists IBCData.SectionIteratorKind iteratorKind = basicBlocksOnly ? IBCData.SectionIteratorKind.BasicBlocks : IBCData.SectionIteratorKind.TokenFlags; foreach (SectionFormat section in IBCData.SectionIterator(iteratorKind)) { if (!parsedData.Tokens.TryGetValue(section, out List <TokenData> TokenList) || TokenList.Count == 0) { continue; } // In V1 and minified V3+ files, tokens aren't stored with a // scenario mask. In minified V3+ files, it can be treated as // anything nonzero--minified files make no guarantee about // preserving scenario information, but the flags must be left // alone. const uint scenarioMaskIfMissing = 1u; HashSet <MethodDesc> methodsFoundInData = new HashSet <MethodDesc>(); foreach (TokenData entry in TokenList) { // // Discard any token list entries which refer to the ParamMethodSpec blob stream entries // (if any) which were thrown away above. Note that the MethodProfilingData token list is // the only place anywhere in the IBC data which can ever contain an embedded ibcMethodSpec // token. // if (section == SectionFormat.MethodProfilingData) { if (ignoredIbcMethodSpecTokens.Contains(entry.Token)) { continue; } } uint scenarioMask = entry.ScenarioMask ?? scenarioMaskIfMissing; // scenarioMask will be 0 in unprocessed or V1 IBC data. if (scenarioMask == 0) { // TODO Compute RunOnce and RunNever from basic block data scenarioMask = scenarioMaskIfMissing; /* Debug.Assert(fullScenarioMask == 1, "Token entry not owned by one scenario"); * // We have to compute the RunOnceMethod and RunNeverMethod flags. * entry.Flags = result.GetFlags(entry.Flags, section, entry.Token); * scenarioMask = defaultScenarioMask;*/ } // Debug.Assert(((~fullScenarioMask & scenarioMask) == 0), "Illegal scenarios mask"); MethodDesc associatedMethod = null; switch (Cor.Macros.TypeFromToken(entry.Token)) { case CorTokenType.mdtMethodDef: case CorTokenType.mdtMemberRef: case CorTokenType.mdtMethodSpec: object metadataObject = ecmaModule.GetObject(System.Reflection.Metadata.Ecma335.MetadataTokens.EntityHandle((int)entry.Token)); if (metadataObject is MethodDesc) { associatedMethod = (MethodDesc)metadataObject; } else { if (_logger.IsVerbose) { _logger.Writer.WriteLine($"Token {(int)entry.Token:x} does not refer to a method"); } } break; case CorTokenType.ibcMethodSpec: { if (!blobs.TryGetValue(new IBCBlobKey(entry.Token, BlobType.ParamMethodSpec), out BlobEntry blobEntry)) { throw new Exception($"Missing blob entry for ibcMethodSpec {entry.Token:x}"); } BlobEntry.SignatureEntry paramSignatureEntry = blobEntry as BlobEntry.SignatureEntry; if (paramSignatureEntry == null) { throw new Exception($"Blob entry for {entry.Token:x} is invalid"); } unsafe { fixed(byte *pb = ¶mSignatureEntry.Signature[0]) { BlobReader br = new BlobReader(pb, paramSignatureEntry.Signature.Length); associatedMethod = GetSigMethodInstantiationFromIBCMethodSpec(ibcModule, br); } } } break; } if (associatedMethod != null) { if (methodsFoundInData.Add(associatedMethod)) { methodProfileData.Add(new MethodProfileData(associatedMethod, (MethodProfilingDataFlags)entry.Flags, 0, null, scenarioMask, null)); } else { if (_logger.IsVerbose) { _logger.Writer.WriteLine($"Multiple copies of data for method '{associatedMethod}' found."); } } } } } return(new IBCProfileData(parsedData.PartialNGen, methodProfileData)); }