Skip to content

Commit 1ea4166

Browse files
authored
Remove decimal alignment quirk from the type loader (#38603)
System.Decimal fields did not match Win32 DECIMAL type for historic reasons. It required type loader to have a quirk to artificially inflate System.Decimal alignment to match the alignment of Win32 DECIMAL type to make interop work well. This change is fixing the System.Decimal fields to match Win32 DECIMAL type and removing the quirk from the type loader since it does not belong there. The downsides are: - Slightly lower code quality on 32-bit platforms. 32-bit platforms are not our high performance targets anymore. - Explicit implementation of ISerializable is required on System.Decimal for binary serialization compatibility. Fixes #38390
1 parent c8b3106 commit 1ea4166

5 files changed

Lines changed: 111 additions & 140 deletions

File tree

src/coreclr/src/vm/classnames.h

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -32,23 +32,12 @@
3232
#define g_ObjectModelAsmName "System.ObjectModel"
3333
#define g_ColorClassName "System.Drawing.Color"
3434
#define g_ColorTranslatorClassName "System.Drawing.ColorTranslator"
35-
#define g_SystemUriClassName "System.Uri"
36-
#define g_INotifyCollectionChangedName "System.Collections.Specialized.INotifyCollectionChanged"
37-
#define g_NotifyCollectionChangedEventHandlerName "System.Collections.Specialized.NotifyCollectionChangedEventHandler"
38-
#define g_NotifyCollectionChangedEventArgsName "System.Collections.Specialized.NotifyCollectionChangedEventArgs"
39-
#define g_NotifyCollectionChangedEventArgsMarshalerName "System.Runtime.InteropServices.WindowsRuntime.NotifyCollectionChangedEventArgsMarshaler"
40-
#define g_INotifyPropertyChangedName "System.ComponentModel.INotifyPropertyChanged"
41-
#define g_PropertyChangedEventHandlerName "System.ComponentModel.PropertyChangedEventHandler"
42-
#define g_PropertyChangedEventArgsName "System.ComponentModel.PropertyChangedEventArgs"
43-
#define g_ICommandName "System.Windows.Input.ICommand"
4435
#define g_ComObjectName "__ComObject"
4536
#endif // FEATURE_COMINTEROP
4637

47-
4838
#define g_DateClassName "System.DateTime"
4939
#define g_DateTimeOffsetClassName "System.DateTimeOffset"
5040
#define g_DecimalClassName "System.Decimal"
51-
#define g_DecimalName "Decimal"
5241

5342
#define g_Vector64ClassName "System.Runtime.Intrinsics.Vector64`1"
5443
#define g_Vector64Name "Vector64`1"
@@ -103,7 +92,6 @@
10392
#define g_StringBufferName "StringBuilder"
10493
#define g_StringClassName "System.String"
10594
#define g_StringName "String"
106-
#define g_SharedStaticsClassName "System.SharedStatics"
10795

10896
#define g_ThreadClassName "System.Threading.Thread"
10997
#define g_TypeClassName "System.Type"

src/coreclr/src/vm/methodtablebuilder.cpp

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -9724,23 +9724,6 @@ void MethodTableBuilder::CheckForSystemTypes()
97249724
pMT->SetInternalCorElementType (ELEMENT_TYPE_I);
97259725
}
97269726
#endif
9727-
#if defined(ALIGN_ACCESS) || defined(FEATURE_64BIT_ALIGNMENT)
9728-
else if (strcmp(name, g_DecimalName) == 0)
9729-
{
9730-
// This is required because native layout of System.Decimal causes it to be aligned
9731-
// differently to the layout of the native DECIMAL structure, which will cause
9732-
// data misalignent exceptions if Decimal is embedded in another type.
9733-
9734-
EEClassLayoutInfo* pLayout = pClass->GetLayoutInfo();
9735-
pLayout->m_ManagedLargestAlignmentRequirementOfAllMembers = sizeof(ULONGLONG);
9736-
9737-
#ifdef FEATURE_64BIT_ALIGNMENT
9738-
// Also need to mark the type so it will be allocated on a 64-bit boundary for
9739-
// platforms that won't do this naturally.
9740-
SetAlign8Candidate();
9741-
#endif
9742-
}
9743-
#endif // ALIGN_ACCESS || FEATURE_64BIT_ALIGNMENT
97449727
}
97459728
else
97469729
{

src/libraries/System.Private.CoreLib/src/System/Decimal.DecCalc.cs

Lines changed: 28 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -14,19 +14,15 @@ namespace System
1414
public partial struct Decimal
1515
{
1616
// Low level accessors used by a DecCalc and formatting
17-
internal uint High => (uint)hi;
18-
internal uint Low => (uint)lo;
19-
internal uint Mid => (uint)mid;
17+
internal uint High => _hi32;
18+
internal uint Low => (uint)_lo64;
19+
internal uint Mid => (uint)(_lo64 >> 32);
2020

21-
internal bool IsNegative => flags < 0;
21+
internal bool IsNegative => _flags < 0;
2222

23-
internal int Scale => (byte)(flags >> ScaleShift);
23+
internal int Scale => (byte)(_flags >> ScaleShift);
2424

25-
#if BIGENDIAN
26-
private ulong Low64 => ((ulong)Mid << 32) | Low;
27-
#else
28-
private ulong Low64 => Unsafe.As<int, ulong>(ref Unsafe.AsRef(in lo));
29-
#endif
25+
private ulong Low64 => _lo64;
3026

3127
private static ref DecCalc AsMutable(ref decimal d) => ref Unsafe.As<decimal, DecCalc>(ref d);
3228

@@ -50,16 +46,23 @@ private struct DecCalc
5046
private uint uflags;
5147
[FieldOffset(4)]
5248
private uint uhi;
49+
#if BIGENDIAN
50+
[FieldOffset(8)]
51+
private uint umid;
52+
[FieldOffset(12)]
53+
private uint ulo;
54+
#else
5355
[FieldOffset(8)]
5456
private uint ulo;
5557
[FieldOffset(12)]
5658
private uint umid;
59+
#endif
5760

5861
/// <summary>
59-
/// The low and mid fields combined in little-endian order
62+
/// The low and mid fields combined
6063
/// </summary>
6164
[FieldOffset(8)]
62-
private ulong ulomidLE;
65+
private ulong ulomid;
6366

6467
private uint High
6568
{
@@ -85,13 +88,8 @@ private uint Mid
8588

8689
private ulong Low64
8790
{
88-
#if BIGENDIAN
89-
get { return ((ulong)umid << 32) | ulo; }
90-
set { umid = (uint)(value >> 32); ulo = (uint)value; }
91-
#else
92-
get => ulomidLE;
93-
set => ulomidLE = value;
94-
#endif
91+
get => ulomid;
92+
set => ulomid = value;
9593
}
9694

9795
private const uint SignMask = 0x80000000;
@@ -163,7 +161,7 @@ private static unsafe void DebugPoison<T>(ref T s) where T : unmanaged
163161
MemoryMarshal.AsBytes(MemoryMarshal.CreateSpan(ref s, 1)).Fill(0xCD);
164162
}
165163

166-
#region Decimal Math Helpers
164+
#region Decimal Math Helpers
167165

168166
private static unsafe uint GetExponent(float f)
169167
{
@@ -1249,26 +1247,26 @@ internal static long VarCyFromDec(ref DecCalc pdecIn)
12491247
/// </summary>
12501248
internal static int VarDecCmp(in decimal d1, in decimal d2)
12511249
{
1252-
if ((d2.Low | d2.Mid | d2.High) == 0)
1250+
if ((d2.Low64 | d2.High) == 0)
12531251
{
1254-
if ((d1.Low | d1.Mid | d1.High) == 0)
1252+
if ((d1.Low64 | d1.High) == 0)
12551253
return 0;
1256-
return (d1.flags >> 31) | 1;
1254+
return (d1._flags >> 31) | 1;
12571255
}
1258-
if ((d1.Low | d1.Mid | d1.High) == 0)
1259-
return -((d2.flags >> 31) | 1);
1256+
if ((d1.Low64 | d1.High) == 0)
1257+
return -((d2._flags >> 31) | 1);
12601258

1261-
int sign = (d1.flags >> 31) - (d2.flags >> 31);
1259+
int sign = (d1._flags >> 31) - (d2._flags >> 31);
12621260
if (sign != 0)
12631261
return sign;
12641262
return VarDecCmpSub(in d1, in d2);
12651263
}
12661264

12671265
private static int VarDecCmpSub(in decimal d1, in decimal d2)
12681266
{
1269-
int flags = d2.flags;
1267+
int flags = d2._flags;
12701268
int sign = (flags >> 31) | 1;
1271-
int scale = flags - d1.flags;
1269+
int scale = flags - d1._flags;
12721270

12731271
ulong low64 = d1.Low64;
12741272
uint high = d1.High;
@@ -1899,10 +1897,10 @@ internal static double VarR8FromDec(in decimal value)
18991897

19001898
internal static int GetHashCode(in decimal d)
19011899
{
1902-
if ((d.Low | d.Mid | d.High) == 0)
1900+
if ((d.Low64 | d.High) == 0)
19031901
return 0;
19041902

1905-
uint flags = (uint)d.flags;
1903+
uint flags = (uint)d._flags;
19061904
if ((flags & ScaleMask) == 0 || (d.Low & 1) != 0)
19071905
return (int)(flags ^ d.High ^ d.Mid ^ d.Low);
19081906

0 commit comments

Comments
 (0)