diff options
author | Jan Kotas <jkotas@microsoft.com> | 2017-06-10 01:57:53 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-06-10 01:57:53 +0300 |
commit | 1c9d5697bfecd4274b08b163d570a9a21832ba4b (patch) | |
tree | 7111a5f54cc53a71ba2f804b5acbf47624131083 | |
parent | 2928e63d8ebd62146c6e94dc3e258c59e598b2c9 (diff) | |
parent | 80791e9aaa9b5a481534cde52c77fb8061af674e (diff) |
Merge pull request #3849 from dotnet/nmirror
Merge nmirror to master
19 files changed, 396 insertions, 320 deletions
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/UtcNodeFactory.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/UtcNodeFactory.cs index 1301565ea..5b099551c 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/UtcNodeFactory.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/UtcNodeFactory.cs @@ -18,6 +18,7 @@ namespace ILCompiler { public static string CompilationUnitPrefix = ""; public string targetPrefix; + private bool buildMRT; private static byte[] ReadBytesFromFile(string filename) { @@ -69,7 +70,7 @@ namespace ILCompiler } } - public UtcNodeFactory(CompilerTypeSystemContext context, CompilationModuleGroup compilationModuleGroup, IEnumerable<ModuleDesc> inputModules, string metadataFile, string outputFile, UTCNameMangler nameMangler) + public UtcNodeFactory(CompilerTypeSystemContext context, CompilationModuleGroup compilationModuleGroup, IEnumerable<ModuleDesc> inputModules, string metadataFile, string outputFile, UTCNameMangler nameMangler, bool buildMRT) : base(context, compilationModuleGroup, PickMetadataManager(context, compilationModuleGroup, inputModules, metadataFile), nameMangler, new AttributeDrivenLazyGenericsPolicy()) { CreateHostedNodeCaches(); @@ -79,6 +80,7 @@ namespace ILCompiler TLSDirectory = new ThreadStaticsDirectoryNode(targetPrefix); TlsStart = new ExternSymbolNode(targetPrefix + "_tls_start"); TlsEnd = new ExternSymbolNode(targetPrefix + "_tls_end"); + this.buildMRT = buildMRT; } private void CreateHostedNodeCaches() @@ -145,8 +147,13 @@ namespace ILCompiler graph.AddRoot(GCStaticDescRegion, "GC Static Desc is always generated"); graph.AddRoot(ThreadStaticsOffsetRegion, "Thread Statics Offset Region is always generated"); graph.AddRoot(ThreadStaticGCDescRegion, "Thread Statics GC Desc Region is always generated"); - graph.AddRoot(ThreadStaticsIndex, "Thread statics index is always generated"); - graph.AddRoot(TLSDirectory, "TLS Directory is always generated"); + + // The native part of the MRT library links against CRT which defines _tls_index and _tls_used. + if (!buildMRT) + { + graph.AddRoot(ThreadStaticsIndex, "Thread statics index is always generated"); + graph.AddRoot(TLSDirectory, "TLS Directory is always generated"); + } ReadyToRunHeader.Add(ReadyToRunSectionType.EagerCctor, EagerCctorTable, EagerCctorTable.StartSymbol, EagerCctorTable.EndSymbol); ReadyToRunHeader.Add(ReadyToRunSectionType.InterfaceDispatchTable, DispatchMapTable, DispatchMapTable.StartSymbol); @@ -156,7 +163,11 @@ namespace ILCompiler ReadyToRunHeader.Add(ReadyToRunSectionType.GCStaticDesc, GCStaticDescRegion, GCStaticDescRegion.StartSymbol, GCStaticDescRegion.EndSymbol); ReadyToRunHeader.Add(ReadyToRunSectionType.ThreadStaticOffsetRegion, ThreadStaticsOffsetRegion, ThreadStaticsOffsetRegion.StartSymbol, ThreadStaticsOffsetRegion.EndSymbol); ReadyToRunHeader.Add(ReadyToRunSectionType.ThreadStaticGCDescRegion, ThreadStaticGCDescRegion, ThreadStaticGCDescRegion.StartSymbol, ThreadStaticGCDescRegion.EndSymbol); - ReadyToRunHeader.Add(ReadyToRunSectionType.ThreadStaticIndex, ThreadStaticsIndex, ThreadStaticsIndex); + + if (!buildMRT) + { + ReadyToRunHeader.Add(ReadyToRunSectionType.ThreadStaticIndex, ThreadStaticsIndex, ThreadStaticsIndex); + } MetadataManager.AddToReadyToRunHeader(ReadyToRunHeader, this); MetadataManager.AttachToDependencyGraph(graph); diff --git a/src/Native/Runtime/DebuggerHook.cpp b/src/Native/Runtime/DebuggerHook.cpp index 59042d912..dafa56b4b 100644 --- a/src/Native/Runtime/DebuggerHook.cpp +++ b/src/Native/Runtime/DebuggerHook.cpp @@ -49,7 +49,7 @@ GVAL_IMPL_INIT(UInt32, g_numGcProtectionRequests, 0); } } - // TODO: Consider an optimization to eliminate this message when they is nothing required from the + // TODO, FuncEval, consider an optimization to eliminate this message when they is nothing required from the // debugger side to fill command.commandCode = DebuggerGcProtectionMessage::ConservativeReportingBufferReady; @@ -101,8 +101,8 @@ GVAL_IMPL_INIT(UInt32, g_numGcProtectionRequests, 0); s_debuggerProtectedBuffers = new (std::nothrow) DebuggerProtectedBufferList(); if (s_debuggerProtectedBuffers == nullptr) { - // TODO: We cannot handle the debugger request to protect a buffer (we have to break our promise) - // TODO: We need to figure out how to communicate this broken promise to the debugger + // TODO, FuncEval, we cannot handle the debugger request to protect a buffer (we have to break our promise) + // TODO, FuncEval, we need to figure out how to communicate this broken promise to the debugger } else { diff --git a/src/Native/Runtime/StackFrameIterator.cpp b/src/Native/Runtime/StackFrameIterator.cpp index 34f2aa0e4..86de077a1 100644 --- a/src/Native/Runtime/StackFrameIterator.cpp +++ b/src/Native/Runtime/StackFrameIterator.cpp @@ -100,7 +100,7 @@ PTR_PInvokeTransitionFrame GetPInvokeTransitionFrame(PTR_VOID pTransitionFrame) return static_cast<PTR_PInvokeTransitionFrame>(pTransitionFrame); } -// TODO: Remove the assumption that there is only 1 func eval in progress +// TODO, FuncEval, remove the assumption that there is only 1 func eval in progress GVAL_IMPL_INIT(UInt64, g_debuggermagic, 0); StackFrameIterator::StackFrameIterator(Thread * pThreadToWalk, PTR_VOID pInitialTransitionFrame) diff --git a/src/System.Private.CoreLib/src/Internal/Runtime/Augments/EnumInfo.cs b/src/System.Private.CoreLib/src/Internal/Runtime/Augments/EnumInfo.cs index 0d72b10c8..ff1d19635 100644 --- a/src/System.Private.CoreLib/src/Internal/Runtime/Augments/EnumInfo.cs +++ b/src/System.Private.CoreLib/src/Internal/Runtime/Augments/EnumInfo.cs @@ -4,30 +4,128 @@ using System; using System.Collections.Generic; +using System.Diagnostics; +using System.Reflection; +using System.Runtime; +using System.Runtime.CompilerServices; namespace Internal.Runtime.Augments { -#pragma warning disable 3003 - - // - // Abstract base for reflection-based information regarding an Enum type. - // - public abstract class EnumInfo + public sealed class EnumInfo { - public abstract Type UnderlyingType { get; } - - /// <summary> - /// Returns an array whose element type is the underlying enum type. Sorted the same way NamesAndValues is sorted. - /// </summary> - public abstract Array Values { get; } - - /// <summary> - /// Sorted by performing a value-preserving cast of each value to long, (except in the case of a ulong in which case, - /// a 2's complement conversion is done), then doing a 2's complement cast to ulong and sorting as ulong. - /// </summary> - public abstract KeyValuePair<String, ulong>[] NamesAndValues { get; } - - public abstract bool HasFlagsAttribute { get; } + public EnumInfo(Type enumType) + { + Debug.Assert(enumType != null); + Debug.Assert(enumType.IsRuntimeImplemented()); + Debug.Assert(enumType.IsEnum); + + UnderlyingType = ComputeUnderlyingType(enumType); + + FieldInfo[] fields = enumType.GetFields(BindingFlags.Public | BindingFlags.Static); + int numValues = fields.Length; + object[] rawValues = new object[numValues]; + KeyValuePair<string, ulong>[] namesAndValues = new KeyValuePair<string, ulong>[numValues]; + for (int i = 0; i < numValues; i++) + { + FieldInfo field = fields[i]; + object rawValue = field.GetRawConstantValue(); + rawValues[i] = rawValue; + + ulong rawUnboxedValue; + if (rawValue is ulong) + { + rawUnboxedValue = (ulong)rawValue; + } + else + { + // This conversion is this way for compatibility: do a value-preseving cast to long - then store (and compare) as ulong. This affects + // the order in which the Enum apis return names and values. + rawUnboxedValue = (ulong)(((IConvertible)rawValue).ToInt64(null)); + } + namesAndValues[i] = new KeyValuePair<string, ulong>(field.Name, rawUnboxedValue); + } + + Array.Sort(keys: namesAndValues, items: rawValues, comparer: NamesAndValueComparer.Default); + NamesAndValues = namesAndValues; + + // Create the unboxed version of values for the Values property to return. (We didn't do this earlier because + // declaring "rawValues" as "Array" would prevent us from using the generic overload of Array.Sort()). + // + // The array element type is the underlying type, not the enum type. (The enum type could be an open generic.) + Values = Array.CreateInstance(UnderlyingType, numValues); + Array.Copy(rawValues, Values, numValues); + + HasFlagsAttribute = enumType.IsDefined(typeof(FlagsAttribute), inherit: false); + } + + internal Type UnderlyingType { get; } + internal Array Values { get; } + internal KeyValuePair<string, ulong>[] NamesAndValues { get; } + internal bool HasFlagsAttribute { get; } + + private static RuntimeImports.RhCorElementType ComputeCorElementType(Type enumType) + { + if (enumType.ContainsGenericParameters) + { + // This is an open generic enum (typeof(Outer<>).NestedEnum). We cannot safely call EETypePtr.CorElementType for this case so fall back to Reflection. + FieldInfo[] candidates = enumType.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly); + if (candidates.Length == 0) + throw RuntimeAugments.Callbacks.CreateMissingMetadataException(enumType); // Most likely cause. + if (candidates.Length > 1) + throw new BadImageFormatException(); + enumType = candidates[0].FieldType; + } + return enumType.TypeHandle.ToEETypePtr().CorElementType; + } + + private static Type ComputeUnderlyingType(Type enumType) + { + RuntimeImports.RhCorElementType corElementType = ComputeCorElementType(enumType); + switch (corElementType) + { + case RuntimeImports.RhCorElementType.ELEMENT_TYPE_BOOLEAN: + return CommonRuntimeTypes.Boolean; + case RuntimeImports.RhCorElementType.ELEMENT_TYPE_CHAR: + return CommonRuntimeTypes.Char; + case RuntimeImports.RhCorElementType.ELEMENT_TYPE_I1: + return CommonRuntimeTypes.SByte; + case RuntimeImports.RhCorElementType.ELEMENT_TYPE_U1: + return CommonRuntimeTypes.Byte; + case RuntimeImports.RhCorElementType.ELEMENT_TYPE_I2: + return CommonRuntimeTypes.Int16; + case RuntimeImports.RhCorElementType.ELEMENT_TYPE_U2: + return CommonRuntimeTypes.UInt16; + case RuntimeImports.RhCorElementType.ELEMENT_TYPE_I4: + return CommonRuntimeTypes.Int32; + case RuntimeImports.RhCorElementType.ELEMENT_TYPE_U4: + return CommonRuntimeTypes.UInt32; + case RuntimeImports.RhCorElementType.ELEMENT_TYPE_I8: + return CommonRuntimeTypes.Int64; + case RuntimeImports.RhCorElementType.ELEMENT_TYPE_U8: + return CommonRuntimeTypes.UInt64; + default: + throw new NotSupportedException(); + } + } + + // + // Sort comparer for NamesAndValues + // + private sealed class NamesAndValueComparer : IComparer<KeyValuePair<string, ulong>> + { + public int Compare(KeyValuePair<string, ulong> kv1, KeyValuePair<string, ulong> kv2) + { + ulong x = kv1.Value; + ulong y = kv2.Value; + if (x < y) + return -1; + else if (x > y) + return 1; + else + return 0; + } + + public static IComparer<KeyValuePair<string, ulong>> Default = new NamesAndValueComparer(); + } } } - diff --git a/src/System.Private.CoreLib/src/Resources/Strings.resx b/src/System.Private.CoreLib/src/Resources/Strings.resx index d43a1ede2..53a8ed147 100644 --- a/src/System.Private.CoreLib/src/Resources/Strings.resx +++ b/src/System.Private.CoreLib/src/Resources/Strings.resx @@ -2446,4 +2446,7 @@ <data name="Serialization_DelegatesNotSupported" xml:space="preserve"> <value>Serializing delegates is not supported on this platform.</value> </data> -</root>
\ No newline at end of file + <data name="Arg_OpenType" xml:space="preserve"> + <value>Cannot create an instance of {0} as it is an open type.</value> + </data> +</root> diff --git a/src/System.Private.CoreLib/src/System/Decimal.DecCalc.cs b/src/System.Private.CoreLib/src/System/Decimal.DecCalc.cs index e2267de5e..27844daf6 100644 --- a/src/System.Private.CoreLib/src/System/Decimal.DecCalc.cs +++ b/src/System.Private.CoreLib/src/System/Decimal.DecCalc.cs @@ -15,38 +15,38 @@ namespace System // Low level accessors used by a DecCalc and formatting internal uint High { - get { return hi; } - set { hi = value; } + get { return uhi; } + set { uhi = value; } } internal uint Low { - get { return lo; } - set { lo = value; } + get { return ulo; } + set { ulo = value; } } internal uint Mid { - get { return mid; } - set { mid = value; } + get { return umid; } + set { umid = value; } } internal bool Sign { - get { return (flags & SignMask) != 0; } - set { flags = (flags & ~SignMask) | (value ? SignMask : 0); } + get { return (uflags & SignMask) != 0; } + set { uflags = (uflags & ~SignMask) | (value ? SignMask : 0); } } internal int Scale { - get { return (int)((flags & ScaleMask) >> ScaleShift); } - set { flags = (flags & ~ScaleMask) | ((uint)value << ScaleShift); } + get { return (int)((uflags & ScaleMask) >> ScaleShift); } + set { uflags = (uflags & ~ScaleMask) | ((uint)value << ScaleShift); } } private ulong Low64 { - get { return ((ulong)mid << 32) | lo; } - set { mid = (uint)(value >> 32); lo = (uint)value; } + get { return ((ulong)umid << 32) | ulo; } + set { umid = (uint)(value >> 32); ulo = (uint)value; } } #region APIs need by number formatting. @@ -1190,7 +1190,7 @@ namespace System // private static Decimal Abs(Decimal d) { - return new Decimal((int)d.lo, (int)d.mid, (int)d.hi, (int)(d.flags & ~SignMask)); + return new Decimal(d.lo, d.mid, d.hi, (int)(d.uflags & ~SignMask)); } /*** @@ -1219,9 +1219,9 @@ namespace System if (input.Scale > 0) { - tmpNum[0] = input.lo; - tmpNum[1] = input.mid; - tmpNum[2] = input.hi; + tmpNum[0] = input.ulo; + tmpNum[1] = input.umid; + tmpNum[2] = input.uhi; scale = input.Scale; result.Sign = input.Sign; remainder = 0; @@ -1237,9 +1237,9 @@ namespace System scale -= MaxInt32Scale; } while (scale > 0); - result.lo = tmpNum[0]; - result.mid = tmpNum[1]; - result.hi = tmpNum[2]; + result.ulo = tmpNum[0]; + result.umid = tmpNum[1]; + result.uhi = tmpNum[2]; result.Scale = 0; return remainder; @@ -1255,7 +1255,7 @@ namespace System //********************************************************************** internal static void VarCyFromDec(ref Decimal pdecIn, out long pcyOut) { - if (!Decimal.IsValid(pdecIn.flags)) + if (!Decimal.IsValid(pdecIn.uflags)) throw new OverflowException(SR.Overflow_Currency); Split64 sdlTmp = default(Split64); @@ -2388,9 +2388,9 @@ namespace System scale = input.Scale - decimals; if (scale > 0) { - tmpNum[0] = input.lo; - tmpNum[1] = input.mid; - tmpNum[2] = input.hi; + tmpNum[0] = input.ulo; + tmpNum[1] = input.umid; + tmpNum[2] = input.uhi; result.Sign = input.Sign; remainder = sticky = 0; @@ -2416,9 +2416,9 @@ namespace System && ++tmpNum[1] == 0) ++tmpNum[2]; - result.lo = tmpNum[0]; - result.mid = tmpNum[1]; - result.hi = tmpNum[2]; + result.ulo = tmpNum[0]; + result.umid = tmpNum[1]; + result.uhi = tmpNum[2]; result.Scale = decimals; return; } @@ -2434,7 +2434,7 @@ namespace System // OleAut doesn't provide a VarDecMod. // In the operation x % y the sign of y does not matter. Result will have the sign of x. - d2.flags = (d2.flags & ~SignMask) | (d1.flags & SignMask); + d2.uflags = (d2.uflags & ~SignMask) | (d1.uflags & SignMask); // This piece of code is to work around the fact that Dividing a decimal with 28 digits number by decimal which causes @@ -2449,7 +2449,7 @@ namespace System if (d1 == 0) { // The sign of D1 will be wrong here. Fall through so that we still get a DivideByZeroException - d1.flags = (d1.flags & ~SignMask) | (d2.flags & SignMask); + d1.uflags = (d1.uflags & ~SignMask) | (d2.uflags & SignMask); } // Formula: d1 - (RoundTowardsZero(d1 / d2) * d2) @@ -2457,14 +2457,14 @@ namespace System Decimal multipliedResult = dividedResult * d2; Decimal result = d1 - multipliedResult; // See if the result has crossed 0 - if ((d1.flags & SignMask) != (result.flags & SignMask)) + if ((d1.uflags & SignMask) != (result.uflags & SignMask)) { if (NearNegativeZero <= result && result <= NearPositiveZero) { // Certain Remainder operations on decimals with 28 significant digits round // to [+-]0.000000000000000000000000001m instead of [+-]0m during the intermediate calculations. // 'zero' results just need their sign corrected. - result.flags = (result.flags & ~SignMask) | (d1.flags & SignMask); + result.uflags = (result.uflags & ~SignMask) | (d1.uflags & SignMask); } else { @@ -2487,17 +2487,17 @@ namespace System { UInt32 v; UInt32 sum; - v = value.lo; + v = value.ulo; sum = v + i; - value.lo = sum; + value.ulo = sum; if (sum < v || sum < i) { - v = value.mid; + v = value.umid; sum = v + 1; - value.mid = sum; + value.umid = sum; if (sum < v || sum < 1) { - value.hi = value.hi + 1; + value.uhi = value.uhi + 1; } } } @@ -2509,22 +2509,22 @@ namespace System { UInt32 remainder = 0; UInt64 n; - if (value.hi != 0) + if (value.uhi != 0) { - n = value.hi; - value.hi = (UInt32)(n / divisor); + n = value.uhi; + value.uhi = (UInt32)(n / divisor); remainder = (UInt32)(n % divisor); } - if (value.mid != 0 || remainder != 0) + if (value.umid != 0 || remainder != 0) { - n = ((UInt64)remainder << 32) | value.mid; - value.mid = (UInt32)(n / divisor); + n = ((UInt64)remainder << 32) | value.umid; + value.umid = (UInt32)(n / divisor); remainder = (UInt32)(n % divisor); } - if (value.lo != 0 || remainder != 0) + if (value.ulo != 0 || remainder != 0) { - n = ((UInt64)remainder << 32) | value.lo; - value.lo = (UInt32)(n / divisor); + n = ((UInt64)remainder << 32) | value.ulo; + value.ulo = (UInt32)(n / divisor); remainder = (UInt32)(n % divisor); } return remainder; @@ -2573,17 +2573,17 @@ namespace System internal static uint DecDivMod1E9(ref Decimal value) { return D32DivMod1E9(D32DivMod1E9(D32DivMod1E9(0, - ref value.hi), - ref value.mid), - ref value.lo); + ref value.uhi), + ref value.umid), + ref value.ulo); } internal static void DecAddInt32(ref Decimal value, uint i) { - if (D32AddCarry(ref value.lo, i)) + if (D32AddCarry(ref value.ulo, i)) { - if (D32AddCarry(ref value.mid, 1)) - D32AddCarry(ref value.hi, 1); + if (D32AddCarry(ref value.umid, 1)) + D32AddCarry(ref value.uhi, 1); } } @@ -2615,16 +2615,16 @@ namespace System private static void DecAdd(ref Decimal value, Decimal d) { - if (D32AddCarry(ref value.lo, d.Low)) + if (D32AddCarry(ref value.ulo, d.Low)) { - if (D32AddCarry(ref value.mid, 1)) - D32AddCarry(ref value.hi, 1); + if (D32AddCarry(ref value.umid, 1)) + D32AddCarry(ref value.uhi, 1); } - if (D32AddCarry(ref value.mid, d.Mid)) - D32AddCarry(ref value.hi, 1); + if (D32AddCarry(ref value.umid, d.Mid)) + D32AddCarry(ref value.uhi, 1); - D32AddCarry(ref value.hi, d.High); + D32AddCarry(ref value.uhi, d.High); } #endregion diff --git a/src/System.Private.CoreLib/src/System/Decimal.cs b/src/System.Private.CoreLib/src/System/Decimal.cs index b23fc204b..1532a0a13 100644 --- a/src/System.Private.CoreLib/src/System/Decimal.cs +++ b/src/System.Private.CoreLib/src/System/Decimal.cs @@ -52,7 +52,7 @@ namespace System // Decimal throws an OverflowException if the value is not within // the range of the Decimal type. [Serializable] - [StructLayout(LayoutKind.Sequential)] + [StructLayout(LayoutKind.Explicit)] public partial struct Decimal : IFormattable, IComparable, IConvertible, IComparable<Decimal>, IEquatable<Decimal>, IDeserializationCallback { // Sign mask for the flags field. A value of zero in this bit indicates a @@ -99,13 +99,27 @@ namespace System // and finally bit 31 indicates the sign of the Decimal value, 0 meaning // positive and 1 meaning negative. // - // NOTE: Do not change the order in which these fields are declared. The - // native methods in this class rely on this particular order. - private uint flags; // Do not rename (binary serialization) - private uint hi; // Do not rename (binary serialization) - private uint lo; // Do not rename (binary serialization) - private uint mid; // Do not rename (binary serialization) - + // NOTE: Do not change the offsets of these fields. This structure maps to the OleAut DECIMAL structure + // and can be passed as such in P/Invokes. + [FieldOffset(0)] + private int flags; // Do not rename (binary serialization) + [FieldOffset(4)] + private int hi; // Do not rename (binary serialization) + [FieldOffset(8)] + private int lo; // Do not rename (binary serialization) + [FieldOffset(12)] + private int mid; // Do not rename (binary serialization) + + // NOTE: This set of fields overlay the ones exposed to serialization (which have to be signed ints for serialization compat.) + // The code inside Decimal was ported from C++ and expect unsigned values. + [FieldOffset(0), NonSerialized] + private uint uflags; + [FieldOffset(4), NonSerialized] + private uint uhi; + [FieldOffset(8), NonSerialized] + private uint ulo; + [FieldOffset(12), NonSerialized] + private uint umid; // Constructs a zero Decimal. //public Decimal() { @@ -124,14 +138,14 @@ namespace System int value_copy = value; if (value_copy >= 0) { - flags = 0; + uflags = 0; } else { - flags = SignMask; + uflags = SignMask; value_copy = -value_copy; } - lo = (uint)value_copy; + lo = value_copy; mid = 0; hi = 0; } @@ -141,10 +155,10 @@ namespace System [CLSCompliant(false)] public Decimal(uint value) { - flags = 0; - lo = value; - mid = 0; - hi = 0; + uflags = 0; + ulo = value; + umid = 0; + uhi = 0; } // Constructs a Decimal from a long value. @@ -156,16 +170,16 @@ namespace System long value_copy = value; if (value_copy >= 0) { - flags = 0; + uflags = 0; } else { - flags = SignMask; + uflags = SignMask; value_copy = -value_copy; } - lo = (uint)value_copy; - mid = (uint)(value_copy >> 32); - hi = 0; + ulo = (uint)value_copy; + umid = (uint)(value_copy >> 32); + uhi = 0; } // Constructs a Decimal from an unsigned long value. @@ -173,10 +187,10 @@ namespace System [CLSCompliant(false)] public Decimal(ulong value) { - flags = 0; - lo = (uint)value; - mid = (uint)(value >> 32); - hi = 0; + uflags = 0; + ulo = (uint)value; + umid = (uint)(value >> 32); + uhi = 0; } // Constructs a Decimal from a float value. @@ -281,10 +295,10 @@ namespace System uint f = (uint)bits[3]; if (IsValid(f)) { - lo = (uint)bits[0]; - mid = (uint)bits[1]; - hi = (uint)bits[2]; - flags = f; + lo = bits[0]; + mid = bits[1]; + hi = bits[2]; + uflags = f; return; } } @@ -298,12 +312,12 @@ namespace System if (scale > 28) throw new ArgumentOutOfRangeException(nameof(scale), SR.ArgumentOutOfRange_DecimalScale); Contract.EndContractBlock(); - this.lo = (uint)lo; - this.mid = (uint)mid; - this.hi = (uint)hi; - flags = ((uint)scale) << 16; + this.lo = lo; + this.mid = mid; + this.hi = hi; + uflags = ((uint)scale) << 16; if (isNegative) - flags |= SignMask; + uflags |= SignMask; } void IDeserializationCallback.OnDeserialization(Object sender) @@ -325,10 +339,10 @@ namespace System { if ((flags & ~(SignMask | ScaleMask)) == 0 && (flags & ScaleMask) <= (28 << 16)) { - this.lo = (uint)lo; - this.mid = (uint)mid; - this.hi = (uint)hi; - this.flags = (uint)flags; + this.lo = lo; + this.mid = mid; + this.hi = hi; + this.flags = flags; return; } throw new ArgumentException(SR.Arg_DecBitCtor); @@ -340,7 +354,7 @@ namespace System // internal static Decimal Abs(Decimal d) { - return new Decimal((int)d.lo, (int)d.mid, (int)d.hi, (int)(d.flags & ~SignMask)); + return new Decimal(d.lo, d.mid, d.hi, (int)(d.uflags & ~SignMask)); } @@ -558,7 +572,7 @@ namespace System // public static int[] GetBits(Decimal d) { - return new int[] { (int)d.lo, (int)d.mid, (int)d.hi, (int)d.flags }; + return new int[] { d.lo, d.mid, d.hi, d.flags }; } // Returns the larger of two Decimal values. @@ -595,7 +609,7 @@ namespace System // public static Decimal Negate(Decimal d) { - return new Decimal((int)d.lo, (int)d.mid, (int)d.hi, (int)(d.flags ^ SignMask)); + return new Decimal(d.lo, d.mid, d.hi, (int)(d.uflags ^ SignMask)); } // Rounds a Decimal value to a given number of decimal places. The value @@ -733,7 +747,7 @@ namespace System if (d.Scale != 0) DecCalc.VarDecFix(ref d); if (d.hi == 0 && d.mid == 0) { - int i = (int)d.lo; + int i = d.lo; if (!d.Sign) { if (i >= 0) return i; @@ -754,9 +768,9 @@ namespace System public static long ToInt64(Decimal d) { if (d.Scale != 0) DecCalc.VarDecFix(ref d); - if (d.hi == 0) + if (d.uhi == 0) { - long l = d.lo | (long)(int)d.mid << 32; + long l = d.ulo | (long)(int)d.umid << 32; if (!d.Sign) { if (l >= 0) return l; @@ -798,10 +812,10 @@ namespace System public static uint ToUInt32(Decimal d) { if (d.Scale != 0) DecCalc.VarDecFix(ref d); - if (d.hi == 0 && d.mid == 0) + if (d.uhi == 0 && d.umid == 0) { - if (!d.Sign || d.lo == 0) - return d.lo; + if (!d.Sign || d.ulo == 0) + return d.ulo; } throw new OverflowException(SR.Overflow_UInt32); } @@ -814,9 +828,9 @@ namespace System public static ulong ToUInt64(Decimal d) { if (d.Scale != 0) DecCalc.VarDecFix(ref d); - if (d.hi == 0) + if (d.uhi == 0) { - ulong l = (ulong)d.lo | ((ulong)d.mid << 32); + ulong l = (ulong)d.ulo | ((ulong)d.umid << 32); if (!d.Sign || l == 0) return l; } diff --git a/src/System.Private.CoreLib/src/System/EETypePtr.cs b/src/System.Private.CoreLib/src/System/EETypePtr.cs index 23aaf31c3..fa5abb6b0 100644 --- a/src/System.Private.CoreLib/src/System/EETypePtr.cs +++ b/src/System.Private.CoreLib/src/System/EETypePtr.cs @@ -182,6 +182,10 @@ namespace System } } + /// <summary> + /// WARNING: Never call unless the EEType came from an instanced object. Nested enums can be open generics (typeof(Outer<>).NestedEnum) + /// and this helper has undefined behavior when passed such as a enum. + /// </summary> internal bool IsEnum { get diff --git a/src/System.Private.CoreLib/src/System/Enum.cs b/src/System.Private.CoreLib/src/System/Enum.cs index 7fe9e393f..7ee0c6980 100644 --- a/src/System.Private.CoreLib/src/System/Enum.cs +++ b/src/System.Private.CoreLib/src/System/Enum.cs @@ -141,16 +141,20 @@ namespace System if (enumType == null) throw new ArgumentNullException(nameof(enumType)); - EnumInfo enumInfo = GetEnumInfo(enumType); + if (!enumType.IsEnum) + throw new ArgumentException(SR.Arg_MustBeEnum, nameof(enumType)); if (value == null) throw new ArgumentNullException(nameof(value)); if (format == null) throw new ArgumentNullException(nameof(format)); - Contract.EndContractBlock(); - if (value.EETypePtr.IsEnum) + if (!enumType.IsRuntimeImplemented()) + throw new ArgumentException(SR.Arg_MustBeType, nameof(enumType)); + + EnumInfo enumInfo = GetEnumInfo(enumType); + if (value is Enum) { EETypePtr enumTypeEEType; if ((!enumType.TryGetEEType(out enumTypeEEType)) || enumTypeEEType != value.EETypePtr) @@ -493,6 +497,9 @@ namespace System // For desktop compatibility, do not bounce an incoming integer that's the wrong size. // Do a value-preserving cast of both it and the enum values and do a 64-bit compare. + if (!enumType.IsEnum) + throw new ArgumentException(SR.Arg_MustBeEnum); + EnumInfo enumInfo = GetEnumInfo(enumType); String nameOrNull = GetNameIfAny(enumInfo, rawValue); return nameOrNull; @@ -506,6 +513,9 @@ namespace System if (!enumType.IsRuntimeImplemented()) return enumType.GetEnumNames(); + if (!enumType.IsEnum) + throw new ArgumentException(SR.Arg_MustBeEnum); + KeyValuePair<String, ulong>[] namesAndValues = GetEnumInfo(enumType).NamesAndValues; String[] names = new String[namesAndValues.Length]; for (int i = 0; i < namesAndValues.Length; i++) @@ -518,46 +528,29 @@ namespace System if (enumType == null) throw new ArgumentNullException(nameof(enumType)); - RuntimeTypeHandle runtimeTypeHandle = enumType.TypeHandle; - EETypePtr eeType = runtimeTypeHandle.ToEETypePtr(); - if (!eeType.IsEnum) + if (!enumType.IsRuntimeImplemented()) + return enumType.GetEnumUnderlyingType(); + + if (!enumType.IsEnum) throw new ArgumentException(SR.Arg_MustBeEnum, nameof(enumType)); - switch (eeType.CorElementType) - { - case RuntimeImports.RhCorElementType.ELEMENT_TYPE_BOOLEAN: - return CommonRuntimeTypes.Boolean; - case RuntimeImports.RhCorElementType.ELEMENT_TYPE_CHAR: - return CommonRuntimeTypes.Char; - case RuntimeImports.RhCorElementType.ELEMENT_TYPE_I1: - return CommonRuntimeTypes.SByte; - case RuntimeImports.RhCorElementType.ELEMENT_TYPE_U1: - return CommonRuntimeTypes.Byte; - case RuntimeImports.RhCorElementType.ELEMENT_TYPE_I2: - return CommonRuntimeTypes.Int16; - case RuntimeImports.RhCorElementType.ELEMENT_TYPE_U2: - return CommonRuntimeTypes.UInt16; - case RuntimeImports.RhCorElementType.ELEMENT_TYPE_I4: - return CommonRuntimeTypes.Int32; - case RuntimeImports.RhCorElementType.ELEMENT_TYPE_U4: - return CommonRuntimeTypes.UInt32; - case RuntimeImports.RhCorElementType.ELEMENT_TYPE_I8: - return CommonRuntimeTypes.Int64; - case RuntimeImports.RhCorElementType.ELEMENT_TYPE_U8: - return CommonRuntimeTypes.UInt64; - default: - throw new ArgumentException(); - } + return GetEnumInfo(enumType).UnderlyingType; } public static Array GetValues(Type enumType) { if (enumType == null) throw new ArgumentNullException(nameof(enumType)); + + if (!enumType.IsRuntimeImplemented()) + return enumType.GetEnumValues(); + + if (!enumType.IsEnum) + throw new ArgumentException(SR.Arg_MustBeEnum); + Array values = GetEnumInfo(enumType).Values; int count = values.Length; - EETypePtr enumArrayType = enumType.MakeArrayType().TypeHandle.ToEETypePtr(); - Array result = RuntimeImports.RhNewArray(enumArrayType, count); + Array result = Array.CreateInstance(enumType, count); Array.CopyImplValueTypeArrayNoInnerGcRefs(values, 0, result, 0, count); return result; } @@ -603,6 +596,9 @@ namespace System if (value.EETypePtr == EETypePtr.EETypePtrOf<string>()) { + if (!enumType.IsEnum) + throw new ArgumentException(SR.Arg_MustBeEnum); + EnumInfo enumInfo = GetEnumInfo(enumType); foreach (KeyValuePair<String, ulong> kv in enumInfo.NamesAndValues) { @@ -623,20 +619,27 @@ namespace System } EnumInfo enumInfo = null; - if (value.EETypePtr.IsEnum) + if (value is Enum) { if (!ValueTypeMatchesEnumType(enumType, value)) throw new ArgumentException(SR.Format(SR.Arg_EnumAndObjectMustBeSameType, value.GetType(), enumType)); } else { + if (!enumType.IsEnum) + throw new ArgumentException(SR.Arg_MustBeEnum); + enumInfo = GetEnumInfo(enumType); if (!(enumInfo.UnderlyingType.TypeHandle.ToEETypePtr() == value.EETypePtr)) throw new ArgumentException(SR.Format(SR.Arg_EnumUnderlyingTypeAndObjectMustBeSameType, value.GetType(), enumInfo.UnderlyingType)); } if (enumInfo == null) + { + if (!enumType.IsEnum) + throw new ArgumentException(SR.Arg_MustBeEnum); enumInfo = GetEnumInfo(enumType); + } String nameOrNull = GetNameIfAny(enumInfo, rawValue); return nameOrNull != null; } @@ -701,13 +704,17 @@ namespace System if (enumType == null) throw new ArgumentNullException(nameof(enumType)); + if (!enumType.IsEnum) + throw new ArgumentException(SR.Arg_MustBeEnum, nameof(enumType)); + if (!enumType.IsRuntimeImplemented()) throw new ArgumentException(SR.Arg_MustBeType, nameof(enumType)); - EETypePtr enumEEType = enumType.TypeHandle.ToEETypePtr(); - if (!enumEEType.IsEnum) - throw new ArgumentException(SR.Arg_MustBeEnum, nameof(enumType)); + // Check for the unfortunate "typeof(Outer<>).InnerEnum" corner case. + if (enumType.ContainsGenericParameters) + throw new InvalidOperationException(SR.Format(SR.Arg_OpenType, enumType.ToString())); + EETypePtr enumEEType = enumType.TypeHandle.ToEETypePtr(); unsafe { byte* pValue = (byte*)&value; @@ -810,7 +817,7 @@ namespace System if (format == null || format.Length == 0) format = "G"; - EnumInfo enumInfo = GetEnumInfoIfAvailable(this.GetType()); + EnumInfo enumInfo = GetEnumInfo(this.GetType()); // Project N port note: If Reflection info isn't available, fallback to ToString() which will substitute a numeric value for the "correct" output. // This scenario has been hit frequently when throwing exceptions formatted with error strings containing enum substitations. @@ -833,25 +840,11 @@ namespace System return ToString(); } - // - // Note: this helper also checks if the enumType is in fact an Enum and throws an user-visible ArgumentException if it's not. - // private static EnumInfo GetEnumInfo(Type enumType) { - EnumInfo enumInfo = GetEnumInfoIfAvailable(enumType); - if (enumInfo == null) - throw RuntimeAugments.Callbacks.CreateMissingMetadataException(enumType); - return enumInfo; - } - - // - // Note: this helper also checks if the enumType is in fact an Enum and throws an user-visible ArgumentException if it's not. - // - private static EnumInfo GetEnumInfoIfAvailable(Type enumType) - { - RuntimeTypeHandle runtimeTypeHandle = enumType.TypeHandle; - if (!runtimeTypeHandle.ToEETypePtr().IsEnum) - throw new ArgumentException(SR.Arg_MustBeEnum); + Debug.Assert(enumType != null); + Debug.Assert(enumType.IsRuntimeImplemented()); + Debug.Assert(enumType.IsEnum); return ReflectionAugments.ReflectionCoreCallbacks.GetEnumInfo(enumType); } @@ -996,10 +989,14 @@ namespace System return false; } - EETypePtr enumEEType = enumType.TypeHandle.ToEETypePtr(); - if (!enumEEType.IsEnum) + if (!enumType.IsEnum) throw new ArgumentException(SR.Arg_MustBeEnum, nameof(enumType)); + // Check for the unfortunate "typeof(Outer<>).InnerEnum" corner case. + if (enumType.ContainsGenericParameters) + throw new InvalidOperationException(SR.Format(SR.Arg_OpenType, enumType.ToString())); + + EETypePtr enumEEType = enumType.TypeHandle.ToEETypePtr(); if (TryParseAsInteger(enumEEType, value, firstNonWhitespaceIndex, out result)) return true; @@ -1010,7 +1007,7 @@ namespace System } // Parse as string. Now (and only now) do we look for metadata information. - EnumInfo enumInfo = ReflectionAugments.ReflectionCoreCallbacks.GetEnumInfo(enumType); + EnumInfo enumInfo = GetEnumInfo(enumType); ulong v = 0; // Port note: The docs are silent on how multiple matches are resolved when doing case-insensitive parses. diff --git a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/PInvokeMarshal.Unix.cs b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/PInvokeMarshal.Unix.cs index 41dae2a3a..f9e07a395 100644 --- a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/PInvokeMarshal.Unix.cs +++ b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/PInvokeMarshal.Unix.cs @@ -18,7 +18,7 @@ namespace System.Runtime.InteropServices s_lastWin32Error = Interop.Sys.GetErrNo(); } - internal static void ClearLastWin32Error() + public static void ClearLastWin32Error() { Interop.Sys.ClearErrNo(); } diff --git a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/PInvokeMarshal.Windows.cs b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/PInvokeMarshal.Windows.cs index 999b516e2..3bb267361 100644 --- a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/PInvokeMarshal.Windows.cs +++ b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/PInvokeMarshal.Windows.cs @@ -38,7 +38,7 @@ namespace System.Runtime.InteropServices s_lastWin32Error = Interop.mincore.GetLastError(); } - internal static void ClearLastWin32Error() + public static void ClearLastWin32Error() { Interop.mincore.SetLastError(0); } diff --git a/src/System.Private.Interop/src/Shared/McgMarshal.cs b/src/System.Private.Interop/src/Shared/McgMarshal.cs index 11315c7a4..9577a33d2 100644 --- a/src/System.Private.Interop/src/Shared/McgMarshal.cs +++ b/src/System.Private.Interop/src/Shared/McgMarshal.cs @@ -49,6 +49,11 @@ namespace System.Runtime.InteropServices PInvokeMarshal.SaveLastWin32Error(); } + public static void ClearLastWin32Error() + { + PInvokeMarshal.ClearLastWin32Error(); + } + public static bool GuidEquals(ref Guid left, ref Guid right) { return InteropExtensions.GuidEquals(ref left, ref right); diff --git a/src/System.Private.Reflection.Core/src/System.Private.Reflection.Core.csproj b/src/System.Private.Reflection.Core/src/System.Private.Reflection.Core.csproj index ab016ad41..30f3206ea 100644 --- a/src/System.Private.Reflection.Core/src/System.Private.Reflection.Core.csproj +++ b/src/System.Private.Reflection.Core/src/System.Private.Reflection.Core.csproj @@ -111,7 +111,6 @@ <Compile Include="System\Reflection\Runtime\General\Helpers.NativeFormat.cs" /> <Compile Include="System\Reflection\Runtime\General\ReflectionCoreCallbacksImplementation.cs" /> <Compile Include="System\Reflection\Runtime\General\Dispensers.cs" /> - <Compile Include="System\Reflection\Runtime\General\EnumInfoImplementation.cs" /> <Compile Include="System\Reflection\Runtime\General\Helpers.cs" /> <Compile Include="System\Reflection\Runtime\General\IRuntimeMemberInfoWithNoMetadataDefinition.cs" /> <Compile Include="System\Reflection\Runtime\General\LegacyCustomAttributeApis.cs" /> diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/EnumInfoImplementation.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/EnumInfoImplementation.cs deleted file mode 100644 index 1f23f0bed..000000000 --- a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/EnumInfoImplementation.cs +++ /dev/null @@ -1,83 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System.Collections.Generic; -using EnumInfo = Internal.Runtime.Augments.EnumInfo; - -namespace System.Reflection.Runtime.General -{ - internal sealed class EnumInfoImplementation : EnumInfo - { - internal EnumInfoImplementation(Type enumType) - { - _underlyingType = Enum.GetUnderlyingType(enumType); - - FieldInfo[] fields = enumType.GetFields(BindingFlags.Public | BindingFlags.Static); - int numValues = fields.Length; - object[] rawValues = new object[numValues]; - KeyValuePair<string, ulong>[] namesAndValues = new KeyValuePair<string, ulong>[numValues]; - for (int i = 0; i < numValues; i++) - { - FieldInfo field = fields[i]; - object rawValue = field.GetRawConstantValue(); - rawValues[i] = rawValue; - - ulong rawUnboxedValue; - if (rawValue is ulong) - { - rawUnboxedValue = (ulong)rawValue; - } - else - { - // This conversion is this way for compatibility: do a value-preseving cast to long - then store (and compare) as ulong. This affects - // the order in which the Enum apis return names and values. - rawUnboxedValue = (ulong)(((IConvertible)rawValue).ToInt64(null)); - } - namesAndValues[i] = new KeyValuePair<string, ulong>(field.Name, rawUnboxedValue); - } - - Array.Sort(keys: namesAndValues, items: rawValues, comparer: NamesAndValueComparer.Default); - _namesAndValues = namesAndValues; - - // Create the unboxed version of values for the Values property to return. (We didn't do this earlier because - // declaring "rawValues" as "Array" would prevent us from using the generic overload of Array.Sort()). - // - // The array element type is the underlying type, not the enum type. (The enum type could be an open generic.) - _values = Array.CreateInstance(_underlyingType, numValues); - Array.Copy(rawValues, _values, numValues); - - _hasFlagsAttribute = enumType.IsDefined(typeof(FlagsAttribute), inherit: false); - } - - public sealed override Type UnderlyingType => _underlyingType; - public sealed override Array Values => _values; - public sealed override KeyValuePair<string, ulong>[] NamesAndValues => _namesAndValues; - public sealed override bool HasFlagsAttribute => _hasFlagsAttribute; - - // - // Sort comparer for NamesAndValues - // - private sealed class NamesAndValueComparer : IComparer<KeyValuePair<string, ulong>> - { - public int Compare(KeyValuePair<string, ulong> kv1, KeyValuePair<string, ulong> kv2) - { - ulong x = kv1.Value; - ulong y = kv2.Value; - if (x < y) - return -1; - else if (x > y) - return 1; - else - return 0; - } - - public static IComparer<KeyValuePair<string, ulong>> Default = new NamesAndValueComparer(); - } - - private readonly Type _underlyingType; - private readonly Array _values; - private readonly KeyValuePair<string, ulong>[] _namesAndValues; - private readonly bool _hasFlagsAttribute; - } -} diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeInfo.TypeComponentsCache.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeInfo.TypeComponentsCache.cs index 1ca52f5ef..9634b167e 100644 --- a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeInfo.TypeComponentsCache.cs +++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeInfo.TypeComponentsCache.cs @@ -74,7 +74,7 @@ namespace System.Reflection.Runtime.TypeInfos return Unsafe.As<QueriedMemberList<M>>(result); } - public EnumInfo EnumInfo => _lazyEnumInfo ?? (_lazyEnumInfo = new EnumInfoImplementation(_type)); + public EnumInfo EnumInfo => _lazyEnumInfo ?? (_lazyEnumInfo = new EnumInfo(_type)); private static object[] CreatePerNameQueryCaches(RuntimeTypeInfo type, bool ignoreCase) { diff --git a/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/DebugFuncEval.cs b/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/DebugFuncEval.cs index 758af0682..cdf1c7b0a 100644 --- a/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/DebugFuncEval.cs +++ b/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/DebugFuncEval.cs @@ -28,7 +28,18 @@ namespace Internal.Runtime.TypeLoader { for (int i = 0; i < param.parameterValues.Length; i++) { - arguments.SetVar<int>(i + 1, param.parameterValues[i]); + unsafe + { + IntPtr input = arguments.GetAddressOfVarData(i + 1); + byte* pInput = (byte*)input; + fixed(byte* pParam = param.parameterValues[i]) + { + for (int j = 0; j < param.parameterValues[i].Length; j++) + { + pInput[j] = pParam[j]; + } + } + } } // Obtain the target method address from the runtime @@ -92,8 +103,7 @@ namespace Internal.Runtime.TypeLoader struct TypesAndValues { public RuntimeTypeHandle[] types; - // TODO: We should support arguments of *any* type - public int[] parameterValues; + public byte[][] parameterValues; } private static void HighLevelDebugFuncEvalHelper() @@ -123,7 +133,7 @@ namespace Internal.Runtime.TypeLoader uint trash; uint parameterCount; - uint parameterValue; + uint parameterValueSize; uint eeTypeCount; ulong eeType; uint offset = 0; @@ -132,24 +142,32 @@ namespace Internal.Runtime.TypeLoader offset = reader.DecodeUnsigned(offset, out trash); // The VertexSequence always generate a length, I don't really need it. offset = reader.DecodeUnsigned(offset, out parameterCount); - typesAndValues.parameterValues = new int[parameterCount]; + typesAndValues.parameterValues = new byte[parameterCount][]; for (int i = 0; i < parameterCount; i++) { - offset = reader.DecodeUnsigned(offset, out parameterValue); - typesAndValues.parameterValues[i] = (int)parameterValue; + offset = reader.DecodeUnsigned(offset, out parameterValueSize); + byte[] parameterValue = new byte[parameterValueSize]; + for (int j = 0; j < parameterValueSize; j++) + { + uint parameterByte; + offset = reader.DecodeUnsigned(offset, out parameterByte); + parameterValue[j] = (byte)parameterByte; + } + typesAndValues.parameterValues[i] = parameterValue; } - offset = reader.DecodeUnsigned(offset, out eeTypeCount); + offset = reader.DecodeUnsigned(offset, out eeTypeCount); + ulong[] debuggerPreparedExternalReferences = new ulong[eeTypeCount]; for (int i = 0; i < eeTypeCount; i++) { - // TODO: Stuff these eeType values into the external reference table offset = reader.DecodeUnsignedLong(offset, out eeType); + debuggerPreparedExternalReferences[i] = eeType; } TypeSystemContext typeSystemContext = TypeSystemContextFactory.Create(); bool hasThis; TypeDesc[] parameters; bool[] parametersWithGenericDependentLayout; - bool result = TypeLoaderEnvironment.Instance.GetCallingConverterDataFromMethodSignature_NativeLayout_Debugger(typeSystemContext, RuntimeSignature.CreateFromNativeLayoutSignatureForDebugger(offset), Instantiation.Empty, Instantiation.Empty, out hasThis, out parameters, out parametersWithGenericDependentLayout, reader); + bool result = TypeLoaderEnvironment.Instance.GetCallingConverterDataFromMethodSignature_NativeLayout_Debugger(typeSystemContext, RuntimeSignature.CreateFromNativeLayoutSignatureForDebugger(offset), Instantiation.Empty, Instantiation.Empty, out hasThis, out parameters, out parametersWithGenericDependentLayout, reader, debuggerPreparedExternalReferences); typesAndValues.types = new RuntimeTypeHandle[parameters.Length]; @@ -191,7 +209,7 @@ namespace Internal.Runtime.TypeLoader LocalVariableType[] argumentTypes = new LocalVariableType[parameters.Length]; for (int i = 0; i < parameters.Length; i++) { - // TODO: What these false really means? Need to make sure our format contains those information + // TODO, FuncEval, what these false really means? Need to make sure our format contains those information argumentTypes[i] = new LocalVariableType(typesAndValues.types[i], false, false); } diff --git a/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/ExternalReferencesTable.cs b/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/ExternalReferencesTable.cs index 53c878cb1..6fd8a1dc4 100644 --- a/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/ExternalReferencesTable.cs +++ b/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/ExternalReferencesTable.cs @@ -17,35 +17,34 @@ namespace Internal.Runtime.TypeLoader private IntPtr _elements; private uint _elementsCount; private TypeManagerHandle _moduleHandle; - private bool isDebuggerPrepared; + private ulong[] debuggerPreparedExternalReferences; - public bool IsInitialized() { return isDebuggerPrepared || !_moduleHandle.IsNull; } + public bool IsInitialized() { return (debuggerPreparedExternalReferences != null) || !_moduleHandle.IsNull; } private unsafe bool Initialize(NativeFormatModuleInfo module, ReflectionMapBlob blobId) { - if (module == null) - { - isDebuggerPrepared = true; - } - else + _moduleHandle = module.Handle; + + byte* pBlob; + uint cbBlob; + if (!module.TryFindBlob(blobId, out pBlob, out cbBlob)) { - _moduleHandle = module.Handle; - - byte* pBlob; - uint cbBlob; - if (!module.TryFindBlob(blobId, out pBlob, out cbBlob)) - { - _elements = IntPtr.Zero; - _elementsCount = 0; - return false; - } - - _elements = (IntPtr)pBlob; - _elementsCount = (uint)(cbBlob / sizeof(TableElement)); + _elements = IntPtr.Zero; + _elementsCount = 0; + return false; } + + _elements = (IntPtr)pBlob; + _elementsCount = (uint)(cbBlob / sizeof(TableElement)); + return true; } + public void InitializeDebuggerReference(ulong[] debuggerPreparedExternalReferences) + { + this.debuggerPreparedExternalReferences = debuggerPreparedExternalReferences; + } + /// <summary> /// Initialize ExternalReferencesTable using the NativeReferences metadata blob on a given module. /// </summary> @@ -140,12 +139,14 @@ namespace Internal.Runtime.TypeLoader public RuntimeTypeHandle GetRuntimeTypeHandleFromIndex(uint index) { - if (isDebuggerPrepared) + if (this.debuggerPreparedExternalReferences == null) { - return typeof(int).TypeHandle; + return RuntimeAugments.CreateRuntimeTypeHandle(GetIntPtrFromIndex(index)); } - - return RuntimeAugments.CreateRuntimeTypeHandle(GetIntPtrFromIndex(index)); + else + { + return RuntimeAugments.CreateRuntimeTypeHandle((IntPtr)this.debuggerPreparedExternalReferences[index]); + } } public IntPtr GetGenericDictionaryFromIndex(uint index) diff --git a/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/NativeLayoutInfoLoadContext.cs b/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/NativeLayoutInfoLoadContext.cs index 78f29bfa5..a1fe56fba 100644 --- a/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/NativeLayoutInfoLoadContext.cs +++ b/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/NativeLayoutInfoLoadContext.cs @@ -29,6 +29,7 @@ namespace Internal.Runtime.TypeLoader private ExternalReferencesTable _externalReferencesLookup; public Instantiation _typeArgumentHandles; public Instantiation _methodArgumentHandles; + public ulong[] _debuggerPreparedExternalReferences; private TypeDesc GetInstantiationType(ref NativeParser parser, uint arity) { @@ -66,8 +67,15 @@ namespace Internal.Runtime.TypeLoader { if (!_externalReferencesLookup.IsInitialized()) { - bool success = _externalReferencesLookup.InitializeNativeReferences(_module); - Debug.Assert(success); + if (this._debuggerPreparedExternalReferences == null) + { + bool success = _externalReferencesLookup.InitializeNativeReferences(_module); + Debug.Assert(success); + } + else + { + _externalReferencesLookup.InitializeDebuggerReference(this._debuggerPreparedExternalReferences); + } } } diff --git a/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.SignatureParsing.cs b/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.SignatureParsing.cs index 3dcdb8b92..c7972fdac 100644 --- a/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.SignatureParsing.cs +++ b/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.SignatureParsing.cs @@ -275,15 +275,15 @@ namespace Internal.Runtime.TypeLoader internal bool GetCallingConverterDataFromMethodSignature_NativeLayout(TypeSystemContext context, RuntimeSignature methodSig, Instantiation typeInstantiation, Instantiation methodInstantiation, out bool hasThis, out TypeDesc[] parameters, out bool[] parametersWithGenericDependentLayout) { - return GetCallingConverterDataFromMethodSignature_NativeLayout_Common(context, methodSig, typeInstantiation, methodInstantiation, out hasThis, out parameters, out parametersWithGenericDependentLayout, null); + return GetCallingConverterDataFromMethodSignature_NativeLayout_Common(context, methodSig, typeInstantiation, methodInstantiation, out hasThis, out parameters, out parametersWithGenericDependentLayout, null, null); } - internal bool GetCallingConverterDataFromMethodSignature_NativeLayout_Debugger(TypeSystemContext context, RuntimeSignature methodSig, Instantiation typeInstantiation, Instantiation methodInstantiation, out bool hasThis, out TypeDesc[] parameters, out bool[] parametersWithGenericDependentLayout, NativeReader nativeReader) + internal bool GetCallingConverterDataFromMethodSignature_NativeLayout_Debugger(TypeSystemContext context, RuntimeSignature methodSig, Instantiation typeInstantiation, Instantiation methodInstantiation, out bool hasThis, out TypeDesc[] parameters, out bool[] parametersWithGenericDependentLayout, NativeReader nativeReader, ulong[] debuggerPreparedExternalReferences) { - return GetCallingConverterDataFromMethodSignature_NativeLayout_Common(context, methodSig, typeInstantiation, methodInstantiation, out hasThis, out parameters, out parametersWithGenericDependentLayout, nativeReader); + return GetCallingConverterDataFromMethodSignature_NativeLayout_Common(context, methodSig, typeInstantiation, methodInstantiation, out hasThis, out parameters, out parametersWithGenericDependentLayout, nativeReader, debuggerPreparedExternalReferences); } - internal bool GetCallingConverterDataFromMethodSignature_NativeLayout_Common(TypeSystemContext context, RuntimeSignature methodSig, Instantiation typeInstantiation, Instantiation methodInstantiation, out bool hasThis, out TypeDesc[] parameters, out bool[] parametersWithGenericDependentLayout, NativeReader nativeReader) + internal bool GetCallingConverterDataFromMethodSignature_NativeLayout_Common(TypeSystemContext context, RuntimeSignature methodSig, Instantiation typeInstantiation, Instantiation methodInstantiation, out bool hasThis, out TypeDesc[] parameters, out bool[] parametersWithGenericDependentLayout, NativeReader nativeReader, ulong[] debuggerPreparedExternalReferences) { bool isNotDebuggerCall = nativeReader == null; hasThis = false; @@ -295,6 +295,7 @@ namespace Internal.Runtime.TypeLoader nativeLayoutContext._typeSystemContext = context; nativeLayoutContext._typeArgumentHandles = typeInstantiation; nativeLayoutContext._methodArgumentHandles = methodInstantiation; + nativeLayoutContext._debuggerPreparedExternalReferences = debuggerPreparedExternalReferences; NativeReader reader = isNotDebuggerCall ? GetNativeLayoutInfoReader(methodSig) : nativeReader; NativeFormatModuleInfo module = isNotDebuggerCall ? ModuleList.Instance.GetModuleInfoByHandle(new TypeManagerHandle(methodSig.ModuleHandle)) : null; |