diff options
Diffstat (limited to 'src/inc/corbbtprof.h')
-rw-r--r-- | src/inc/corbbtprof.h | 589 |
1 files changed, 589 insertions, 0 deletions
diff --git a/src/inc/corbbtprof.h b/src/inc/corbbtprof.h new file mode 100644 index 0000000000..2f69dcccc8 --- /dev/null +++ b/src/inc/corbbtprof.h @@ -0,0 +1,589 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/*****************************************************************************\ +* * +* CorBBTProf.h - File format for profile data * +* * +* Version 1.0 * +******************************************************************************* +* * +* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY * +* KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE * +* IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR * +* PURPOSE. * +* * +\*****************************************************************************/ + +#ifndef _COR_BBTPROF_H_ +#define _COR_BBTPROF_H_ + +#include <cor.h> +#include <corinfo.h> + +const CorTokenType ibcExternalNamespace = CorTokenType(0x61000000); +const CorTokenType ibcExternalType = CorTokenType(0x62000000); +const CorTokenType ibcExternalSignature = CorTokenType(0x63000000); +const CorTokenType ibcExternalMethod = CorTokenType(0x64000000); +const CorTokenType ibcTypeSpec = CorTokenType(0x68000000); +const CorTokenType ibcMethodSpec = CorTokenType(0x69000000); + +typedef mdToken idExternalNamespace; // External Namespace token in the IBC data +typedef mdToken idExternalType; // External Type token in the IBC data +typedef mdToken idExternalSignature; // External Signature token in the IBC data +typedef mdToken idExternalMethod; // External Method token in the IBC data +typedef mdToken idTypeSpec; // TypeSpec token in the IBC data +typedef mdToken idMethodSpec; // MethodSpec token in the IBC data + +#define idExternalNamespaceNil ((idExternalNamespace) ibcExternalNamespace) +#define idExternalTypeNil ((idExternalType) ibcExternalType) +#define idExternalSignatureNil ((idExternalSignature) ibcExternalSignature) +#define idExternalMethodNil ((idExternalMethod) ibcExternalMethod) +#define idTypeSpecNil ((idTypeSpec) ibcTypeSpec) +#define idMethodSpecNil ((idMethodSpec) ibcMethodSpec) + +// +// File format: +// +// CORBBTPROF_FILE_HEADER +// CORBBTPROF_SECTION_TABLE_HEADER +// CORBBTPROF_SECTION_TABLE_ENTRY +// ... (can be multiple entries) +// +// Method block counts section: +// CORBBTPROF_METHOD_BLOCK_COUNTS_SECTION_HEADER +// CORBBTPROF_METHOD_HEADER +// CORBBTPROF_BLOCK_DATA +// ... (can be multiple method header/block data entries) +// +// Method load order section: +// CORBBTPROF_TOKEN_LIST_SECTION_HEADER +// ... (list of tokens) +// +// Type token usage information +// CORBBTPROF_TOKEN_LIST_SECTION_HEADER +// ... (list of tokens) +// + +// MethodDef token usage information +// CORBBTPROF_TOKEN_LIST_SECTION_HEADER +// ... (list of tokens) +// + +// RIDs to not use slim headers section +// CORBBTPROF_TOKEN_LIST_SECTION_HEADER +// ... (list of tokens) +// + +// Metadata hints to re-order some tables +// Instantiated TypeSPecs to re-order EEClasses +// +// The header for the profile data file. +// ... (list of CORBBTPROF_BLOB_ENTRY) +// terminated by null + +struct CORBBTPROF_FILE_HEADER +{ + DWORD HeaderSize; + DWORD Magic; + DWORD Version; + GUID MVID; +}; + +// Optional in V1 and V2. Usually present in V2. Must be present in V3. +struct CORBBTPROF_FILE_OPTIONAL_HEADER +{ + DWORD Size; // Including the size field + DWORD MinorVersion; + DWORD FileFlags; // Only in V3 or later + // future fields +}; + +enum CORBBTPROF_FILE_FLAGS +{ + CORBBTPROF_FILE_FLAG_MINIFIED = 1, + CORBBTPROF_FILE_FLAG_PARTIAL_NGEN = 2 +}; + +enum +{ + CORBBTPROF_V0_VERSION = 0, + CORBBTPROF_V1_VERSION = 1, + CORBBTPROF_V2_VERSION = 2, + CORBBTPROF_V3_VERSION = 3, + CORBBTPROF_CURRENT_VERSION = CORBBTPROF_V2_VERSION, // V3 is opt-in + CORBBTPROF_MAGIC = 0xb1d0f11e, + CORBBTPROF_END_TOKEN = 0xb4356f98 +}; + +// +// The profile data can be mapped anywhere in memory. So instead of using pointers, +// to denote sections, we will instead use offsets from the beginning of the file. +// + +struct Section +{ + DWORD Offset; + DWORD Size; +}; + +// +// Section types, where various sections contains different types of profile data. +// + +#define CORBBTPROF_TOKEN_MAX_NUM_FLAGS 32 + +enum TypeProfilingDataFlags +{ + // Important: update toolbox\ibcmerge\ibcmerge.cs if you change these + ReadMethodTable = 0, // 0x00001 + ReadEEClass = 1, // 0x00002 + WriteEEClass = 2, // 0x00004 +// ReadStoredEnumData = 3, // 0x00008 + ReadFieldDescs = 4, // 0x00010 + ReadCCtorInfo = 5, // 0x00020 + ReadClassHashTable = 6, // 0x00040 + ReadDispatchMap = 7, // 0x00080 + ReadDispatchTable = 8, // 0x00100 + ReadMethodTableWriteableData = 9, // 0x00200 + ReadFieldMarshalers = 10, // 0x00400 +// Unused = 11, // 0x00800 ... Was WriteDispatchTable in the past +// WriteMethodTable = 12, // 0x01000 + WriteMethodTableWriteableData = 13, // 0x02000 + ReadTypeDesc = 14, // 0x04000 + WriteTypeDesc = 15, // 0x08000 + ReadTypeHashTable = 16, // 0x10000 +// WriteTypeHashTable = 17, // 0x20000 +// ReadDictionary = 18, // 0x40000 +// WriteDictionary = 19, // 0x80000 + ReadNonVirtualSlots = 20, // 0x100000 +}; + +enum MethodProfilingDataFlags +{ + // Important: update toolbox\ibcmerge\ibcmerge.cs if you change these + ReadMethodCode = 0, // 0x00001 + ReadMethodDesc = 1, // 0x00002 + RunOnceMethod = 2, // 0x00004 // was CommonMethod + RunNeverMethod = 3, // 0x00008 // was MethodMetadataAccess +// MethodStoredDataAccess = 4, // 0x00010 + WriteMethodDesc = 5, // 0x00020 +// ReadFCallHash = 6, // 0x00040 + ReadGCInfo = 7, // 0x00080 + CommonReadGCInfo = 8, // 0x00100 +// ReadMethodDefRidMap = 9, // 0x00200 + ReadCerMethodList = 10, // 0x00400 + ReadMethodPrecode = 11, // 0x00800 + WriteMethodPrecode = 12, // 0x01000 +}; + +enum GeneralProfilingDataFlags +{ + // Important: update ibcmerge.cs if you change these + // ZapImage.h depends on 0xFFFFFFFF being an invalid flag value. If this + // changes, update ReadFlagWithMemory in that file. + // Important: make sure these don't collide with TypeProfilingDataFlags or MethodProfilingDataFlags + // These grow downward from CORBBTPROF_TOKEN_MAX_NUM_FLAGS-1 to minimize the chance of collision + ProfilingFlags_MetaData = 31, // 0x800... + CommonMetaData = 30, // 0x400... + RidMap = 29, // 0x200... + RVAFieldData = 28, // 0x100... + ProfilingFlags_MetaDataSearch = 27, // 0x080... +}; + +enum BlobType +{ + /* IMPORTANT: Keep the first four enums together in the same order and at + the very begining of this enum. See MetaModelPub.h for the order */ + MetadataStringPool = 0, + MetadataGuidPool = 1, + MetadataBlobPool = 2, + MetadataUserStringPool = 3, + + FirstMetadataPool = 0, + LastMetadataPool = 3, + + // SectionFormat only supports tokens, which have to already exist in the module. + // For instantiated paramterized types, there may be no corresponding token + // in the module, if a dependent module caused the type to be instantiated. + // For such instantiated types, we save a blob/signature to identify the type. + // + ParamTypeSpec = 4, // Instantiated Type Signature + ParamMethodSpec = 5, // Instantiated Method Signature + ExternalNamespaceDef = 6, // External Namespace Token Definition + ExternalTypeDef = 7, // External Type Token Definition + ExternalSignatureDef = 8, // External Signature Definition + ExternalMethodDef = 9, // External Method Token Definition + + IllegalBlob = 10, // Failed to allocate the blob + + EndOfBlobStream = -1 +}; + +enum SectionFormat +{ + // Important: update ibcmerge.cs if you change these + ScenarioInfo = 0, + MethodBlockCounts = 1, // Basic-block counts. Cold blocks will be placed in the cold-code section + BlobStream = 2, // metadata access, inst-type-spec and inst-method-spec blobs + + FirstTokenFlagSection = 3, + + ModuleProfilingData = FirstTokenFlagSection + (mdtModule >> 24), + TypeRefProfilingData = FirstTokenFlagSection + (mdtTypeRef >> 24), + TypeProfilingData = FirstTokenFlagSection + (mdtTypeDef >> 24), + FieldDefProfilingData = FirstTokenFlagSection + (mdtFieldDef >> 24), + MethodProfilingData = FirstTokenFlagSection + (mdtMethodDef >> 24), + ParamDefProfilingData = FirstTokenFlagSection + (mdtParamDef >> 24), + InterfaceImplProfilingData = FirstTokenFlagSection + (mdtInterfaceImpl >> 24), + MemberRefProfilingData = FirstTokenFlagSection + (mdtMemberRef >> 24), + CustomAttributeProfilingData = FirstTokenFlagSection + (mdtCustomAttribute >> 24), + PermissionProfilingData = FirstTokenFlagSection + (mdtPermission >> 24), + SignatureProfilingData = FirstTokenFlagSection + (mdtSignature >> 24), + EventProfilingData = FirstTokenFlagSection + (mdtEvent >> 24), + PropertyProfilingData = FirstTokenFlagSection + (mdtProperty >> 24), + ModuleRefProfilingData = FirstTokenFlagSection + (mdtModuleRef >> 24), + TypeSpecProfilingData = FirstTokenFlagSection + (mdtTypeSpec >> 24), + AssemblyProfilingData = FirstTokenFlagSection + (mdtAssembly >> 24), + AssemblyRefProfilingData = FirstTokenFlagSection + (mdtAssemblyRef >> 24), + FileProfilingData = FirstTokenFlagSection + (mdtFile >> 24), + ExportedTypeProfilingData = FirstTokenFlagSection + (mdtExportedType >> 24), + ManifestResourceProfilingData = FirstTokenFlagSection + (mdtManifestResource >> 24), + GenericParamProfilingData = FirstTokenFlagSection + (mdtGenericParam >> 24), + MethodSpecProfilingData = FirstTokenFlagSection + (mdtMethodSpec >> 24), + GenericParamConstraintProfilingData = FirstTokenFlagSection + (mdtGenericParamConstraint >> 24), + + StringPoolProfilingData, + GuidPoolProfilingData, + BlobPoolProfilingData, + UserStringPoolProfilingData, + + FirstMetadataPoolSection = StringPoolProfilingData, + LastMetadataPoolSection = UserStringPoolProfilingData, + LastTokenFlagSection = LastMetadataPoolSection, + + IbcTypeSpecSection, + IbcMethodSpecSection, + + GenericTypeProfilingData = 63, // Deprecated with V2 IBC data + SectionFormatCount = 64, // 0x40 + + SectionFormatInvalid = -1 +}; + +struct CORBBTPROF_SECTION_TABLE_ENTRY +{ + SectionFormat FormatID; + Section Data; +}; + +struct CORBBTPROF_SECTION_TABLE_HEADER +{ + DWORD NumEntries; + CORBBTPROF_SECTION_TABLE_ENTRY Entries[0]; +}; + +// +// ScenarioInfo section +// + +struct CORBBTPROF_SCENARIO_RUN +{ + FILETIME runTime; // the FILETIME when the scenario was cnt + GUID mvid; // The GUID of this assembly when the scenario was run (useful for incremental ibcdata) + DWORD cCmdLine; // the count of WCHAR's in the cmdLine for this run of the scenario + DWORD cSystemInfo; // the count of WCHAR's in the systemInfo string for this run of the scenario + WCHAR cmdLine[0]; // the command line used, the array is 'cName' in length +// WCHAR systemInfo[]; // the system information, the array is 'cSystemInfo' in length + + DWORD sizeofCmdLine() + { + return (cCmdLine * (DWORD)sizeof(WCHAR)); + } + + DWORD sizeofSystemInfo() + { + return (cSystemInfo * (DWORD)sizeof(WCHAR)); + } + + DWORD Size() + { + return (DWORD)sizeof(CORBBTPROF_SCENARIO_RUN) + sizeofCmdLine() + sizeofSystemInfo(); + } + + CORBBTPROF_SCENARIO_RUN* GetNextRun() + { + return reinterpret_cast< CORBBTPROF_SCENARIO_RUN* >( + reinterpret_cast< PBYTE >( this + 1 ) + Size() ); + } +}; + +struct CORBBTPROF_SCENARIO_INFO +{ + DWORD ordinal; // the id number for this scenario + DWORD mask; // the one-bit mask use to identify this scenario + DWORD priority; // the priority of this scenario + DWORD numRuns; // the number of times this scenario was run + DWORD cName; // the count of WCHAR's in name[] + WCHAR name[0]; // the name of this scenario, the array is 'cName' in length +// CORBBTPROF_SCENARIO_RUN run[]; // the array is 'numRuns' in length + + DWORD sizeofName() + { + return (DWORD) (cName * sizeof(WCHAR)); + } + + DWORD Size() + { + return (DWORD) sizeof(CORBBTPROF_SCENARIO_INFO) + sizeofName() + sizeofRuns(); + } + + CORBBTPROF_SCENARIO_RUN* GetScenarioRun() + { + return reinterpret_cast< CORBBTPROF_SCENARIO_RUN* >( + reinterpret_cast< PBYTE >( this ) + (DWORD)sizeof(CORBBTPROF_SCENARIO_INFO) + sizeofName()); + } + + DWORD sizeofRuns() + { + DWORD sum = 0; + if (numRuns > 0) + { + DWORD cnt = 1; + CORBBTPROF_SCENARIO_RUN* pRun = GetScenarioRun(); + do + { + sum += pRun->Size(); + if (cnt == numRuns) + break; + cnt++; + pRun = pRun->GetNextRun(); + } + while (true); + } + return sum; + } +}; + +struct CORBBTPROF_SCENARIO_HEADER +{ + DWORD size; // Size to skip to get to the next CORBBTPROF_SCENARIO_HEADER + CORBBTPROF_SCENARIO_INFO scenario; + + DWORD Size() + { + return (DWORD) sizeof(CORBBTPROF_SCENARIO_HEADER) + scenario.sizeofName() + scenario.sizeofRuns(); + } +}; + +struct CORBBTPROF_SCENARIO_INFO_SECTION_HEADER +{ + DWORD TotalNumRuns; + DWORD NumScenarios; +// CORBBTPROF_SCENARIO_HEADER scenario[0]; // array is 'NumScenarios' in length +}; + +// +// MethodBlockCounts section +// + +struct CORBBTPROF_METHOD_BLOCK_COUNTS_SECTION_HEADER_V1 +{ + DWORD NumMethods; + DWORD NumRuns; +}; + +struct CORBBTPROF_METHOD_BLOCK_COUNTS_SECTION_HEADER +{ + DWORD NumMethods; +}; + +struct CORBBTPROF_BLOCK_DATA // Also defined here code:ICorJitInfo.ProfileBuffer +{ + DWORD ILOffset; + DWORD ExecutionCount; +}; + +struct CORBBTPROF_METHOD_DETAIL_HEADER +{ + DWORD size; // Size to skip to get to the next CORBBTPROF_METHOD_DETAIL_HEADER at this level + DWORD kind; // Identifier that specifies what kind this CORBBTPROF_METHOD_DETAIL_HEADER actually represents + + size_t Size() + { + return size; + } +}; + +// +// This struct records the basic block execution counts for a method +// +struct CORBBTPROF_METHOD_INFO +{ + DWORD token; // token for this method + DWORD ILSize; // IL size for this method + DWORD cBlock; // count for block[] + CORBBTPROF_BLOCK_DATA block[0]; // actually 'cBlock' in length + + size_t Size() + { + return sizeof(CORBBTPROF_METHOD_INFO) + sizeofBlock(); + } + + size_t sizeofBlock() + { + return cBlock * sizeof(CORBBTPROF_BLOCK_DATA); + } +}; + +struct CORBBTPROF_METHOD_HEADER_V1 +{ + DWORD HeaderSize; + mdToken MethodToken; + DWORD Size; +}; + +struct CORBBTPROF_METHOD_HEADER +{ + DWORD size; // Size to skip to get to the next CORBBTPROF_METHOD_HEADER + DWORD cDetail; // the count of CORBBTPROF_METHOD_DETAIL_HEADER records that folow this record + CORBBTPROF_METHOD_INFO method; // Basic block execution counts for a method + // ... followed by 'cDetail' occurances of CORBBTPROF_METHOD_DETAIL_HEADER + + size_t Size() + { + return sizeof(CORBBTPROF_METHOD_HEADER) + method.sizeofBlock(); + } +}; + + +struct CORBBTPROF_TOKEN_LIST_SECTION_HEADER +{ + DWORD NumTokens; +}; + +struct CORBBTPROF_TOKEN_LIST_ENTRY_V1 +{ + mdToken token; + DWORD flags; +}; + +struct CORBBTPROF_TOKEN_INFO // Was CORBBTPROF_TOKEN_LIST_ENTRY +{ + mdToken token; + DWORD flags; + DWORD scenarios; // Could use UINT64 instead + + CORBBTPROF_TOKEN_INFO() + : token(0) + , flags(0) + , scenarios(0) + {} + + CORBBTPROF_TOKEN_INFO( mdToken t, DWORD f = 0, DWORD s = 0) + : token(t) + , flags(f) + , scenarios(s) + {} + + CORBBTPROF_TOKEN_INFO( CORBBTPROF_TOKEN_INFO const & right ) + : token(right.token) + , flags(right.flags) + , scenarios(right.scenarios) + {} + + CORBBTPROF_TOKEN_INFO operator=( CORBBTPROF_TOKEN_INFO const & right ) + { + token = right.token; + flags = right.flags; + scenarios = right.scenarios; + return *this; + } + + bool operator<( CORBBTPROF_TOKEN_INFO const & right ) const + { + return token < right.token; + } +}; + +struct CORBBTPROF_BLOB_ENTRY_V1 +{ + BlobType blobType; + DWORD flags; + DWORD cBuffer; + BYTE pBuffer[0]; // actually 'cBuffer' in length + + CORBBTPROF_BLOB_ENTRY_V1 * GetNextEntry() + { + return reinterpret_cast< CORBBTPROF_BLOB_ENTRY_V1* >( + reinterpret_cast< PBYTE >( this + 1 ) + cBuffer ); + } +}; + +struct CORBBTPROF_BLOB_ENTRY +{ + DWORD size; + BlobType type; + mdToken token; // The code:CORBBTPROF_BLOB_ENTRY.token field is not a real meta-data token + // but a look-alike that IBCMerge makes to represent blob entry + + bool TypeIsValid() + { + return (type >= MetadataStringPool) && (type < IllegalBlob); + } + + CORBBTPROF_BLOB_ENTRY * GetNextEntry() + { + return reinterpret_cast< CORBBTPROF_BLOB_ENTRY* >( + reinterpret_cast< PBYTE >( this ) + size); + } +}; + +struct CORBBTPROF_BLOB_PARAM_SIG_ENTRY +{ + CORBBTPROF_BLOB_ENTRY blob; + DWORD cSig; + COR_SIGNATURE sig[0]; // actually 'cSig' in length +}; + +struct CORBBTPROF_BLOB_NAMESPACE_DEF_ENTRY +{ + CORBBTPROF_BLOB_ENTRY blob; + DWORD cName; + CHAR name[0]; // actually cName in length +}; + +struct CORBBTPROF_BLOB_TYPE_DEF_ENTRY +{ + CORBBTPROF_BLOB_ENTRY blob; + mdToken assemblyRefToken; + mdToken nestedClassToken; + mdToken nameSpaceToken; + DWORD cName; + CHAR name[0]; // actually cName in length +}; + +struct CORBBTPROF_BLOB_SIGNATURE_DEF_ENTRY +{ + CORBBTPROF_BLOB_ENTRY blob; + DWORD cSig; + COR_SIGNATURE sig[0]; // actually 'cSig' in length +}; + +struct CORBBTPROF_BLOB_METHOD_DEF_ENTRY +{ + CORBBTPROF_BLOB_ENTRY blob; + mdToken nestedClassToken; + mdToken signatureToken; + DWORD cName; + CHAR name[0]; // actually cName in length +}; + +struct CORBBTPROF_BLOB_POOL_ENTRY +{ + CORBBTPROF_BLOB_ENTRY blob; + DWORD cBuffer; + BYTE buffer[0]; // actually 'cBuffer' in length +}; +#endif /* COR_BBTPROF_H_ */ |