diff options
author | Jan Kotas <jkotas@microsoft.com> | 2018-08-25 06:58:06 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-08-25 06:58:06 +0300 |
commit | f0bcd9c2dca8b4fc2cb7de9b6ae80dbf8d584229 (patch) | |
tree | 0e0e7b91e78ae1a98d3fe967dd89266ccd0e99fc | |
parent | c8bbf0e8d2a5bac2663c98570b28e27da092d894 (diff) | |
parent | cbb7caca89d9951c0b9f7db79e5a3395058e03e0 (diff) |
Merge pull request #6259 from dotnet/nmirror
Merge nmirror to master
9 files changed, 84 insertions, 19 deletions
diff --git a/src/Common/src/TypeSystem/IL/ILProvider.cs b/src/Common/src/TypeSystem/IL/ILProvider.cs index 05a615154..31d8147c2 100644 --- a/src/Common/src/TypeSystem/IL/ILProvider.cs +++ b/src/Common/src/TypeSystem/IL/ILProvider.cs @@ -225,6 +225,10 @@ namespace Internal.IL { methodToCall = helperType.GetKnownMethod("StructOnlyEqualsIEquatable", null).MakeInstantiatedMethod(elementType); } + else + { + methodToCall = helperType.GetKnownMethod("StructOnlyNormalEquals", null).MakeInstantiatedMethod(elementType); + } if (methodToCall != null) { diff --git a/src/ILCompiler.Compiler/src/Compiler/CompilerTypeSystemContext.cs b/src/ILCompiler.Compiler/src/Compiler/CompilerTypeSystemContext.cs index 9b822d89b..e522e2144 100644 --- a/src/ILCompiler.Compiler/src/Compiler/CompilerTypeSystemContext.cs +++ b/src/ILCompiler.Compiler/src/Compiler/CompilerTypeSystemContext.cs @@ -499,6 +499,10 @@ namespace ILCompiler // method table. public long UniversalCanonReflectionMethodRootHeuristic_InstantiationCount { get; } + // To avoid infinite generic recursion issues during debug type record generation, attempt to + // use canonical form for types with high generic complexity. + public long MaxGenericDepthOfDebugRecord { get; } + public SharedGenericsConfiguration() { UniversalCanonGVMReflectionRootHeuristic_InstantiationCount = 4; @@ -510,6 +514,8 @@ namespace ILCompiler // expansion is allowed. Numbers are chosen to allow a fairly large // amount of generic expansion before trimming. UniversalCanonReflectionMethodRootHeuristic_InstantiationCount = 1024; + + MaxGenericDepthOfDebugRecord = 15; } }; } diff --git a/src/ILCompiler.Compiler/src/Compiler/UserDefinedTypeDescriptor.cs b/src/ILCompiler.Compiler/src/Compiler/UserDefinedTypeDescriptor.cs index 35142c6da..7427c4981 100644 --- a/src/ILCompiler.Compiler/src/Compiler/UserDefinedTypeDescriptor.cs +++ b/src/ILCompiler.Compiler/src/Compiler/UserDefinedTypeDescriptor.cs @@ -387,27 +387,57 @@ namespace ILCompiler return 0; } - TypeDesc GetFieldDebugType(FieldDesc field) + bool ShouldUseCanonicalTypeRecord(TypeDesc type) { - TypeDesc type = field.FieldType; - // TODO: check the type's generic complexity - if (NodeFactory.LazyGenericsPolicy.UsesLazyGenerics(type)) + return type.GetGenericDepth() > NodeFactory.TypeSystemContext.GenericsConfig.MaxGenericDepthOfDebugRecord; + } + + TypeDesc GetDebugType(TypeDesc type) + { + TypeDesc typeGenericComplexityInfo = type; + + // Strip off pointer, array, and byref details. + while (typeGenericComplexityInfo is ParameterizedType paramType) { + typeGenericComplexityInfo = paramType.ParameterType; + } + + // Types that have some canonical subtypes types should always be represented in normalized canonical form to the binder. + // Also, to avoid infinite generic recursion issues, attempt to use canonical form for fields with high generic complexity. + if (type.IsCanonicalSubtype(CanonicalFormKind.Specific) || (typeGenericComplexityInfo is DefType defType) && ShouldUseCanonicalTypeRecord(defType)) { type = type.ConvertToCanonForm(CanonicalFormKind.Specific); + + // Re-check if the canonical subtype has acceptable generic complexity + typeGenericComplexityInfo = type; + + while (typeGenericComplexityInfo is ParameterizedType paramType) { + typeGenericComplexityInfo = paramType.ParameterType; + } + + if ((typeGenericComplexityInfo is DefType canonDefType) && ShouldUseCanonicalTypeRecord(canonDefType)) + { + type = type.ConvertToCanonForm(CanonicalFormKind.Universal); + } } return type; } + TypeDesc GetFieldDebugType(FieldDesc field) + { + return GetDebugType(field.FieldType); + } + private uint GetClassTypeIndex(TypeDesc type, bool needsCompleteType) { - DefType defType = type as DefType; + TypeDesc debugType = GetDebugType(type); + DefType defType = debugType as DefType; System.Diagnostics.Debug.Assert(defType != null, "GetClassTypeIndex was called with non def type"); ClassTypeDescriptor classTypeDescriptor = new ClassTypeDescriptor { IsStruct = type.IsValueType ? 1 : 0, - Name = _objectWriter.GetMangledName(type), + Name = _objectWriter.GetMangledName(defType), BaseClassId = 0, InstanceSize = 0 }; diff --git a/src/Native/Runtime/RHCodeMan.cpp b/src/Native/Runtime/RHCodeMan.cpp index 8fbaea299..054287fc4 100644 --- a/src/Native/Runtime/RHCodeMan.cpp +++ b/src/Native/Runtime/RHCodeMan.cpp @@ -1327,7 +1327,6 @@ bool EECodeManager::GetEpilogOffset( // ARM64 epilogs have a window between loading the hijackable return address into LR and the RET instruction. // We cannot hijack or unhijack a thread while it is suspended in that window unless we implement hijacking // via LR register modification. -#ifndef _ARM64_ void ** EECodeManager::GetReturnAddressLocationFromEpilog(GCInfoHeader * pInfoHeader, REGDISPLAY * pContext, UInt32 epilogOffset, UInt32 epilogSize) { @@ -1740,7 +1739,6 @@ void ** EECodeManager::GetReturnAddressLocationFromEpilog(GCInfoHeader * pInfoHe #endif } -#endif // _ARM64_ #ifdef _DEBUG diff --git a/src/System.Private.CoreLib/src/Internal/IntrinsicSupport/EqualityComparerHelpers.cs b/src/System.Private.CoreLib/src/Internal/IntrinsicSupport/EqualityComparerHelpers.cs index 2b230eed8..b9c735ca1 100644 --- a/src/System.Private.CoreLib/src/Internal/IntrinsicSupport/EqualityComparerHelpers.cs +++ b/src/System.Private.CoreLib/src/Internal/IntrinsicSupport/EqualityComparerHelpers.cs @@ -195,10 +195,15 @@ namespace Internal.IntrinsicSupport #endif } + private static bool StructOnlyNormalEquals<T>(T left, T right) + { + return left.Equals(right); + } + [Intrinsic] internal static bool StructOnlyEquals<T>(T left, T right) { - return left.Equals(right); + return EqualityComparer<T>.Default.Equals(left, right); } } } diff --git a/src/System.Private.CoreLib/src/System/Diagnostics/StackFrame.CoreRT.cs b/src/System.Private.CoreLib/src/System/Diagnostics/StackFrame.CoreRT.cs index cc8ac5a3d..31a0da58d 100644 --- a/src/System.Private.CoreLib/src/System/Diagnostics/StackFrame.CoreRT.cs +++ b/src/System.Private.CoreLib/src/System/Diagnostics/StackFrame.CoreRT.cs @@ -129,15 +129,15 @@ namespace System.Diagnostics /// </summary> internal void AppendToStackTrace(StringBuilder builder) { - if (_ipAddress == StackTraceHelper.SpecialIP.EdiSeparator) - { - builder.AppendLine(SR.StackTrace_EndStackTraceFromPreviousThrow); - } - else + if (_ipAddress != StackTraceHelper.SpecialIP.EdiSeparator) { builder.Append(SR.StackTrace_AtWord); builder.AppendLine(DeveloperExperience.Default.CreateStackTraceString(_ipAddress, _needFileInfo)); } + if (GetIsLastFrameFromForeignExceptionStackTrace()) + { + builder.AppendLine(SR.StackTrace_EndStackTraceFromPreviousThrow); + } } } } diff --git a/src/System.Private.CoreLib/src/System/Diagnostics/StackTrace.cs b/src/System.Private.CoreLib/src/System/Diagnostics/StackTrace.cs index 5b7c10ca3..2aed3264a 100644 --- a/src/System.Private.CoreLib/src/System/Diagnostics/StackTrace.cs +++ b/src/System.Private.CoreLib/src/System/Diagnostics/StackTrace.cs @@ -148,14 +148,35 @@ namespace System.Diagnostics private void InitializeForIpAddressArray(IntPtr[] ipAddresses, int skipFrames, int endFrameIndex, bool needFileInfo) { int frameCount = (skipFrames < endFrameIndex ? endFrameIndex - skipFrames : 0); - if (frameCount > 0) + + // Calculate true frame count upfront - we need to skip EdiSeparators which get + // collapsed onto boolean flags on the preceding stack frame + int outputFrameCount = 0; + for (int frameIndex = 0; frameIndex < frameCount; frameIndex++) + { + if (ipAddresses[frameIndex + skipFrames] != StackTraceHelper.SpecialIP.EdiSeparator) + { + outputFrameCount++; + } + } + + if (outputFrameCount > 0) { - _stackFrames = new StackFrame[frameCount]; + _stackFrames = new StackFrame[outputFrameCount]; + int outputFrameIndex = 0; for (int frameIndex = 0; frameIndex < frameCount; frameIndex++) { IntPtr ipAddress = ipAddresses[frameIndex + skipFrames]; - _stackFrames[frameIndex] = new StackFrame(ipAddress, needFileInfo); + if (ipAddress != StackTraceHelper.SpecialIP.EdiSeparator) + { + _stackFrames[outputFrameIndex++] = new StackFrame(ipAddress, needFileInfo); + } + else if (outputFrameIndex > 0) + { + _stackFrames[outputFrameIndex - 1].SetIsLastFrameFromForeignExceptionStackTrace(true); + } } + Debug.Assert(outputFrameIndex == outputFrameCount); } } diff --git a/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.LdTokenResultLookup.cs b/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.LdTokenResultLookup.cs index b8682b894..3c6ecf107 100644 --- a/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.LdTokenResultLookup.cs +++ b/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.LdTokenResultLookup.cs @@ -363,7 +363,7 @@ namespace Internal.Runtime.TypeLoader DynamicMethodHandleInfo* methodData = (DynamicMethodHandleInfo*)runtimeMethodHandleValue.ToPointer(); declaringTypeHandle = *(RuntimeTypeHandle*)&(methodData->DeclaringType); - genericMethodArgs = Array.Empty<RuntimeTypeHandle>(); + genericMethodArgs = null; if (methodData->NumGenericArgs > 0) { diff --git a/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeSystemExtensions.cs b/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeSystemExtensions.cs index cbdbd68fd..0154a424c 100644 --- a/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeSystemExtensions.cs +++ b/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeSystemExtensions.cs @@ -145,8 +145,9 @@ namespace Internal.Runtime.TypeLoader methodOnInstantiatedType = typeSystemContext.GetMethodForInstantiatedType(typicalMethod, (InstantiatedType)declaringType); MethodDesc instantiatedMethod = methodOnInstantiatedType; - if (genericMethodArgs.Length != 0) + if (genericMethodArgs != null) { + Debug.Assert(genericMethodArgs.Length > 0); Instantiation genericMethodInstantiation = typeSystemContext.ResolveRuntimeTypeHandles(genericMethodArgs); typeSystemContext.GetInstantiatedMethod(methodOnInstantiatedType, genericMethodInstantiation); } |