-
Notifications
You must be signed in to change notification settings - Fork 5.4k
[cDAC] Implement GetTieredVersions for cDAC #126164
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||
|---|---|---|---|---|
|
|
@@ -22,6 +22,14 @@ public enum ModuleFlags | |||
| Tenured = 0x1, // Set once we know for sure the Module will not be freed until the appdomain itself exits | ||||
| EditAndContinue = 0x8, // Edit and Continue is enabled for this module | ||||
| ReflectionEmit = 0x40, // Reflection.Emit was used to create this module | ||||
| ProfilerDisableOpt = 0x80, // Profiler disabled JIT optimizations when module was loaded | ||||
| } | ||||
|
|
||||
| [Flags] | ||||
| public enum DebuggerAssemblyControlFlags | ||||
| { | ||||
| DACF_USER_OVERRIDE = 0x01, | ||||
| DACF_ALLOW_JIT_OPTS = 0x02, | ||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. When adding these flags that mirror enums, please add comments in the native enum of the format [cDAC] [insert whichever contract depends on it] : cDAC depends on this value. See runtime/src/coreclr/vm/comcallablewrapper.h Line 752 in 67495bc
|
||||
| } | ||||
|
|
||||
| [Flags] | ||||
|
|
@@ -75,6 +83,8 @@ public interface ILoader : IContract | |||
|
|
||||
| bool IsProbeExtensionResultValid(ModuleHandle handle) => throw new NotImplementedException(); | ||||
| ModuleFlags GetFlags(ModuleHandle handle) => throw new NotImplementedException(); | ||||
| bool IsReadyToRun(ModuleHandle handle) => throw new NotImplementedException(); | ||||
| DebuggerAssemblyControlFlags GetDebuggerInfoBits(ModuleHandle handle) => throw new NotImplementedException(); | ||||
| bool TryGetSimpleName(ModuleHandle handle, out string simpleName) => throw new NotImplementedException(); | ||||
| string GetPath(ModuleHandle handle) => throw new NotImplementedException(); | ||||
| string GetFileName(ModuleHandle handle) => throw new NotImplementedException(); | ||||
|
|
||||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -413,4 +413,31 @@ bool ICodeVersions.HasDefaultIL(ILCodeVersionHandle iLCodeVersionHandle) | |||||
| { | ||||||
| return iLCodeVersionHandle.IsExplicit ? AsNode(iLCodeVersionHandle).ILAddress == TargetPointer.Null : true; | ||||||
| } | ||||||
|
|
||||||
| NativeCodeVersionOptimizationTier ICodeVersions.GetOptimizationTier(NativeCodeVersionHandle codeVersionHandle) | ||||||
| { | ||||||
| if (!codeVersionHandle.Valid) | ||||||
| { | ||||||
| throw new ArgumentException("Invalid NativeCodeVersionHandle"); | ||||||
| } | ||||||
|
|
||||||
| if (codeVersionHandle.IsExplicit) | ||||||
| { | ||||||
| NativeCodeVersionNode nativeCodeVersionNode = _target.ProcessedData.GetOrAdd<NativeCodeVersionNode>(codeVersionHandle.CodeVersionNodeAddress); | ||||||
| return nativeCodeVersionNode.OptimizationTier is null | ||||||
| ? NativeCodeVersionOptimizationTier.OptimizationTierUnknown | ||||||
| : (NativeCodeVersionOptimizationTier) nativeCodeVersionNode.OptimizationTier; | ||||||
|
||||||
| : (NativeCodeVersionOptimizationTier) nativeCodeVersionNode.OptimizationTier; | |
| : (NativeCodeVersionOptimizationTier) nativeCodeVersionNode.OptimizationTier.Value; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -14,13 +14,16 @@ namespace Microsoft.Diagnostics.DataContractReader.Contracts; | |
| { | ||
| private const string DefaultDomainFriendlyName = "DefaultDomain"; | ||
| private const uint ASSEMBLY_NOTIFYFLAGS_PROFILER_NOTIFIED = 0x1; // Assembly Notify Flag for profiler notification | ||
| private const uint DEBUGGER_INFO_MASK_PRIV = 0x0000FC00; | ||
| private const int DEBUGGER_INFO_SHIFT_PRIV = 10; | ||
| private const ushort MaxWebcilSections = 16; // Must stay in sync with native WEBCIL_MAX_SECTIONS. | ||
|
|
||
| private enum ModuleFlags_1 : uint | ||
| { | ||
| Tenured = 0x1, // Set once we know for sure the Module will not be freed until the appdomain itself exits | ||
| EditAndContinue = 0x8, // Edit and Continue is enabled for this module | ||
| ReflectionEmit = 0x40, // Reflection.Emit was used to create this module | ||
| ProfilerDisableOpt = 0x80, // Profiler disabled JIT optimizations when module was loaded | ||
| } | ||
|
|
||
| private enum PEImageFlags : uint | ||
|
|
@@ -366,6 +369,8 @@ private static ModuleFlags GetFlags(Data.Module module) | |
| flags |= ModuleFlags.EditAndContinue; | ||
| if (runtimeFlags.HasFlag(ModuleFlags_1.ReflectionEmit)) | ||
| flags |= ModuleFlags.ReflectionEmit; | ||
| if (runtimeFlags.HasFlag(ModuleFlags_1.ProfilerDisableOpt)) | ||
| flags |= ModuleFlags.ProfilerDisableOpt; | ||
|
|
||
| return flags; | ||
| } | ||
|
|
@@ -376,6 +381,18 @@ ModuleFlags ILoader.GetFlags(ModuleHandle handle) | |
| return GetFlags(module); | ||
| } | ||
|
|
||
| bool ILoader.IsReadyToRun(ModuleHandle handle) | ||
| { | ||
| Data.Module module = _target.ProcessedData.GetOrAdd<Data.Module>(handle.Address); | ||
| return module.ReadyToRunInfo != TargetPointer.Null; | ||
| } | ||
|
|
||
| DebuggerAssemblyControlFlags ILoader.GetDebuggerInfoBits(ModuleHandle handle) | ||
| { | ||
| Data.Module module = _target.ProcessedData.GetOrAdd<Data.Module>(handle.Address); | ||
| return (DebuggerAssemblyControlFlags)((module.Flags & DEBUGGER_INFO_MASK_PRIV) >> DEBUGGER_INFO_SHIFT_PRIV); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These should be in an enum |
||
| } | ||
|
|
||
| bool ILoader.TryGetSimpleName(ModuleHandle handle, out string simpleName) | ||
| { | ||
| simpleName = string.Empty; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1645,6 +1645,86 @@ TargetPointer IRuntimeTypeSystem.GetGCStressCodeCopy(MethodDescHandle methodDesc | |
| return TargetPointer.Null; | ||
| } | ||
|
|
||
| NativeCodeVersionOptimizationTier IRuntimeTypeSystem.GetMethodDescOptimizationTier(MethodDescHandle methodDescHandle) | ||
|
Comment on lines
1645
to
+1648
|
||
| { | ||
| MethodDesc methodDesc = _methodDescs[methodDescHandle.Address]; | ||
| TargetPointer codeDataAddress = methodDesc.CodeData; | ||
| if (codeDataAddress == TargetPointer.Null) | ||
| return NativeCodeVersionOptimizationTier.OptimizationTierUnknown; | ||
|
|
||
| Data.MethodDescCodeData codeData = _target.ProcessedData.GetOrAdd<Data.MethodDescCodeData>(codeDataAddress); | ||
| return codeData.OptimizationTier is null | ||
| ? NativeCodeVersionOptimizationTier.OptimizationTierUnknown | ||
| : (NativeCodeVersionOptimizationTier)codeData.OptimizationTier; | ||
| } | ||
|
|
||
| bool IRuntimeTypeSystem.IsEligibleForTieredCompilation(MethodDescHandle methodDescHandle) | ||
| { | ||
| MethodDesc methodDesc = _methodDescs[methodDescHandle.Address]; | ||
| return methodDesc.IsEligibleForTieredCompilation; | ||
| } | ||
|
|
||
| private bool IsJitOptimizationDisabledForSpecificMethod(MethodDescHandle methodDescHandle) | ||
| { | ||
| MethodDesc methodDesc = _methodDescs[methodDescHandle.Address]; | ||
| MethodTable methodTable = GetOrCreateMethodTable(methodDesc); | ||
|
Comment on lines
+1654
to
+1670
|
||
| ModuleHandle moduleHandle = _target.Contracts.Loader.GetModuleHandleFromModulePtr(methodTable.Module); | ||
| MetadataReader? mdReader = _target.Contracts.EcmaMetadata.GetMetadata(moduleHandle); | ||
|
|
||
| bool isNoMetadata = methodDesc.Classification == MethodClassification.Dynamic; | ||
| bool isMiNoOptimization = false; | ||
| if (mdReader is not null) | ||
| { | ||
| MethodDefinitionHandle methodDefHandle = MetadataTokens.MethodDefinitionHandle((int)methodDesc.Token); | ||
| MethodDefinition methodDef = mdReader.GetMethodDefinition(methodDefHandle); | ||
| MethodImplAttributes implAttrs = methodDef.ImplAttributes; | ||
| isMiNoOptimization = (implAttrs & MethodImplAttributes.NoOptimization) != 0; | ||
| } | ||
| else if (!isNoMetadata) | ||
|
Comment on lines
+1679
to
+1683
|
||
| { | ||
| throw new InvalidOperationException("Failed to get metadata for method"); | ||
| } | ||
|
|
||
| return !isNoMetadata && isMiNoOptimization; | ||
| } | ||
|
|
||
| private bool IsJitOptimizationDisabledForAllMethodsInChunk(MethodDescHandle methodDescHandle) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It would be better to call this |
||
| { | ||
| MethodDesc methodDesc = _methodDescs[methodDescHandle.Address]; | ||
| MethodTable methodTable = GetOrCreateMethodTable(methodDesc); | ||
| ModuleHandle moduleHandle = _target.Contracts.Loader.GetModuleHandleFromModulePtr(methodTable.Module); | ||
| DebuggerAssemblyControlFlags debuggerInfoBits = _target.Contracts.Loader.GetDebuggerInfoBits(moduleHandle); | ||
| DebuggerControlFlag corDebuggerControlFlags = (DebuggerControlFlag)_target.Read<uint>(_target.ReadGlobalPointer(Constants.Globals.CORDebuggerControlFlags)); | ||
| TargetPointer eeConfigPtr = _target.ReadPointer(_target.ReadGlobalPointer(Constants.Globals.EEConfig)); | ||
| Data.EEConfig eeConfig = _target.ProcessedData.GetOrAdd<Data.EEConfig>(eeConfigPtr); | ||
|
|
||
| bool corDebuggerAllowJITOpts = debuggerInfoBits.HasFlag(DebuggerAssemblyControlFlags.DACF_ALLOW_JIT_OPTS) | ||
| || (corDebuggerControlFlags.HasFlag(DebuggerControlFlag.DBCF_ALLOW_JIT_OPT) | ||
| && !debuggerInfoBits.HasFlag(DebuggerAssemblyControlFlags.DACF_USER_OVERRIDE)); | ||
| bool profilerDisabledOptimizations = _target.Contracts.Loader.GetFlags(moduleHandle).HasFlag(ModuleFlags.ProfilerDisableOpt); | ||
| bool areJITOptimizationsDisabled = !corDebuggerAllowJITOpts || profilerDisabledOptimizations; | ||
|
|
||
| return eeConfig.JitMinOpts || eeConfig.GenDebuggable || areJITOptimizationsDisabled; | ||
| } | ||
|
|
||
| bool IRuntimeTypeSystem.IsJitOptimizationDisabled(MethodDescHandle methodDescHandle) | ||
|
Comment on lines
+1699
to
+1710
|
||
| { | ||
| return IsJitOptimizationDisabledForAllMethodsInChunk(methodDescHandle) || IsJitOptimizationDisabledForSpecificMethod(methodDescHandle); | ||
| } | ||
|
|
||
| NativeCodeVersionOptimizationTier IRuntimeTypeSystem.GetInitialOptimizationTier(MethodDescHandle methodDescHandle) | ||
| { | ||
| MethodDesc methodDesc = _methodDescs[methodDescHandle.Address]; | ||
| if (!methodDesc.IsEligibleForTieredCompilation) | ||
| { | ||
| return NativeCodeVersionOptimizationTier.OptimizationTierOptimized; | ||
| } | ||
|
|
||
| TargetPointer eeConfigPtr = _target.ReadPointer(_target.ReadGlobalPointer(Constants.Globals.EEConfig)); | ||
| Data.EEConfig eeConfig = _target.ProcessedData.GetOrAdd<Data.EEConfig>(eeConfigPtr); | ||
| return (NativeCodeVersionOptimizationTier)eeConfig.TieredCompilation_DefaultTier; | ||
| } | ||
|
|
||
| private sealed class NonValidatedMethodTableQueries : MethodValidation.IMethodTableQueries | ||
| { | ||
| private readonly RuntimeTypeSystem_1 _rts; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| // Licensed to the .NET Foundation under one or more agreements. | ||
| // The .NET Foundation licenses this file to you under the MIT license. | ||
|
|
||
| namespace Microsoft.Diagnostics.DataContractReader.Data; | ||
|
|
||
| internal sealed class EEConfig : IData<EEConfig> | ||
| { | ||
| static EEConfig IData<EEConfig>.Create(Target target, TargetPointer address) | ||
| => new EEConfig(target, address); | ||
|
|
||
| public EEConfig(Target target, TargetPointer address) | ||
| { | ||
| Target.TypeInfo type = target.GetTypeInfo(DataType.EEConfig); | ||
|
|
||
| JitMinOpts = target.Read<byte>(address + (ulong)type.Fields[nameof(JitMinOpts)].Offset) != 0; | ||
| GenDebuggable = target.Read<byte>(address + (ulong)type.Fields[nameof(GenDebuggable)].Offset) != 0; | ||
| TieredCompilation_DefaultTier = target.Read<uint>(address + (ulong)type.Fields[nameof(TieredCompilation_DefaultTier)].Offset); | ||
| } | ||
|
|
||
| public bool JitMinOpts { get; init; } | ||
| public bool GenDebuggable { get; init; } | ||
| public uint TieredCompilation_DefaultTier { get; init; } | ||
| } |
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here with the enum. Since these are not included in the data descriptor we have to ensure that anyone who decides to change these also changes the cDAC contract