Skip to content

Commit

Permalink
Integrate selected changes from nativeaot branch (#53185)
Browse files Browse the repository at this point in the history
- More code sharing for System.Exception
- Some support for default interface methods
- Move callling convention helpers around to avoid duplication
- Unify Environment.StackTrace
  • Loading branch information
jkotas committed May 25, 2021
1 parent 2df3923 commit 517421c
Show file tree
Hide file tree
Showing 17 changed files with 296 additions and 178 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

/// <summary>Gets the number of milliseconds elapsed since the system started.</summary>
/// <value>A 32-bit signed integer containing the amount of time in milliseconds that has passed since the last time the computer was started.</value>
public static extern int TickCount
Expand Down
46 changes: 2 additions & 44 deletions src/coreclr/System.Private.CoreLib/src/System/Exception.CoreCLR.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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
Expand Down
59 changes: 59 additions & 0 deletions src/coreclr/tools/Common/Compiler/TypeExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,42 @@ public static bool IsGenericDepthGreaterThan(this TypeDesc type, int depth)
return false;
}

/// <summary>
/// What is the maximum number of steps that need to be taken from this type to its most contained generic type.
/// i.e.
/// SomeGenericType&lt;System.Int32&gt;.Method&lt;System.Int32&gt; => 1
/// SomeType.Method&lt;System.Int32&gt; => 0
/// SomeType.Method&lt;List&lt;System.Int32&gt;&gt; => 1
/// </summary>
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;
}

/// <summary>
/// Determine if a type has a generic depth greater than a given value
/// </summary>
/// <param name="depth"></param>
/// <returns></returns>
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;
}

/// <summary>
/// Determines whether an array type does implements the generic collection interfaces. This is the case
/// for multi-dimensional arrays, and arrays of pointers.
Expand Down Expand Up @@ -508,5 +544,28 @@ public static bool IsNonVersionable(this MetadataType type)
{
return type.HasCustomAttribute("System.Runtime.Versioning", "NonVersionableAttribute");
}

/// <summary>
/// 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.
/// </summary>
/// <param name="method">Method to check</param>
/// <returns>True when the method is marked as non-versionable, false otherwise.</returns>
public static bool IsNonVersionable(this MethodDesc method)
{
return method.HasCustomAttribute("System.Runtime.Versioning", "NonVersionableAttribute");
}

/// <summary>
/// Returns true if <paramref name="method"/> 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.
/// </summary>
public static bool IsRawPInvoke(this MethodDesc method)
{
return method.IsPInvoke && (method is Internal.IL.Stubs.PInvokeTargetNativeMethod);
}
}
}
42 changes: 0 additions & 42 deletions src/coreclr/tools/Common/JitInterface/CallConvHelper.cs

This file was deleted.

13 changes: 8 additions & 5 deletions src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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")
{
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -3484,7 +3484,7 @@ private PgoSchemaElem[] getPgoInstrumentationResults(MethodDesc method)
return _compilation.ProfileData[method]?.SchemaData;
}

public static void ComputeJitPgoInstrumentationSchema(Func<object, IntPtr> objectToHandle, PgoSchemaElem[] pgoResultsSchemas, out PgoInstrumentationSchema[] nativeSchemas, out byte[] instrumentationData)
public static void ComputeJitPgoInstrumentationSchema(Func<object, IntPtr> objectToHandle, PgoSchemaElem[] pgoResultsSchemas, out PgoInstrumentationSchema[] nativeSchemas, out byte[] instrumentationData, Func<TypeDesc, bool> typeFilter = null)
{
nativeSchemas = new PgoInstrumentationSchema[pgoResultsSchemas.Length];
MemoryStream msInstrumentationData = new MemoryStream();
Expand Down Expand Up @@ -3524,9 +3524,12 @@ public static void ComputeJitPgoInstrumentationSchema(Func<object, IntPtr> objec
{
foreach (TypeSystemEntityOrUnknown typeVal in typeArray)
{
IntPtr ptrVal = IntPtr.Zero;
if (typeVal.AsType != null)
IntPtr ptrVal;

if (typeVal.AsType != null && (typeFilter == null || typeFilter(typeVal.AsType)))
{
ptrVal = (IntPtr)objectToHandle(typeVal.AsType);
}
else
{
// The "Unknown types are the values from 1-33
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -586,6 +586,9 @@ public override MethodDesc ResolveVariantInterfaceMethodToVirtualMethodOnType(Me
// See current interface call resolution for details on how that happens.
private static MethodDesc ResolveInterfaceMethodToVirtualMethodOnType(MethodDesc interfaceMethod, MetadataType currentType)
{
if (currentType.IsInterface)
return null;

MethodDesc methodImpl = FindImplFromDeclFromMethodImpls(currentType, interfaceMethod);
if (methodImpl != null)
return methodImpl;
Expand Down Expand Up @@ -723,6 +726,77 @@ private static MethodDesc FindNameSigOverrideForInterfaceMethodRecursive(MethodD
}
}

public override DefaultInterfaceMethodResolution ResolveInterfaceMethodToDefaultImplementationOnType(MethodDesc interfaceMethod, TypeDesc currentType, out MethodDesc impl)
{
return ResolveInterfaceMethodToDefaultImplementationOnType(interfaceMethod, (MetadataType)currentType, out impl);
}

private static DefaultInterfaceMethodResolution ResolveInterfaceMethodToDefaultImplementationOnType(MethodDesc interfaceMethod, MetadataType currentType, out MethodDesc impl)
{
TypeDesc interfaceMethodOwningType = interfaceMethod.OwningType;
MetadataType mostSpecificInterface = null;
bool diamondCase = false;
impl = null;

foreach (MetadataType runtimeInterface in currentType.RuntimeInterfaces)
{
if (runtimeInterface == interfaceMethodOwningType)
{
// Also consider the default interface method implementation on the interface itself
// if we don't have anything else yet
if (mostSpecificInterface == null && !interfaceMethod.IsAbstract)
{
mostSpecificInterface = runtimeInterface;
impl = interfaceMethod;
}
}
else if (Array.IndexOf(runtimeInterface.RuntimeInterfaces, interfaceMethodOwningType) != -1)
{
// This interface might provide a default implementation
MethodImplRecord[] possibleImpls = runtimeInterface.FindMethodsImplWithMatchingDeclName(interfaceMethod.Name);
if (possibleImpls != null)
{
foreach (MethodImplRecord implRecord in possibleImpls)
{
if (implRecord.Decl == interfaceMethod)
{
// This interface provides a default implementation.
// Is it also most specific?
if (mostSpecificInterface == null || Array.IndexOf(runtimeInterface.RuntimeInterfaces, mostSpecificInterface) != -1)
{
mostSpecificInterface = runtimeInterface;
impl = implRecord.Body;
diamondCase = false;
}
else if (Array.IndexOf(mostSpecificInterface.RuntimeInterfaces, runtimeInterface) == -1)
{
diamondCase = true;
}

break;
}
}
}
}
}

if (diamondCase)
{
impl = null;
return DefaultInterfaceMethodResolution.Diamond;
}
else if (impl == null)
{
return DefaultInterfaceMethodResolution.None;
}
else if (impl.IsAbstract)
{
return DefaultInterfaceMethodResolution.Reabstraction;
}

return DefaultInterfaceMethodResolution.DefaultImplementation;
}

public override IEnumerable<MethodDesc> ComputeAllVirtualSlots(TypeDesc type)
{
return EnumAllVirtualSlots((MetadataType)type);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,11 @@ public static MethodDesc ResolveVariantInterfaceMethodToVirtualMethodOnType(this
return type.Context.GetVirtualMethodAlgorithmForType(type).ResolveVariantInterfaceMethodToVirtualMethodOnType(interfaceMethod, type);
}

public static DefaultInterfaceMethodResolution ResolveInterfaceMethodToDefaultImplementationOnType(this TypeDesc type, MethodDesc interfaceMethod, out MethodDesc implMethod)
{
return type.Context.GetVirtualMethodAlgorithmForType(type).ResolveInterfaceMethodToDefaultImplementationOnType(interfaceMethod, type, out implMethod);
}

/// <summary>
/// Resolves a virtual method call.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ public abstract class VirtualMethodAlgorithm

public abstract MethodDesc ResolveVariantInterfaceMethodToVirtualMethodOnType(MethodDesc interfaceMethod, TypeDesc currentType);

public abstract DefaultInterfaceMethodResolution ResolveInterfaceMethodToDefaultImplementationOnType(MethodDesc interfaceMethod, TypeDesc currentType, out MethodDesc impl);

/// <summary>
/// Resolves a virtual method call.
/// </summary>
Expand All @@ -34,4 +36,27 @@ public abstract class VirtualMethodAlgorithm
/// </summary>
public abstract IEnumerable<MethodDesc> ComputeAllVirtualSlots(TypeDesc type);
}

public enum DefaultInterfaceMethodResolution
{
/// <summary>
/// No default implementation was found.
/// </summary>
None,

/// <summary>
/// A default implementation was found.
/// </summary>
DefaultImplementation,

/// <summary>
/// The implementation was reabstracted.
/// </summary>
Reabstraction,

/// <summary>
/// The default implementation conflicts.
/// </summary>
Diamond,
}
}
Loading

0 comments on commit 517421c

Please sign in to comment.