diff --git a/src/coreclr/System.Private.CoreLib/src/System/Environment.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Environment.CoreCLR.cs
index b375cfddc7ba5..56ac1ec84dfa8 100644
--- a/src/coreclr/System.Private.CoreLib/src/System/Environment.CoreCLR.cs
+++ b/src/coreclr/System.Private.CoreLib/src/System/Environment.CoreCLR.cs
@@ -90,12 +90,6 @@ public static string[] GetCommandLineArgs()
// Used by VM
internal static string? GetResourceStringLocal(string key) => SR.GetResourceString(key);
- public static string StackTrace
- {
- [MethodImpl(MethodImplOptions.NoInlining)] // Prevent inlining from affecting where the stacktrace starts
- get => new StackTrace(true).ToString(System.Diagnostics.StackTrace.TraceFormat.Normal);
- }
-
/// Gets the number of milliseconds elapsed since the system started.
/// A 32-bit signed integer containing the amount of time in milliseconds that has passed since the last time the computer was started.
public static extern int TickCount
diff --git a/src/coreclr/System.Private.CoreLib/src/System/Exception.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Exception.CoreCLR.cs
index 2be63740dc34c..8a0c9402cb54c 100644
--- a/src/coreclr/System.Private.CoreLib/src/System/Exception.CoreCLR.cs
+++ b/src/coreclr/System.Private.CoreLib/src/System/Exception.CoreCLR.cs
@@ -85,35 +85,6 @@ public MethodBase? TargetSite
}
}
- // Returns the stack trace as a string. If no stack trace is
- // available, null is returned.
- public virtual string? StackTrace
- {
- get
- {
- string? stackTraceString = _stackTraceString;
- string? remoteStackTraceString = _remoteStackTraceString;
-
- // if no stack trace, try to get one
- if (stackTraceString != null)
- {
- return remoteStackTraceString + stackTraceString;
- }
- if (_stackTrace == null)
- {
- return remoteStackTraceString;
- }
-
- return remoteStackTraceString + GetStackTrace();
- }
- }
-
- private string GetStackTrace()
- {
- // Do not include a trailing newline for backwards compatibility
- return new StackTrace(this, fNeedFileInfo: true).ToString(System.Diagnostics.StackTrace.TraceFormat.Normal);
- }
-
private string? CreateSourceName()
{
StackTrace st = new StackTrace(this, fNeedFileInfo: false);
@@ -243,22 +214,9 @@ internal void RestoreDispatchState(in DispatchState dispatchState)
// See src\inc\corexcep.h's EXCEPTION_COMPLUS definition:
private const int _COMPlusExceptionCode = unchecked((int)0xe0434352); // Win32 exception code for COM+ exceptions
- private object? SerializationWatsonBuckets => _watsonBuckets;
-
- private string? SerializationStackTraceString
- {
- get
- {
- string? stackTraceString = _stackTraceString;
+ private bool HasBeenThrown => _stackTrace != null;
- if (stackTraceString == null && _stackTrace != null)
- {
- stackTraceString = GetStackTrace();
- }
-
- return stackTraceString;
- }
- }
+ private object? SerializationWatsonBuckets => _watsonBuckets;
// This piece of infrastructure exists to help avoid deadlocks
// between parts of CoreLib that might throw an exception while
diff --git a/src/coreclr/tools/Common/Compiler/TypeExtensions.cs b/src/coreclr/tools/Common/Compiler/TypeExtensions.cs
index c9418961afd9b..428ca4b1d1397 100644
--- a/src/coreclr/tools/Common/Compiler/TypeExtensions.cs
+++ b/src/coreclr/tools/Common/Compiler/TypeExtensions.cs
@@ -199,6 +199,42 @@ public static bool IsGenericDepthGreaterThan(this TypeDesc type, int depth)
return false;
}
+ ///
+ /// What is the maximum number of steps that need to be taken from this type to its most contained generic type.
+ /// i.e.
+ /// SomeGenericType<System.Int32>.Method<System.Int32> => 1
+ /// SomeType.Method<System.Int32> => 0
+ /// SomeType.Method<List<System.Int32>> => 1
+ ///
+ public static int GetGenericDepth(this MethodDesc method)
+ {
+ int genericDepth = method.OwningType.GetGenericDepth();
+ foreach (TypeDesc type in method.Instantiation)
+ {
+ genericDepth = Math.Max(genericDepth, type.GetGenericDepth());
+ }
+ return genericDepth;
+ }
+
+ ///
+ /// Determine if a type has a generic depth greater than a given value
+ ///
+ ///
+ ///
+ public static bool IsGenericDepthGreaterThan(this MethodDesc method, int depth)
+ {
+ if (method.OwningType.IsGenericDepthGreaterThan(depth))
+ return true;
+
+ foreach (TypeDesc type in method.Instantiation)
+ {
+ if (type.IsGenericDepthGreaterThan(depth))
+ return true;
+ }
+
+ return false;
+ }
+
///
/// Determines whether an array type does implements the generic collection interfaces. This is the case
/// for multi-dimensional arrays, and arrays of pointers.
@@ -508,5 +544,28 @@ public static bool IsNonVersionable(this MetadataType type)
{
return type.HasCustomAttribute("System.Runtime.Versioning", "NonVersionableAttribute");
}
+
+ ///
+ /// Return true when the method is marked as non-versionable. Non-versionable methods
+ /// may be freely inlined into ReadyToRun images even when they don't reside in the
+ /// same version bubble as the module being compiled.
+ ///
+ /// Method to check
+ /// True when the method is marked as non-versionable, false otherwise.
+ public static bool IsNonVersionable(this MethodDesc method)
+ {
+ return method.HasCustomAttribute("System.Runtime.Versioning", "NonVersionableAttribute");
+ }
+
+ ///
+ /// Returns true if is an actual native entrypoint.
+ /// There's a distinction between when a method reports it's a PInvoke in the metadata
+ /// versus how it's treated in the compiler. For many PInvoke methods the compiler will generate
+ /// an IL body. The methods with an IL method body shouldn't be treated as PInvoke within the compiler.
+ ///
+ public static bool IsRawPInvoke(this MethodDesc method)
+ {
+ return method.IsPInvoke && (method is Internal.IL.Stubs.PInvokeTargetNativeMethod);
+ }
}
}
diff --git a/src/coreclr/tools/Common/JitInterface/CallConvHelper.cs b/src/coreclr/tools/Common/JitInterface/CallConvHelper.cs
deleted file mode 100644
index ad92b5b36e34c..0000000000000
--- a/src/coreclr/tools/Common/JitInterface/CallConvHelper.cs
+++ /dev/null
@@ -1,42 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using System;
-using System.Collections.Generic;
-using System.Collections.Immutable;
-using System.Reflection.Metadata;
-
-using Internal.TypeSystem;
-
-namespace Internal.JitInterface
-{
- internal static unsafe class CallConvHelper
- {
- internal static IEnumerable EnumerateCallConvsFromAttribute(CustomAttributeValue attributeWithCallConvsArray)
- {
- ImmutableArray> callConvArray = default;
- foreach (var arg in attributeWithCallConvsArray.NamedArguments)
- {
- if (arg.Name == "CallConvs")
- {
- callConvArray = (ImmutableArray>)arg.Value;
- }
- }
-
- // No calling convention was specified in the attribute
- if (callConvArray.IsDefault)
- yield break;
-
- foreach (CustomAttributeTypedArgument type in callConvArray)
- {
- if (!(type.Value is DefType defType))
- continue;
-
- if (defType.Namespace != "System.Runtime.CompilerServices")
- continue;
-
- yield return defType;
- }
- }
- }
-}
diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs
index d0cd0f7bc069f..8ec87f59d4a11 100644
--- a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs
+++ b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs
@@ -646,7 +646,7 @@ private CorInfoCallConvExtension GetUnmanagedCallingConventionFromAttribute(Cust
bool found = false;
bool memberFunctionVariant = false;
- foreach (DefType defType in CallConvHelper.EnumerateCallConvsFromAttribute(attributeWithCallConvsArray))
+ foreach (DefType defType in attributeWithCallConvsArray.EnumerateCallConvsFromAttribute())
{
if (defType.Name == "CallConvMemberFunction")
{
@@ -1371,7 +1371,7 @@ private static object ResolveTokenInScope(MethodIL methodIL, object typeOrMethod
if (typeOrMethodContext is TypeDesc typeContext)
{
- Debug.Assert(typeContext.HasSameTypeDefinition(owningMethod.OwningType));
+ Debug.Assert(typeContext.HasSameTypeDefinition(owningMethod.OwningType) || typeContext.IsArray);
typeInst = typeContext.Instantiation;
}
else
@@ -3484,7 +3484,7 @@ private PgoSchemaElem[] getPgoInstrumentationResults(MethodDesc method)
return _compilation.ProfileData[method]?.SchemaData;
}
- public static void ComputeJitPgoInstrumentationSchema(Func
public abstract IEnumerable ComputeAllVirtualSlots(TypeDesc type);
}
+
+ public enum DefaultInterfaceMethodResolution
+ {
+ ///
+ /// No default implementation was found.
+ ///
+ None,
+
+ ///
+ /// A default implementation was found.
+ ///
+ DefaultImplementation,
+
+ ///
+ /// The implementation was reabstracted.
+ ///
+ Reabstraction,
+
+ ///
+ /// The default implementation conflicts.
+ ///
+ Diamond,
+ }
}
diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/MethodExtensions.cs b/src/coreclr/tools/Common/TypeSystem/Interop/CallConvHelpers.cs
similarity index 57%
rename from src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/MethodExtensions.cs
rename to src/coreclr/tools/Common/TypeSystem/Interop/CallConvHelpers.cs
index f9b363778a6b0..91a4d0c8da778 100644
--- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/MethodExtensions.cs
+++ b/src/coreclr/tools/Common/TypeSystem/Interop/CallConvHelpers.cs
@@ -1,26 +1,18 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
-using Internal.TypeSystem;
-using Internal.TypeSystem.Ecma;
+using System;
+using System.Diagnostics;
+using System.Collections.Generic;
+using System.Collections.Immutable;
+using System.Reflection.Metadata;
-using Debug = System.Diagnostics.Debug;
+using Internal.TypeSystem.Ecma;
-namespace ILCompiler
+namespace Internal.TypeSystem
{
- static class MethodExtensions
+ internal static unsafe class CallConvHelpers
{
- ///
- /// Returns true if is an actual native entrypoint.
- /// There's a distinction between when a method reports it's a PInvoke in the metadata
- /// versus how it's treated in the compiler. For many PInvoke methods the compiler will generate
- /// an IL body. The methods with an IL method body shouldn't be treated as PInvoke within the compiler.
- ///
- public static bool IsRawPInvoke(this MethodDesc method)
- {
- return method.IsPInvoke && (method is Internal.IL.Stubs.PInvokeTargetNativeMethod);
- }
-
///
/// Gets a value indicating whether the method has the SuppressGCTransition attribute
///
@@ -58,7 +50,7 @@ public static bool IsSuppressGCTransition(this MethodDesc method)
if (unmanagedCallConvAttribute == null)
return false;
- foreach (DefType defType in Internal.JitInterface.CallConvHelper.EnumerateCallConvsFromAttribute(unmanagedCallConvAttribute.Value))
+ foreach (DefType defType in unmanagedCallConvAttribute.Value.EnumerateCallConvsFromAttribute())
{
if (defType.Name == "CallConvSuppressGCTransition")
{
@@ -69,16 +61,31 @@ public static bool IsSuppressGCTransition(this MethodDesc method)
return false;
}
- ///
- /// Return true when the method is marked as non-versionable. Non-versionable methods
- /// may be freely inlined into ReadyToRun images even when they don't reside in the
- /// same version bubble as the module being compiled.
- ///
- /// Method to check
- /// True when the method is marked as non-versionable, false otherwise.
- public static bool IsNonVersionable(this MethodDesc method)
+ public static IEnumerable EnumerateCallConvsFromAttribute(this CustomAttributeValue attributeWithCallConvsArray)
{
- return method.HasCustomAttribute("System.Runtime.Versioning", "NonVersionableAttribute");
+ ImmutableArray> callConvArray = default;
+ foreach (var arg in attributeWithCallConvsArray.NamedArguments)
+ {
+ if (arg.Name == "CallConvs")
+ {
+ callConvArray = (ImmutableArray>)arg.Value;
+ }
+ }
+
+ // No calling convention was specified in the attribute
+ if (callConvArray.IsDefault)
+ yield break;
+
+ foreach (CustomAttributeTypedArgument type in callConvArray)
+ {
+ if (!(type.Value is DefType defType))
+ continue;
+
+ if (defType.Namespace != "System.Runtime.CompilerServices")
+ continue;
+
+ yield return defType;
+ }
}
}
}
diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj
index 6299418227bde..bedb1ce62e3a8 100644
--- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj
+++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj
@@ -1,4 +1,4 @@
-
+LibraryILCompiler.ReadyToRun
@@ -186,7 +186,6 @@
-
@@ -245,12 +244,12 @@
IL\HelperExtensions.cs
+
+ Interop\CallConvHelpers.cs
+
JitInterface\TypeString.cs
-
- JitInterface\CallConvHelper.cs
-
JitInterface\CorInfoBase.cs
diff --git a/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs b/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs
index ecf16031fe9db..c30fbb254733a 100644
--- a/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs
+++ b/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs
@@ -245,7 +245,7 @@ private static Version GetICUVersion()
int version = 0;
try
{
- Type interopGlobalization = Type.GetType("Interop+Globalization");
+ Type interopGlobalization = Type.GetType("Interop+Globalization, System.Private.CoreLib");
if (interopGlobalization != null)
{
MethodInfo methodInfo = interopGlobalization.GetMethod("GetICUVersion", BindingFlags.NonPublic | BindingFlags.Static);
diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventSource.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventSource.cs
index 0492071dba4a3..3db188d5a80b6 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventSource.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventSource.cs
@@ -3657,6 +3657,7 @@ private static void DebugCheckEvent(ref Dictionary? eventsByName
#endif
private static int GetHelperCallFirstArg(MethodInfo method)
{
+#if !CORERT
// Currently searches for the following pattern
//
// ... // CAN ONLY BE THE INSTRUCTIONS BELOW
@@ -3773,6 +3774,7 @@ private static int GetHelperCallFirstArg(MethodInfo method)
}
idx++;
}
+#endif
return -1;
}
diff --git a/src/libraries/System.Private.CoreLib/src/System/Environment.cs b/src/libraries/System.Private.CoreLib/src/System/Environment.cs
index 15e19465cae31..6c6c8ced629d0 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Environment.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Environment.cs
@@ -4,6 +4,7 @@
using System.Collections;
using System.Diagnostics;
using System.Reflection;
+using System.Runtime.CompilerServices;
using System.Threading;
namespace System
@@ -203,6 +204,12 @@ public static Version Version
}
}
+ public static string StackTrace
+ {
+ [MethodImpl(MethodImplOptions.NoInlining)] // Prevent inlining from affecting where the stacktrace starts
+ get => new StackTrace(true).ToString(System.Diagnostics.StackTrace.TraceFormat.Normal);
+ }
+
private static bool ValidateAndConvertRegistryTarget(EnvironmentVariableTarget target)
{
Debug.Assert(target != EnvironmentVariableTarget.Process);
diff --git a/src/libraries/System.Private.CoreLib/src/System/Exception.cs b/src/libraries/System.Private.CoreLib/src/System/Exception.cs
index 3db9eb77fd5e2..a6760916f9306 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Exception.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Exception.cs
@@ -201,6 +201,35 @@ public int HResult
partial void RestoreRemoteStackTrace(SerializationInfo info, StreamingContext context);
+ // Returns the stack trace as a string. If no stack trace is
+ // available, null is returned.
+ public virtual string? StackTrace
+ {
+ get
+ {
+ string? stackTraceString = _stackTraceString;
+ string? remoteStackTraceString = _remoteStackTraceString;
+
+ // if no stack trace, try to get one
+ if (stackTraceString != null)
+ {
+ return remoteStackTraceString + stackTraceString;
+ }
+ if (!HasBeenThrown)
+ {
+ return remoteStackTraceString;
+ }
+
+ return remoteStackTraceString + GetStackTrace();
+ }
+ }
+
+ private string GetStackTrace()
+ {
+ // Do not include a trailing newline for backwards compatibility
+ return new StackTrace(this, fNeedFileInfo: true).ToString(System.Diagnostics.StackTrace.TraceFormat.Normal);
+ }
+
[StackTraceHidden]
internal void SetCurrentStackTrace()
{
@@ -229,5 +258,20 @@ internal void SetRemoteStackTrace(string stackTrace)
// would have generated.
_remoteStackTraceString = stackTrace + Environment.NewLineConst + SR.Exception_EndStackTraceFromPreviousThrow + Environment.NewLineConst;
}
+
+ private string? SerializationStackTraceString
+ {
+ get
+ {
+ string? stackTraceString = _stackTraceString;
+
+ if (stackTraceString == null && HasBeenThrown)
+ {
+ stackTraceString = GetStackTrace();
+ }
+
+ return stackTraceString;
+ }
+ }
}
}
diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.cs
index 64269561d7e01..6b0838fc69118 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.cs
@@ -142,7 +142,16 @@ public static int SizeOf(Type t)
return SizeOfHelper(t, throwIfNotMarshalable: true);
}
- public static int SizeOf() => SizeOf(typeof(T));
+ public static int SizeOf()
+ {
+ Type t = typeof(T);
+ if (t.IsGenericType)
+ {
+ throw new ArgumentException(SR.Argument_NeedNonGenericType, nameof(T));
+ }
+
+ return SizeOfHelper(t, throwIfNotMarshalable: true);
+ }
public static unsafe int QueryInterface(IntPtr pUnk, ref Guid iid, out IntPtr ppv)
{
@@ -1153,7 +1162,26 @@ public static Delegate GetDelegateForFunctionPointer(IntPtr ptr, Type t)
public static TDelegate GetDelegateForFunctionPointer(IntPtr ptr)
{
- return (TDelegate)(object)GetDelegateForFunctionPointer(ptr, typeof(TDelegate));
+ if (ptr == IntPtr.Zero)
+ {
+ throw new ArgumentNullException(nameof(ptr));
+ }
+
+ Type t = typeof(TDelegate);
+ if (t.IsGenericType)
+ {
+ throw new ArgumentException(SR.Argument_NeedNonGenericType, nameof(TDelegate));
+ }
+
+ // For backward compatibility, we allow lookup of existing delegate to
+ // function pointer mappings using abstract MulticastDelegate type. We will check
+ // for the non-abstract delegate type later if no existing mapping is found.
+ if (t.BaseType != typeof(MulticastDelegate) && t != typeof(MulticastDelegate))
+ {
+ throw new ArgumentException(SR.Arg_MustBeDelegate, nameof(TDelegate));
+ }
+
+ return (TDelegate)(object)GetDelegateForFunctionPointerInternal(ptr, t);
}
public static IntPtr GetFunctionPointerForDelegate(Delegate d)
diff --git a/src/mono/System.Private.CoreLib/src/System/Environment.Mono.cs b/src/mono/System.Private.CoreLib/src/System/Environment.Mono.cs
index 69c6bf09ab2dd..43350fe683f2b 100644
--- a/src/mono/System.Private.CoreLib/src/System/Environment.Mono.cs
+++ b/src/mono/System.Private.CoreLib/src/System/Environment.Mono.cs
@@ -24,12 +24,6 @@ public static extern int ExitCode
[MethodImplAttribute(MethodImplOptions.InternalCall)]
private static extern int GetProcessorCount();
- public static string StackTrace
- {
- [MethodImpl(MethodImplOptions.NoInlining)] // Prevent inlining from affecting where the stacktrace starts
- get => new StackTrace(true).ToString(Diagnostics.StackTrace.TraceFormat.Normal);
- }
-
public static extern int TickCount
{
[MethodImplAttribute(MethodImplOptions.InternalCall)]
diff --git a/src/mono/System.Private.CoreLib/src/System/Exception.Mono.cs b/src/mono/System.Private.CoreLib/src/System/Exception.Mono.cs
index 8924a9bfd5b9a..a8fda176114d6 100644
--- a/src/mono/System.Private.CoreLib/src/System/Exception.Mono.cs
+++ b/src/mono/System.Private.CoreLib/src/System/Exception.Mono.cs
@@ -46,6 +46,8 @@ public DispatchState(MonoStackFrame[]? stackFrames)
private int caught_in_unmanaged;
#endregion
+ private bool HasBeenThrown => _traceIPs != null;
+
public MethodBase? TargetSite
{
get
@@ -58,32 +60,6 @@ public MethodBase? TargetSite
}
}
- public virtual string? StackTrace
- {
- get
- {
- string? stackTraceString = _stackTraceString;
- string? remoteStackTraceString = _remoteStackTraceString;
-
- if (stackTraceString != null)
- {
- return remoteStackTraceString + stackTraceString;
- }
- if (_traceIPs == null)
- {
- return remoteStackTraceString;
- }
-
- return remoteStackTraceString + GetStackTrace();
- }
- }
-
- private string GetStackTrace()
- {
- // Do not include a trailing newline for backwards compatibility
- return new StackTrace(this, fNeedFileInfo: true).ToString(System.Diagnostics.StackTrace.TraceFormat.Normal);
- }
-
internal DispatchState CaptureDispatchState()
{
MonoStackFrame[]? stackFrames;
@@ -160,20 +136,5 @@ private bool CanSetRemoteStackTrace()
private static IDictionary CreateDataContainer() => new ListDictionaryInternal();
private static string? SerializationWatsonBuckets => null;
-
- private string? SerializationStackTraceString
- {
- get
- {
- string? stackTraceString = _stackTraceString;
-
- if (stackTraceString == null && _traceIPs != null)
- {
- stackTraceString = GetStackTrace();
- }
-
- return stackTraceString;
- }
- }
}
}