From 0fcd7690a14335a8807144d0e7ad937aa83699b0 Mon Sep 17 00:00:00 2001 From: Jan Kotas Date: Thu, 3 Jun 2021 05:58:33 -0700 Subject: [PATCH] Integrate changes from NativeAOT branch (#53650) * Integrate changes from NativeAOT branch Includes faster virtual method enumerator that should help crossgen2 too * Fix tests --- .../tools/Common/TypeSystem/Common/ArrayType.cs | 5 ++ .../Common/TypeSystem/Common/ExceptionStringID.cs | 3 + .../Common/TypeSystem/Common/InstantiatedType.cs | 8 +++ .../Common/MetadataVirtualMethodAlgorithm.cs | 10 +--- .../TypeSystem/Common/Properties/Resources.resx | 3 + .../tools/Common/TypeSystem/Common/ThrowHelper.cs | 6 ++ .../tools/Common/TypeSystem/Common/TypeDesc.cs | 10 ++++ .../Common/TypeSystem/Common/TypeSystemContext.cs | 5 ++ .../TypeSystem/Common/TypeSystemException.cs | 8 +++ .../Common/TypeSystem/Common/TypeSystemHelpers.cs | 8 +++ .../Common/Utilities/DebugNameFormatter.cs | 10 +++- .../tools/Common/TypeSystem/Ecma/EcmaType.cs | 25 ++++++--- .../Ecma/SymbolReader/PortablePdbSymbolReader.cs | 17 +++++- .../Common/TypeSystem/Interop/IL/MarshalHelpers.cs | 26 +++++++-- .../Common/TypeSystem/Interop/IL/Marshaller.cs | 65 ++++++++++++++++------ .../TypeSystem/Interop/MarshalAsDescriptor.cs | 2 + .../RuntimeDetermined/RuntimeDeterminedType.cs | 8 +++ .../SyntheticVirtualOverrideTests.cs | 15 +++++ .../src/System/Diagnostics/StackFrame.cs | 13 ++++- .../src/System/Diagnostics/StackTrace.cs | 4 ++ .../Metadata/ReflectionMemberAccessor.cs | 14 ++++- 21 files changed, 224 insertions(+), 41 deletions(-) diff --git a/src/coreclr/tools/Common/TypeSystem/Common/ArrayType.cs b/src/coreclr/tools/Common/TypeSystem/Common/ArrayType.cs index c3e227e..c21ba93 100644 --- a/src/coreclr/tools/Common/TypeSystem/Common/ArrayType.cs +++ b/src/coreclr/tools/Common/TypeSystem/Common/ArrayType.cs @@ -119,6 +119,11 @@ namespace Internal.TypeSystem return _methods; } + public override IEnumerable GetVirtualMethods() + { + return MethodDesc.EmptyMethods; + } + public MethodDesc GetArrayMethod(ArrayMethodKind kind) { if (_methods == null) diff --git a/src/coreclr/tools/Common/TypeSystem/Common/ExceptionStringID.cs b/src/coreclr/tools/Common/TypeSystem/Common/ExceptionStringID.cs index dd38a71..ab093a3 100644 --- a/src/coreclr/tools/Common/TypeSystem/Common/ExceptionStringID.cs +++ b/src/coreclr/tools/Common/TypeSystem/Common/ExceptionStringID.cs @@ -41,5 +41,8 @@ namespace Internal.TypeSystem // BadImageFormatException BadImageFormatGeneric, BadImageFormatSpecific, + + // MarshalDirectiveException + MarshalDirectiveGeneric, } } diff --git a/src/coreclr/tools/Common/TypeSystem/Common/InstantiatedType.cs b/src/coreclr/tools/Common/TypeSystem/Common/InstantiatedType.cs index 8d9d18c..f1164b6 100644 --- a/src/coreclr/tools/Common/TypeSystem/Common/InstantiatedType.cs +++ b/src/coreclr/tools/Common/TypeSystem/Common/InstantiatedType.cs @@ -144,6 +144,14 @@ namespace Internal.TypeSystem } } + public override IEnumerable GetVirtualMethods() + { + foreach (var typicalMethodDef in _typeDef.GetVirtualMethods()) + { + yield return _typeDef.Context.GetMethodForInstantiatedType(typicalMethodDef, this); + } + } + // TODO: Substitutions, generics, modopts, ... public override MethodDesc GetMethod(string name, MethodSignature signature, Instantiation substitution) { diff --git a/src/coreclr/tools/Common/TypeSystem/Common/MetadataVirtualMethodAlgorithm.cs b/src/coreclr/tools/Common/TypeSystem/Common/MetadataVirtualMethodAlgorithm.cs index a3af0aa..5a33ab4 100644 --- a/src/coreclr/tools/Common/TypeSystem/Common/MetadataVirtualMethodAlgorithm.cs +++ b/src/coreclr/tools/Common/TypeSystem/Common/MetadataVirtualMethodAlgorithm.cs @@ -330,11 +330,8 @@ namespace Internal.TypeSystem MethodSignature sig = targetMethod.Signature; MethodDesc implMethod = null; - foreach (MethodDesc candidate in currentType.GetAllMethods()) + foreach (MethodDesc candidate in currentType.GetAllVirtualMethods()) { - if (!candidate.IsVirtual) - continue; - if (candidate.Name == name) { if (candidate.Signature.Equals(sig)) @@ -810,11 +807,8 @@ namespace Internal.TypeSystem { do { - foreach (MethodDesc m in type.GetAllMethods()) + foreach (MethodDesc m in type.GetAllVirtualMethods()) { - if (!m.IsVirtual) - continue; - MethodDesc possibleVirtual = FindSlotDefiningMethodForVirtualMethod(m); if (!alreadyEnumerated.Contains(possibleVirtual)) { diff --git a/src/coreclr/tools/Common/TypeSystem/Common/Properties/Resources.resx b/src/coreclr/tools/Common/TypeSystem/Common/Properties/Resources.resx index 489fa6d..a4f9e6a 100644 --- a/src/coreclr/tools/Common/TypeSystem/Common/Properties/Resources.resx +++ b/src/coreclr/tools/Common/TypeSystem/Common/Properties/Resources.resx @@ -183,4 +183,7 @@ The format of a DLL or executable being loaded is invalid with {0} + + Marshaling directives are invalid + diff --git a/src/coreclr/tools/Common/TypeSystem/Common/ThrowHelper.cs b/src/coreclr/tools/Common/TypeSystem/Common/ThrowHelper.cs index 90c02f6..4e31950 100644 --- a/src/coreclr/tools/Common/TypeSystem/Common/ThrowHelper.cs +++ b/src/coreclr/tools/Common/TypeSystem/Common/ThrowHelper.cs @@ -65,6 +65,12 @@ namespace Internal.TypeSystem throw new TypeSystemException.BadImageFormatException(message); } + [System.Diagnostics.DebuggerHidden] + public static void ThrowMarshalDirectiveException() + { + throw new TypeSystemException.MarshalDirectiveException(ExceptionStringID.MarshalDirectiveGeneric); + } + private static partial class Format { public static string OwningModule(TypeDesc type) diff --git a/src/coreclr/tools/Common/TypeSystem/Common/TypeDesc.cs b/src/coreclr/tools/Common/TypeSystem/Common/TypeDesc.cs index b60e016..51cf729 100644 --- a/src/coreclr/tools/Common/TypeSystem/Common/TypeDesc.cs +++ b/src/coreclr/tools/Common/TypeSystem/Common/TypeDesc.cs @@ -511,6 +511,16 @@ namespace Internal.TypeSystem } /// + /// Gets a subset of methods returned by that are virtual. + /// + public virtual IEnumerable GetVirtualMethods() + { + foreach (MethodDesc method in GetMethods()) + if (method.IsVirtual) + yield return method; + } + + /// /// Gets a named method on the type. This method only looks at methods defined /// in type's metadata. The parameter can be null. /// If signature is not specified and there are multiple matches, the first one diff --git a/src/coreclr/tools/Common/TypeSystem/Common/TypeSystemContext.cs b/src/coreclr/tools/Common/TypeSystem/Common/TypeSystemContext.cs index 21c17d4..fcb47f4 100644 --- a/src/coreclr/tools/Common/TypeSystem/Common/TypeSystemContext.cs +++ b/src/coreclr/tools/Common/TypeSystem/Common/TypeSystemContext.cs @@ -677,6 +677,11 @@ namespace Internal.TypeSystem return type.GetMethods(); } + protected internal virtual IEnumerable GetAllVirtualMethods(TypeDesc type) + { + return type.GetVirtualMethods(); + } + /// /// Abstraction to allow the type system context to affect the field layout /// algorithm used by types to lay themselves out. diff --git a/src/coreclr/tools/Common/TypeSystem/Common/TypeSystemException.cs b/src/coreclr/tools/Common/TypeSystem/Common/TypeSystemException.cs index 598f0f6..39015e8 100644 --- a/src/coreclr/tools/Common/TypeSystem/Common/TypeSystemException.cs +++ b/src/coreclr/tools/Common/TypeSystem/Common/TypeSystemException.cs @@ -162,5 +162,13 @@ namespace Internal.TypeSystem } } + + public class MarshalDirectiveException : TypeSystemException + { + internal MarshalDirectiveException(ExceptionStringID id) + : base(id) + { + } + } } } diff --git a/src/coreclr/tools/Common/TypeSystem/Common/TypeSystemHelpers.cs b/src/coreclr/tools/Common/TypeSystem/Common/TypeSystemHelpers.cs index 76bb199..2442f04 100644 --- a/src/coreclr/tools/Common/TypeSystem/Common/TypeSystemHelpers.cs +++ b/src/coreclr/tools/Common/TypeSystem/Common/TypeSystemHelpers.cs @@ -261,6 +261,14 @@ namespace Internal.TypeSystem return type.Context.GetAllMethods(type); } + /// + /// Retrieves all virtual methods on a type, including the ones injected by the type system context. + /// + public static IEnumerable GetAllVirtualMethods(this TypeDesc type) + { + return type.Context.GetAllVirtualMethods(type); + } + public static IEnumerable EnumAllVirtualSlots(this TypeDesc type) { return type.Context.GetVirtualMethodAlgorithmForType(type).ComputeAllVirtualSlots(type); diff --git a/src/coreclr/tools/Common/TypeSystem/Common/Utilities/DebugNameFormatter.cs b/src/coreclr/tools/Common/TypeSystem/Common/Utilities/DebugNameFormatter.cs index e353a59..ea55c07 100644 --- a/src/coreclr/tools/Common/TypeSystem/Common/Utilities/DebugNameFormatter.cs +++ b/src/coreclr/tools/Common/TypeSystem/Common/Utilities/DebugNameFormatter.cs @@ -202,9 +202,15 @@ namespace Internal.TypeSystem } if (assemblyName.StartsWith("System.Private", StringComparison.Ordinal)) - assemblyName = "S.P" + assemblyName.Substring(14); + { + sb.Append("S.P"); + sb.Append(assemblyName, 14, assemblyName.Length - 14); + } + else + { + sb.Append(assemblyName); + } - sb.Append(assemblyName); sb.Append(']'); } } diff --git a/src/coreclr/tools/Common/TypeSystem/Ecma/EcmaType.cs b/src/coreclr/tools/Common/TypeSystem/Ecma/EcmaType.cs index 8075ef7..073cb7a 100644 --- a/src/coreclr/tools/Common/TypeSystem/Ecma/EcmaType.cs +++ b/src/coreclr/tools/Common/TypeSystem/Ecma/EcmaType.cs @@ -306,7 +306,18 @@ namespace Internal.TypeSystem.Ecma { foreach (var handle in _typeDefinition.GetMethods()) { - yield return (MethodDesc)_module.GetObject(handle); + yield return (EcmaMethod)_module.GetObject(handle); + } + } + + public override IEnumerable GetVirtualMethods() + { + MetadataReader reader = _module.MetadataReader; + foreach (var handle in _typeDefinition.GetMethods()) + { + MethodDefinition methodDef = reader.GetMethodDefinition(handle); + if ((methodDef.Attributes & MethodAttributes.Virtual) != 0) + yield return (EcmaMethod)_module.GetObject(handle); } } @@ -319,7 +330,7 @@ namespace Internal.TypeSystem.Ecma { if (stringComparer.Equals(metadataReader.GetMethodDefinition(handle).Name, name)) { - MethodDesc method = (MethodDesc)_module.GetObject(handle); + var method = (EcmaMethod)_module.GetObject(handle); if (signature == null || signature.Equals(method.Signature.ApplySubstitution(substitution))) return method; } @@ -339,7 +350,7 @@ namespace Internal.TypeSystem.Ecma if (methodDefinition.Attributes.IsRuntimeSpecialName() && stringComparer.Equals(methodDefinition.Name, ".cctor")) { - MethodDesc method = (MethodDesc)_module.GetObject(handle); + var method = (EcmaMethod)_module.GetObject(handle); return method; } } @@ -362,7 +373,7 @@ namespace Internal.TypeSystem.Ecma if (attributes.IsRuntimeSpecialName() && attributes.IsPublic() && stringComparer.Equals(methodDefinition.Name, ".ctor")) { - MethodDesc method = (MethodDesc)_module.GetObject(handle); + var method = (EcmaMethod)_module.GetObject(handle); if (method.Signature.Length != 0) continue; @@ -435,7 +446,7 @@ namespace Internal.TypeSystem.Ecma { foreach (var handle in _typeDefinition.GetNestedTypes()) { - yield return (MetadataType)_module.GetObject(handle); + yield return (EcmaType)_module.GetObject(handle); } } @@ -460,7 +471,7 @@ namespace Internal.TypeSystem.Ecma } if (nameMatched) - return (MetadataType)_module.GetObject(handle); + return (EcmaType)_module.GetObject(handle); } return null; @@ -527,7 +538,7 @@ namespace Internal.TypeSystem.Ecma // Note: GetOffset() returns -1 when offset was not set in the metadata int specifiedOffset = fieldDefinition.GetOffset(); result.Offsets[index] = - new FieldAndOffset((FieldDesc)_module.GetObject(handle), specifiedOffset == -1 ? FieldAndOffset.InvalidOffset : new LayoutInt(specifiedOffset)); + new FieldAndOffset((EcmaField)_module.GetObject(handle), specifiedOffset == -1 ? FieldAndOffset.InvalidOffset : new LayoutInt(specifiedOffset)); index++; } diff --git a/src/coreclr/tools/Common/TypeSystem/Ecma/SymbolReader/PortablePdbSymbolReader.cs b/src/coreclr/tools/Common/TypeSystem/Ecma/SymbolReader/PortablePdbSymbolReader.cs index b7aacf6..5d8d4fd 100644 --- a/src/coreclr/tools/Common/TypeSystem/Ecma/SymbolReader/PortablePdbSymbolReader.cs +++ b/src/coreclr/tools/Common/TypeSystem/Ecma/SymbolReader/PortablePdbSymbolReader.cs @@ -123,12 +123,25 @@ namespace Internal.TypeSystem.Ecma var sequencePoints = debugInformation.GetSequencePoints(); + DocumentHandle previousDocumentHandle = default; + string previousDocumentUrl = null; + foreach (var sequencePoint in sequencePoints) { - if (sequencePoint.StartLine == 0xFEEFEE) + if (sequencePoint.StartLine == SequencePoint.HiddenLine) continue; - var url = _reader.GetString(_reader.GetDocument(sequencePoint.Document).Name); + string url; + if (sequencePoint.Document == previousDocumentHandle) + { + url = previousDocumentUrl; + } + else + { + url = _reader.GetString(_reader.GetDocument(sequencePoint.Document).Name); + previousDocumentHandle = sequencePoint.Document; + previousDocumentUrl = url; + } yield return new ILSequencePoint(sequencePoint.Offset, url, sequencePoint.StartLine); } diff --git a/src/coreclr/tools/Common/TypeSystem/Interop/IL/MarshalHelpers.cs b/src/coreclr/tools/Common/TypeSystem/Interop/IL/MarshalHelpers.cs index 1989b65..64ba412 100644 --- a/src/coreclr/tools/Common/TypeSystem/Interop/IL/MarshalHelpers.cs +++ b/src/coreclr/tools/Common/TypeSystem/Interop/IL/MarshalHelpers.cs @@ -63,6 +63,9 @@ namespace Internal.TypeSystem.Interop case MarshallerKind.CBool: return context.GetWellKnownType(WellKnownType.Byte); + case MarshallerKind.VariantBool: + return context.GetWellKnownType(WellKnownType.Int16); + case MarshallerKind.Enum: case MarshallerKind.BlittableStruct: case MarshallerKind.Decimal: @@ -162,6 +165,14 @@ namespace Internal.TypeSystem.Interop case MarshallerKind.ComInterface: return context.GetWellKnownType(WellKnownType.IntPtr); +#if !READYTORUN + case MarshallerKind.Variant: + return InteropTypes.GetVariant(context); +#endif + + case MarshallerKind.OleCurrency: + return context.GetWellKnownType(WellKnownType.Int64); + case MarshallerKind.Unknown: default: throw new NotSupportedException(); @@ -254,6 +265,9 @@ namespace Internal.TypeSystem.Interop case NativeTypeKind.I1: return MarshallerKind.CBool; + case NativeTypeKind.VariantBool: + return MarshallerKind.VariantBool; + default: return MarshallerKind.Invalid; } @@ -355,6 +369,8 @@ namespace Internal.TypeSystem.Interop return MarshallerKind.Decimal; else if (nativeType == NativeTypeKind.LPStruct && !isField) return MarshallerKind.BlittableStructPtr; + else if (nativeType == NativeTypeKind.Currency) + return MarshallerKind.OleCurrency; else return MarshallerKind.Invalid; } @@ -434,9 +450,6 @@ namespace Internal.TypeSystem.Interop { case NativeTypeKind.Array: { - if (isField || isReturn) - return MarshallerKind.Invalid; - var arrayType = (ArrayType)type; elementMarshallerKind = GetArrayElementMarshallerKind( @@ -569,7 +582,7 @@ namespace Internal.TypeSystem.Interop || nativeType == NativeTypeKind.IUnknown) return MarshallerKind.ComInterface; else - return MarshallerKind.Invalid; + return MarshallerKind.Variant; } else if (InteropTypes.IsStringBuilder(context, type)) { @@ -794,6 +807,11 @@ namespace Internal.TypeSystem.Interop return MarshallerKind.UnicodeString; case NativeTypeKind.LPUTF8Str: return MarshallerKind.UTF8String; + case NativeTypeKind.BStr: + case NativeTypeKind.TBStr: + return MarshallerKind.BSTRString; + case NativeTypeKind.AnsiBStr: + return MarshallerKind.AnsiBSTRString; default: return MarshallerKind.Invalid; } diff --git a/src/coreclr/tools/Common/TypeSystem/Interop/IL/Marshaller.cs b/src/coreclr/tools/Common/TypeSystem/Interop/IL/Marshaller.cs index d9d23c5..46c5315 100644 --- a/src/coreclr/tools/Common/TypeSystem/Interop/IL/Marshaller.cs +++ b/src/coreclr/tools/Common/TypeSystem/Interop/IL/Marshaller.cs @@ -19,6 +19,7 @@ namespace Internal.TypeSystem.Interop BlittableArray, Bool, // 4 byte bool CBool, // 1 byte bool + VariantBool, // Variant bool Enum, AnsiChar, // Marshal char (Unicode 16bits) for byte (Ansi 8bits) UnicodeChar, @@ -43,6 +44,7 @@ namespace Internal.TypeSystem.Interop Object, OleDateTime, Decimal, + OleCurrency, Guid, Struct, BlittableStruct, @@ -152,7 +154,7 @@ namespace Internal.TypeSystem.Interop public bool Return; public bool IsManagedByRef; // Whether managed argument is passed by ref public bool IsNativeByRef; // Whether native argument is passed by byref - // There are special cases (such as LpStruct, and class) that + // There are special cases (such as LpStruct, and class) that // isNativeByRef != IsManagedByRef public MarshalDirection MarshalDirection; protected PInvokeILCodeStreams _ilCodeStreams; @@ -245,7 +247,7 @@ namespace Internal.TypeSystem.Interop break; default: // Storing by-ref arg/local is not supported because StInd require - // address to be pushed first. Instead we need to introduce a non-byref + // address to be pushed first. Instead we need to introduce a non-byref // local and propagate value as needed for by-ref arguments Debug.Assert(false); break; @@ -333,7 +335,7 @@ namespace Internal.TypeSystem.Interop // if (isOut) { - // Passing as [Out] by ref is always valid. + // Passing as [Out] by ref is always valid. if (!marshaller.IsManagedByRef) { // Ignore [Out] for ValueType, string and pointers @@ -634,7 +636,7 @@ namespace Internal.TypeSystem.Interop /// /// Propagate by-ref arg to corresponding local - /// We can't load value + ldarg + ldind in the expected order, so + /// We can't load value + ldarg + ldind in the expected order, so /// we had to use a non-by-ref local and manually propagate the value /// protected void PropagateFromByRefArg(ILCodeStream stream, Home home) @@ -646,7 +648,7 @@ namespace Internal.TypeSystem.Interop /// /// Propagate local to corresponding by-ref arg - /// We can't load value + ldarg + ldind in the expected order, so + /// We can't load value + ldarg + ldind in the expected order, so /// we had to use a non-by-ref local and manually propagate the value /// protected void PropagateToByRefArg(ILCodeStream stream, Home home) @@ -838,7 +840,7 @@ namespace Internal.TypeSystem.Interop SetupArgumentsForFieldMarshalling(); // // For field marshalling we expect the value of the field is already loaded - // in the stack. + // in the stack. // StoreManagedValue(marshallingCodeStream); @@ -980,6 +982,11 @@ namespace Internal.TypeSystem.Interop } } + protected override void SetupArgumentsForFieldMarshalling() + { + ThrowHelper.ThrowTypeLoadException(ExceptionStringID.ClassLoadGeneral, ManagedType); + } + protected Marshaller GetElementMarshaller(MarshalDirection direction) { if (_elementMarshaller == null) @@ -1038,7 +1045,7 @@ namespace Internal.TypeSystem.Interop if (index < 0 || index >= Marshallers.Length - 1) { - throw new InvalidProgramException("Invalid SizeParamIndex, must be between 0 and parameter count"); + ThrowHelper.ThrowMarshalDirectiveException(); } //zero-th index is for return type @@ -1058,7 +1065,8 @@ namespace Internal.TypeSystem.Interop case TypeFlags.UIntPtr: break; default: - throw new InvalidProgramException("Invalid SizeParamIndex, parameter must be of type int/uint"); + ThrowHelper.ThrowMarshalDirectiveException(); + break; } // @TODO - We can use LoadManagedValue, but that requires byref arg propagation happen in a special setup stream @@ -1347,7 +1355,7 @@ namespace Internal.TypeSystem.Interop // Check for null array LoadManagedValue(codeStream); codeStream.Emit(ILOpcode.brfalse, lNullArray); - + if (IsManagedByRef) { base.AllocManagedToNative(codeStream); @@ -1405,13 +1413,38 @@ namespace Internal.TypeSystem.Interop class BooleanMarshaller : Marshaller { + private int _trueValue; + public BooleanMarshaller(int trueValue = 1) + { + _trueValue = trueValue; + } + protected override void AllocAndTransformManagedToNative(ILCodeStream codeStream) { + ILEmitter emitter = _ilCodeStreams.Emitter; + ILCodeLabel pLoadFalseLabel = emitter.NewCodeLabel(); + ILCodeLabel pDoneLabel = emitter.NewCodeLabel(); + LoadManagedValue(codeStream); - codeStream.EmitLdc(0); - codeStream.Emit(ILOpcode.ceq); - codeStream.EmitLdc(0); - codeStream.Emit(ILOpcode.ceq); + if (_trueValue == 1) + { + codeStream.EmitLdc(0); + codeStream.Emit(ILOpcode.ceq); + codeStream.EmitLdc(0); + codeStream.Emit(ILOpcode.ceq); + } + else + { + codeStream.Emit(ILOpcode.brfalse, pLoadFalseLabel); + codeStream.EmitLdc(_trueValue); + codeStream.Emit(ILOpcode.br, pDoneLabel); + + codeStream.EmitLabel(pLoadFalseLabel); + codeStream.EmitLdc(0); + + codeStream.EmitLabel(pDoneLabel); + } + StoreNativeValue(codeStream); } @@ -1763,7 +1796,7 @@ namespace Internal.TypeSystem.Interop cleanupCodeStream.Emit(ILOpcode.brfalse, lNotAddrefed); LoadManagedValue(cleanupCodeStream); cleanupCodeStream.Emit(ILOpcode.call, emitter.NewToken( - safeHandleType.GetKnownMethod("DangerousRelease", + safeHandleType.GetKnownMethod("DangerousRelease", new MethodSignature(0, 0, Context.GetWellKnownType(WellKnownType.Void), TypeDesc.EmptyTypes)))); cleanupCodeStream.EmitLabel(lNotAddrefed); } @@ -1774,7 +1807,7 @@ namespace Internal.TypeSystem.Interop // must allocate this before the native call to avoid a failure point when we already have a native resource // allocated. We must allocate a new SafeHandle even if we have one on input since both input and output native // handles need to be tracked and released by a SafeHandle. - // 2) Initialize a local IntPtr that will be passed to the native call. + // 2) Initialize a local IntPtr that will be passed to the native call. // 3) After the native call, the new handle value is written into the output SafeHandle and that SafeHandle // is propagated back to the caller. var vSafeHandle = emitter.NewLocal(ManagedType); @@ -1891,7 +1924,7 @@ namespace Internal.TypeSystem.Interop )))); #else codeStream.Emit(ILOpcode.ldtoken, _ilCodeStreams.Emitter.NewToken(ManagedType)); - + codeStream.Emit(ILOpcode.call, _ilCodeStreams.Emitter.NewToken( InteropTypes.GetPInvokeMarshal(Context).GetKnownMethod("GetDelegateForFunctionPointer", new MethodSignature(MethodSignatureFlags.Static, 0, Context.GetWellKnownType(WellKnownType.MulticastDelegate).BaseType, diff --git a/src/coreclr/tools/Common/TypeSystem/Interop/MarshalAsDescriptor.cs b/src/coreclr/tools/Common/TypeSystem/Interop/MarshalAsDescriptor.cs index 05c9582..26b5312 100644 --- a/src/coreclr/tools/Common/TypeSystem/Interop/MarshalAsDescriptor.cs +++ b/src/coreclr/tools/Common/TypeSystem/Interop/MarshalAsDescriptor.cs @@ -19,6 +19,7 @@ namespace Internal.TypeSystem U8 = 0xa, R4 = 0xb, R8 = 0xc, + Currency = 0xf, BStr = 0x13, LPStr = 0x14, LPWStr = 0x15, @@ -33,6 +34,7 @@ namespace Internal.TypeSystem SysUInt = 0x20, AnsiBStr = 0x23, TBStr = 0x24, + VariantBool = 0x25, Func = 0x26, AsAny = 0x28, Array = 0x2a, diff --git a/src/coreclr/tools/Common/TypeSystem/RuntimeDetermined/RuntimeDeterminedType.cs b/src/coreclr/tools/Common/TypeSystem/RuntimeDetermined/RuntimeDeterminedType.cs index e651989..df7dbd1 100644 --- a/src/coreclr/tools/Common/TypeSystem/RuntimeDetermined/RuntimeDeterminedType.cs +++ b/src/coreclr/tools/Common/TypeSystem/RuntimeDetermined/RuntimeDeterminedType.cs @@ -114,6 +114,14 @@ namespace Internal.TypeSystem } } + public override IEnumerable GetVirtualMethods() + { + foreach (var method in _rawCanonType.GetVirtualMethods()) + { + yield return Context.GetMethodForRuntimeDeterminedType(method.GetTypicalMethodDefinition(), this); + } + } + public override MethodDesc GetMethod(string name, MethodSignature signature, Instantiation substitution) { MethodDesc method = _rawCanonType.GetMethod(name, signature, substitution); diff --git a/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/SyntheticVirtualOverrideTests.cs b/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/SyntheticVirtualOverrideTests.cs index 9fc3b9b..46aa71c 100644 --- a/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/SyntheticVirtualOverrideTests.cs +++ b/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/SyntheticVirtualOverrideTests.cs @@ -153,6 +153,21 @@ namespace TypeSystemTests foreach (var m in mdType.GetMethods()) yield return m; } + + protected override IEnumerable GetAllVirtualMethods(TypeDesc type) + { + MetadataType mdType = type as MetadataType; + + if (mdType.Name == "StructWithNoEqualsAndGetHashCode" + || mdType.Name == "ClassWithInjectedEqualsAndGetHashCode") + { + yield return GetEqualsMethod(type); + yield return GetGetHashCodeMethod(type); + } + + foreach (var m in mdType.GetVirtualMethods()) + yield return m; + } } private partial class SyntheticMethod : MethodDesc diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/StackFrame.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/StackFrame.cs index cc2d1d1..5f19d27 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/StackFrame.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/StackFrame.cs @@ -3,6 +3,7 @@ using System.Text; using System.Reflection; +using System.Runtime.CompilerServices; namespace System.Diagnostics { @@ -57,6 +58,7 @@ namespace System.Diagnostics /// /// Constructs a StackFrame corresponding to the active stack frame. /// + [MethodImplAttribute(MethodImplOptions.NoInlining)] public StackFrame() { InitMembers(); @@ -66,6 +68,7 @@ namespace System.Diagnostics /// /// Constructs a StackFrame corresponding to the active stack frame. /// + [MethodImplAttribute(MethodImplOptions.NoInlining)] public StackFrame(bool needFileInfo) { InitMembers(); @@ -75,6 +78,7 @@ namespace System.Diagnostics /// /// Constructs a StackFrame corresponding to a calling stack frame. /// + [MethodImplAttribute(MethodImplOptions.NoInlining)] public StackFrame(int skipFrames) { InitMembers(); @@ -84,6 +88,7 @@ namespace System.Diagnostics /// /// Constructs a StackFrame corresponding to a calling stack frame. /// + [MethodImplAttribute(MethodImplOptions.NoInlining)] public StackFrame(int skipFrames, bool needFileInfo) { InitMembers(); @@ -95,6 +100,7 @@ namespace System.Diagnostics /// name and line number. Use when you don't want to use the /// debugger's line mapping logic. /// + [MethodImplAttribute(MethodImplOptions.NoInlining)] public StackFrame(string? fileName, int lineNumber) { InitMembers(); @@ -109,9 +115,14 @@ namespace System.Diagnostics /// name, line number and column number. Use when you don't want to /// use the debugger's line mapping logic. /// + [MethodImplAttribute(MethodImplOptions.NoInlining)] public StackFrame(string? fileName, int lineNumber, int colNumber) - : this(fileName, lineNumber) { + InitMembers(); + + BuildStackFrame(StackTrace.METHODS_TO_SKIP, false); + _fileName = fileName; + _lineNumber = lineNumber; _columnNumber = colNumber; } diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/StackTrace.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/StackTrace.cs index f8e46b0..50d873d 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/StackTrace.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/StackTrace.cs @@ -30,6 +30,7 @@ namespace System.Diagnostics /// /// Constructs a stack trace from the current location. /// + [MethodImplAttribute(MethodImplOptions.NoInlining)] public StackTrace() { InitializeForCurrentThread(METHODS_TO_SKIP, false); @@ -38,6 +39,7 @@ namespace System.Diagnostics /// /// Constructs a stack trace from the current location. /// + [MethodImplAttribute(MethodImplOptions.NoInlining)] public StackTrace(bool fNeedFileInfo) { InitializeForCurrentThread(METHODS_TO_SKIP, fNeedFileInfo); @@ -47,6 +49,7 @@ namespace System.Diagnostics /// Constructs a stack trace from the current location, in a caller's /// frame /// + [MethodImplAttribute(MethodImplOptions.NoInlining)] public StackTrace(int skipFrames) { if (skipFrames < 0) @@ -60,6 +63,7 @@ namespace System.Diagnostics /// Constructs a stack trace from the current location, in a caller's /// frame /// + [MethodImplAttribute(MethodImplOptions.NoInlining)] public StackTrace(int skipFrames, bool fNeedFileInfo) { if (skipFrames < 0) diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/ReflectionMemberAccessor.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/ReflectionMemberAccessor.cs index 2a8ccd1..0352277 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/ReflectionMemberAccessor.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/ReflectionMemberAccessor.cs @@ -10,6 +10,18 @@ namespace System.Text.Json.Serialization.Metadata { internal sealed class ReflectionMemberAccessor : MemberAccessor { + private class ConstructorContext + { + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] + private readonly Type _type; + + public ConstructorContext([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type type) + => _type = type; + + public object? CreateInstance() + => Activator.CreateInstance(_type, nonPublic: false); + } + public override JsonTypeInfo.ConstructorDelegate? CreateConstructor( [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type type) { @@ -26,7 +38,7 @@ namespace System.Text.Json.Serialization.Metadata return null; } - return () => Activator.CreateInstance(type, nonPublic: false); + return new ConstructorContext(type).CreateInstance; } public override JsonTypeInfo.ParameterizedConstructorDelegate? CreateParameterizedConstructor(ConstructorInfo constructor) -- 2.7.4