Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/corert.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Kotas <jkotas@microsoft.com>2017-06-10 01:57:53 +0300
committerGitHub <noreply@github.com>2017-06-10 01:57:53 +0300
commit1c9d5697bfecd4274b08b163d570a9a21832ba4b (patch)
tree7111a5f54cc53a71ba2f804b5acbf47624131083
parent2928e63d8ebd62146c6e94dc3e258c59e598b2c9 (diff)
parent80791e9aaa9b5a481534cde52c77fb8061af674e (diff)
Merge pull request #3849 from dotnet/nmirror
Merge nmirror to master
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/UtcNodeFactory.cs19
-rw-r--r--src/Native/Runtime/DebuggerHook.cpp6
-rw-r--r--src/Native/Runtime/StackFrameIterator.cpp2
-rw-r--r--src/System.Private.CoreLib/src/Internal/Runtime/Augments/EnumInfo.cs140
-rw-r--r--src/System.Private.CoreLib/src/Resources/Strings.resx5
-rw-r--r--src/System.Private.CoreLib/src/System/Decimal.DecCalc.cs112
-rw-r--r--src/System.Private.CoreLib/src/System/Decimal.cs110
-rw-r--r--src/System.Private.CoreLib/src/System/EETypePtr.cs4
-rw-r--r--src/System.Private.CoreLib/src/System/Enum.cs113
-rw-r--r--src/System.Private.CoreLib/src/System/Runtime/InteropServices/PInvokeMarshal.Unix.cs2
-rw-r--r--src/System.Private.CoreLib/src/System/Runtime/InteropServices/PInvokeMarshal.Windows.cs2
-rw-r--r--src/System.Private.Interop/src/Shared/McgMarshal.cs5
-rw-r--r--src/System.Private.Reflection.Core/src/System.Private.Reflection.Core.csproj1
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/EnumInfoImplementation.cs83
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeInfo.TypeComponentsCache.cs2
-rw-r--r--src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/DebugFuncEval.cs40
-rw-r--r--src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/ExternalReferencesTable.cs49
-rw-r--r--src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/NativeLayoutInfoLoadContext.cs12
-rw-r--r--src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.SignatureParsing.cs9
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;