diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/CompilerServices/ClassConstructorRunner.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/CompilerServices/ClassConstructorRunner.cs index 21a52801cadc..8093c0f71ff1 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/CompilerServices/ClassConstructorRunner.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/CompilerServices/ClassConstructorRunner.cs @@ -52,13 +52,13 @@ private static unsafe object CheckStaticClassConstructionReturnThreadStaticBase( public static unsafe void EnsureClassConstructorRun(StaticClassConstructionContext* pContext) { IntPtr pfnCctor = pContext->cctorMethodAddress; - NoisyLog("EnsureClassConstructorRun, cctor={0}, thread={1}", pfnCctor, CurrentManagedThreadId); + NoisyLog("EnsureClassConstructorRun, context={0}, thread={1}", pContext, CurrentManagedThreadId); // If we were called from MRT, this check is redundant but harmless. This is in case someone within classlib // (cough, Reflection) needs to call this explicitly. - if (pContext->initialized == 1) + if (pfnCctor == 0) { - NoisyLog("Cctor already run, cctor={0}, thread={1}", pfnCctor, CurrentManagedThreadId); + NoisyLog("Cctor already run, context={0}, thread={1}", pContext, CurrentManagedThreadId); return; } @@ -68,22 +68,22 @@ public static unsafe void EnsureClassConstructorRun(StaticClassConstructionConte try { Lock cctorLock = cctors[cctorIndex].Lock; - if (DeadlockAwareAcquire(cctor, pfnCctor)) + if (DeadlockAwareAcquire(cctor, pContext)) { int currentManagedThreadId = CurrentManagedThreadId; try { - NoisyLog("Acquired cctor lock, cctor={0}, thread={1}", pfnCctor, currentManagedThreadId); + NoisyLog("Acquired cctor lock, context={0}, thread={1}", pContext, currentManagedThreadId); cctors[cctorIndex].HoldingThread = currentManagedThreadId; - if (pContext->initialized == 0) // Check again in case some thread raced us while we were acquiring the lock. + if (pContext->cctorMethodAddress != 0) // Check again in case some thread raced us while we were acquiring the lock. { TypeInitializationException priorException = cctors[cctorIndex].Exception; if (priorException != null) throw priorException; try { - NoisyLog("Calling cctor, cctor={0}, thread={1}", pfnCctor, currentManagedThreadId); + NoisyLog("Calling cctor, context={0}, thread={1}", pContext, currentManagedThreadId); ((delegate*)pfnCctor)(); @@ -94,9 +94,9 @@ public static unsafe void EnsureClassConstructorRun(StaticClassConstructionConte // still see uninitialized static fields on the class. Interlocked.MemoryBarrier(); - NoisyLog("Set type inited, cctor={0}, thread={1}", pfnCctor, currentManagedThreadId); + NoisyLog("Set type inited, context={0}, thread={1}", pContext, currentManagedThreadId); - pContext->initialized = 1; + pContext->cctorMethodAddress = 0; } catch (Exception e) { @@ -109,7 +109,7 @@ public static unsafe void EnsureClassConstructorRun(StaticClassConstructionConte finally { cctors[cctorIndex].HoldingThread = ManagedThreadIdNone; - NoisyLog("Releasing cctor lock, cctor={0}, thread={1}", pfnCctor, currentManagedThreadId); + NoisyLog("Releasing cctor lock, context={0}, thread={1}", pContext, currentManagedThreadId); cctorLock.Release(); } @@ -124,7 +124,7 @@ public static unsafe void EnsureClassConstructorRun(StaticClassConstructionConte { Cctor.Release(cctor); } - NoisyLog("EnsureClassConstructorRun complete, cctor={0}, thread={1}", pfnCctor, CurrentManagedThreadId); + NoisyLog("EnsureClassConstructorRun complete, context={0}, thread={1}", pContext, CurrentManagedThreadId); } //========================================================================================================= @@ -132,7 +132,7 @@ public static unsafe void EnsureClassConstructorRun(StaticClassConstructionConte // true - lock acquired. // false - deadlock detected. Lock not acquired. //========================================================================================================= - private static bool DeadlockAwareAcquire(CctorHandle cctor, IntPtr pfnCctor) + private static unsafe bool DeadlockAwareAcquire(CctorHandle cctor, StaticClassConstructionContext* pContext) { const int WaitIntervalSeedInMS = 1; // seed with 1ms and double every time through the loop const int WaitIntervalLimitInMS = WaitIntervalSeedInMS << 7; // limit of 128ms @@ -181,8 +181,8 @@ private static bool DeadlockAwareAcquire(CctorHandle cctor, IntPtr pfnCctor) if (holdingThread == currentManagedThreadId) { // Deadlock detected. We will break the guarantee and return without running the .cctor. - DebugLog("A class constructor was skipped due to class constructor cycle. cctor={0}, thread={1}", - pfnCctor, currentManagedThreadId); + DebugLog("A class constructor was skipped due to class constructor cycle. context={0}, thread={1}", + pContext, currentManagedThreadId); // We are maintaining an invariant that the BlockingRecords never show a cycle because, // before we add a record, we first check for a cycle. As a result, once we've said @@ -223,7 +223,7 @@ private static bool DeadlockAwareAcquire(CctorHandle cctor, IntPtr pfnCctor) // respect to other updates to the BlockingRecords. if (unmarkCookie == -1) { - NoisyLog("Mark thread blocked, cctor={0}, thread={1}", pfnCctor, currentManagedThreadId); + NoisyLog("Mark thread blocked, context={0}, thread={1}", pContext, currentManagedThreadId); unmarkCookie = BlockingRecord.MarkThreadAsBlocked(currentManagedThreadId, cctor); } @@ -241,7 +241,7 @@ private static bool DeadlockAwareAcquire(CctorHandle cctor, IntPtr pfnCctor) { if (unmarkCookie != -1) { - NoisyLog("Unmark thread blocked, cctor={0}, thread={1}", pfnCctor, currentManagedThreadId); + NoisyLog("Unmark thread blocked, context={0}, thread={1}", pContext, currentManagedThreadId); BlockingRecord.UnmarkThreadAsBlocked(unmarkCookie); } } @@ -493,22 +493,22 @@ internal static void Initialize() } [Conditional("ENABLE_NOISY_CCTOR_LOG")] - private static void NoisyLog(string format, IntPtr cctorMethod, int threadId) + private static unsafe void NoisyLog(string format, StaticClassConstructionContext* pContext, int threadId) { // We cannot utilize any of the typical number formatting code because it triggers globalization code to run // and this cctor code is layered below globalization. #if DEBUG - Debug.WriteLine(format, ToHexString(cctorMethod), ToHexString(threadId)); + Debug.WriteLine(format, ToHexString((IntPtr)pContext), ToHexString(threadId)); #endif // DEBUG } [Conditional("DEBUG")] - private static void DebugLog(string format, IntPtr cctorMethod, int threadId) + private static unsafe void DebugLog(string format, StaticClassConstructionContext* pContext, int threadId) { // We cannot utilize any of the typical number formatting code because it triggers globalization code to run // and this cctor code is layered below globalization. #if DEBUG - Debug.WriteLine(format, ToHexString(cctorMethod), ToHexString(threadId)); + Debug.WriteLine(format, ToHexString((IntPtr)pContext), ToHexString(threadId)); #endif } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/CompilerServices/StaticClassConstructionContext.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/CompilerServices/StaticClassConstructionContext.cs index 455cc5ed0145..a07e6e9bbc21 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/CompilerServices/StaticClassConstructionContext.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/CompilerServices/StaticClassConstructionContext.cs @@ -8,23 +8,14 @@ namespace System.Runtime.CompilerServices { // This structure is used to pass context about a type's static class construction state from the runtime - // to the classlibrary via the CheckStaticClassConstruction callback. The runtime knows about the first - // two fields (cctorMethodAddress and initialized) and thus these must remain the first two fields in the - // same order and at the same offset (hence the sequential layout attribute). It is permissable for the - // classlibrary to add its own fields after these for its own use however. These must not contain GC + // to the classlibrary via the CheckStaticClassConstruction callback. It is permissable for the + // classlibrary to add its own fields after these for its own use. These must not contain GC // references and will be zero initialized. [CLSCompliant(false)] [StructLayout(LayoutKind.Sequential)] public struct StaticClassConstructionContext { - // Pointer to the code for the static class constructor method. This is initialized by the - // binder/runtime. - public IntPtr cctorMethodAddress; - - // Initialization state of the class. This is initialized to 0. Every time managed code checks the - // cctor state the runtime will call the classlibrary's CheckStaticClassConstruction with this context - // structure unless initialized == 1. This check is specific to allow the classlibrary to store more - // than a binary state for each cctor if it so desires. - public volatile int initialized; + // Pointer to the code for the static class constructor method. Set to 0 once the cctor has run. + public volatile IntPtr cctorMethodAddress; } } diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeBuilder.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeBuilder.cs index 50e13f047b19..0668dc4d8805 100644 --- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeBuilder.cs +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeBuilder.cs @@ -53,7 +53,7 @@ public TypeBuilder() /// The StaticClassConstructionContext for a type is encoded in the negative space /// of the NonGCStatic fields of a type. /// - public static readonly unsafe int ClassConstructorOffset = -sizeof(System.Runtime.CompilerServices.StaticClassConstructionContext); + public static unsafe int ClassConstructorOffset => -sizeof(System.Runtime.CompilerServices.StaticClassConstructionContext); private LowLevelList _typesThatNeedTypeHandles = new LowLevelList(); diff --git a/src/coreclr/nativeaot/Test.CoreLib/src/System/Runtime/CompilerServices/ClassConstructorRunner.cs b/src/coreclr/nativeaot/Test.CoreLib/src/System/Runtime/CompilerServices/ClassConstructorRunner.cs index 2a034b6bb748..8c8de3b2b462 100644 --- a/src/coreclr/nativeaot/Test.CoreLib/src/System/Runtime/CompilerServices/ClassConstructorRunner.cs +++ b/src/coreclr/nativeaot/Test.CoreLib/src/System/Runtime/CompilerServices/ClassConstructorRunner.cs @@ -40,17 +40,16 @@ private static unsafe void CheckStaticClassConstruction(ref StaticClassConstruct while (true) { // Read the current state of the cctor. - int oldInitializationState = context.initialized; + IntPtr oldInitializationState = context.cctorMethodAddress; - // Once it transitions to 1 then the cctor has been run (another thread got there first) and + // Once it transitions to 0 then the cctor has been run (another thread got there first) and // we can simply return. - if (oldInitializationState == 1) + if (oldInitializationState == (IntPtr)0) return; - // If the state is anything other than 0 (the initial state) then another thread is currently - // running this cctor. We must wait for it to complete doing so before continuing, so loop - // again. - if (oldInitializationState != 0) + // If the state is 1 then another thread is currently running this cctor. + // We must wait for it to complete doing so before continuing, so loop again. + if (oldInitializationState == (IntPtr)1) continue; // C# warns that passing a volatile field to a method via a reference loses the volatility of the field. @@ -58,15 +57,14 @@ private static unsafe void CheckStaticClassConstruction(ref StaticClassConstruct // unimportant. #pragma warning disable 420 - // We read a state of 0 (the initial state: not initialized and not being initialized). Try to - // transition this to 2 which will let other threads know we're going to run the cctor here. - if (Interlocked.CompareExchange(ref context.initialized, 2, 0) == 0) + // Try to transition this to 1 which will let other threads know we're going to run the cctor here. + if (Interlocked.CompareExchange(ref context.cctorMethodAddress, (IntPtr)1, oldInitializationState) == oldInitializationState) { - // We won the race to transition the state from 0 -> 2. So we can now run the cctor. Other + // We won the race to transition the state to 1. So we can now run the cctor. Other // threads trying to do the same thing will spin waiting for us to transition the state to // 1. - ((delegate*)context.cctorMethodAddress)(); + ((delegate*)oldInitializationState)(); // Insert a memory barrier here to order any writes executed as part of static class // construction above with respect to the initialized flag update we're about to make @@ -75,9 +73,9 @@ private static unsafe void CheckStaticClassConstruction(ref StaticClassConstruct // still see uninitialized static fields on the class. Interlocked.MemoryBarrier(); - // Set the state to 1 to indicate to the runtime and other threads that this cctor has now + // Set the cctorMethodAddress to 0 to indicate to the runtime and other threads that this cctor has now // been run. - context.initialized = 1; + context.cctorMethodAddress = (IntPtr)0; } // If we get here some other thread changed the initialization state to a non-zero value diff --git a/src/coreclr/nativeaot/Test.CoreLib/src/System/Runtime/CompilerServices/StaticClassConstructionContext.cs b/src/coreclr/nativeaot/Test.CoreLib/src/System/Runtime/CompilerServices/StaticClassConstructionContext.cs index 5cc04d3f013a..1f8ba767345f 100644 --- a/src/coreclr/nativeaot/Test.CoreLib/src/System/Runtime/CompilerServices/StaticClassConstructionContext.cs +++ b/src/coreclr/nativeaot/Test.CoreLib/src/System/Runtime/CompilerServices/StaticClassConstructionContext.cs @@ -6,22 +6,13 @@ namespace System.Runtime.CompilerServices { // This structure is used to pass context about a type's static class construction state from the runtime - // to the classlibrary via the CheckStaticClassConstruction callback. The runtime knows about the first - // two fields (cctorMethodAddress and initialized) and thus these must remain the first two fields in the - // same order and at the same offset (hence the sequential layout attribute). It is permissable for the - // classlibrary to add its own fields after these for its own use however. These must not contain GC + // to the classlibrary via the CheckStaticClassConstruction callback. It is permissable for the + // classlibrary to add its own fields after these for its own use. These must not contain GC // references and will be zero initialized. [StructLayout(LayoutKind.Sequential)] public struct StaticClassConstructionContext { - // Pointer to the code for the static class constructor method. This is initialized by the - // binder/runtime. - public IntPtr cctorMethodAddress; - - // Initialization state of the class. This is initialized to 0. Every time managed code checks the - // cctor state the runtime will call the classlibrary's CheckStaticClassConstruction with this context - // structure unless initialized == 1. This check is specific to allow the classlibrary to store more - // than a binary state for each cctor if it so desires. - public volatile int initialized; + // Pointer to the code for the static class constructor method. Set to 0 . + public volatile IntPtr cctorMethodAddress; } } diff --git a/src/coreclr/nativeaot/Test.CoreLib/src/System/Runtime/RuntimeImports.cs b/src/coreclr/nativeaot/Test.CoreLib/src/System/Runtime/RuntimeImports.cs index b1ffb46e39c9..bd1681f250df 100644 --- a/src/coreclr/nativeaot/Test.CoreLib/src/System/Runtime/RuntimeImports.cs +++ b/src/coreclr/nativeaot/Test.CoreLib/src/System/Runtime/RuntimeImports.cs @@ -99,6 +99,10 @@ internal static unsafe Array RhNewArray(EETypePtr pEEType, int length) [RuntimeImport(RuntimeLibrary, "RhpLockCmpXchg32")] internal static extern int InterlockedCompareExchange(ref int location1, int value, int comparand); + [MethodImplAttribute(MethodImplOptions.InternalCall)] + [RuntimeImport(RuntimeLibrary, "RhpLockCmpXchg64")] + internal static extern long InterlockedCompareExchange(ref long location1, long value, long comparand); + [MethodImplAttribute(MethodImplOptions.InternalCall)] [RuntimeImport(RuntimeLibrary, "RhpMemoryBarrier")] internal static extern void MemoryBarrier(); diff --git a/src/coreclr/nativeaot/Test.CoreLib/src/System/Threading/Interlocked.cs b/src/coreclr/nativeaot/Test.CoreLib/src/System/Threading/Interlocked.cs index b3cbdc657947..34d02ffca1d6 100644 --- a/src/coreclr/nativeaot/Test.CoreLib/src/System/Threading/Interlocked.cs +++ b/src/coreclr/nativeaot/Test.CoreLib/src/System/Threading/Interlocked.cs @@ -8,12 +8,28 @@ namespace System.Threading { public static class Interlocked { + [Intrinsic] + public static IntPtr CompareExchange(ref IntPtr location1, IntPtr value, IntPtr comparand) + { +#if TARGET_64BIT + return (IntPtr)Interlocked.CompareExchange(ref Unsafe.As(ref location1), (long)value, (long)comparand); +#else + return (IntPtr)Interlocked.CompareExchange(ref Unsafe.As(ref location1), (int)value, (int)comparand); +#endif + } + [Intrinsic] public static int CompareExchange(ref int location1, int value, int comparand) { return RuntimeImports.InterlockedCompareExchange(ref location1, value, comparand); } + [Intrinsic] + public static long CompareExchange(ref long location1, long value, long comparand) + { + return RuntimeImports.InterlockedCompareExchange(ref location1, value, comparand); + } + [Intrinsic] public static void MemoryBarrier() { diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NonGCStaticsNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NonGCStaticsNode.cs index 08ca5742e63c..8e548e4ce518 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NonGCStaticsNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NonGCStaticsNode.cs @@ -103,7 +103,7 @@ public static int GetClassConstructorContextSize(TargetDetails target) { // TODO: Assert that StaticClassConstructionContext type has the expected size // (need to make it a well known type?) - return target.PointerSize * 2; + return target.PointerSize; } private static int GetClassConstructorContextStorageSize(TargetDetails target, MetadataType type) @@ -172,26 +172,15 @@ protected override ObjectData GetDehydratableData(NodeFactory factory, bool relo // cctor context as already executed. if (!HasLazyStaticConstructor) { - // Pointer to the cctor: we don't care - emit as zero + // Pointer to the cctor: Zero means initialized builder.EmitZeroPointer(); - - // Constructor executed - // TODO-NICE: introduce a named constant and also use it in the runner in CoreLib - builder.EmitInt(1); } else { // Emit pointer to the cctor MethodDesc cctorMethod = _type.GetStaticConstructor(); builder.EmitPointerReloc(factory.ExactCallableAddress(cctorMethod)); - - // Constructor didn't execute - builder.EmitInt(0); } - - // Emit padding if needed - if (builder.TargetPointerSize == 8) - builder.EmitInt(0); } else { diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_ARM/ARMReadyToRunGenericHelperNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_ARM/ARMReadyToRunGenericHelperNode.cs index 65e4e9f315a5..6423bf2ecaf0 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_ARM/ARMReadyToRunGenericHelperNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_ARM/ARMReadyToRunGenericHelperNode.cs @@ -82,12 +82,12 @@ protected sealed override void EmitCode(NodeFactory factory, ref ARMEmitter enco { // We need to trigger the cctor before returning the base. It is stored at the beginning of the non-GC statics region. int cctorContextSize = NonGCStaticsNode.GetClassConstructorContextSize(factory.Target); - encoder.EmitLDR(encoder.TargetRegister.Arg1, encoder.TargetRegister.Arg0, ((short)(factory.Target.PointerSize - cctorContextSize))); - encoder.EmitCMP(encoder.TargetRegister.Arg1, ((byte)1)); + encoder.EmitLDR(encoder.TargetRegister.Arg1, encoder.TargetRegister.Arg0, (short)-cctorContextSize); + encoder.EmitCMP(encoder.TargetRegister.Arg1, 0); encoder.EmitRETIfEqual(); encoder.EmitMOV(encoder.TargetRegister.Arg1, encoder.TargetRegister.Result); - encoder.EmitSUB(encoder.TargetRegister.Arg0, ((byte)(cctorContextSize))); + encoder.EmitSUB(encoder.TargetRegister.Arg0, (byte)cctorContextSize); encoder.EmitJMP(factory.HelperEntrypoint(HelperEntrypoint.EnsureClassConstructorRunAndReturnNonGCStaticBase)); } } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_ARM/ARMReadyToRunHelperNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_ARM/ARMReadyToRunHelperNode.cs index d2adbfd22174..b07ebf96fac9 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_ARM/ARMReadyToRunHelperNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_ARM/ARMReadyToRunHelperNode.cs @@ -55,8 +55,8 @@ protected override void EmitCode(NodeFactory factory, ref ARMEmitter encoder, bo // We need to trigger the cctor before returning the base. It is stored at the beginning of the non-GC statics region. encoder.EmitMOV(encoder.TargetRegister.Arg2, factory.TypeNonGCStaticsSymbol(target)); encoder.EmitLDR(encoder.TargetRegister.Arg3, encoder.TargetRegister.Arg2, - ((short)(factory.Target.PointerSize - NonGCStaticsNode.GetClassConstructorContextSize(factory.Target)))); - encoder.EmitCMP(encoder.TargetRegister.Arg3, 1); + (short)-NonGCStaticsNode.GetClassConstructorContextSize(factory.Target)); + encoder.EmitCMP(encoder.TargetRegister.Arg3, 0); encoder.EmitRETIfEqual(); encoder.EmitMOV(encoder.TargetRegister.Arg1, encoder.TargetRegister.Result); @@ -108,8 +108,8 @@ protected override void EmitCode(NodeFactory factory, ref ARMEmitter encoder, bo // We need to trigger the cctor before returning the base. It is stored at the beginning of the non-GC statics region. encoder.EmitMOV(encoder.TargetRegister.Arg2, factory.TypeNonGCStaticsSymbol(target)); encoder.EmitLDR(encoder.TargetRegister.Arg3, encoder.TargetRegister.Arg2, - ((short)(factory.Target.PointerSize - NonGCStaticsNode.GetClassConstructorContextSize(factory.Target)))); - encoder.EmitCMP(encoder.TargetRegister.Arg3, 1); + (short)-NonGCStaticsNode.GetClassConstructorContextSize(factory.Target)); + encoder.EmitCMP(encoder.TargetRegister.Arg3, 0); encoder.EmitRETIfEqual(); encoder.EmitMOV(encoder.TargetRegister.Arg1, encoder.TargetRegister.Result); diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_ARM64/ARM64ReadyToRunGenericHelperNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_ARM64/ARM64ReadyToRunGenericHelperNode.cs index 0513017a1704..f0b69d1967a2 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_ARM64/ARM64ReadyToRunGenericHelperNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_ARM64/ARM64ReadyToRunGenericHelperNode.cs @@ -93,8 +93,8 @@ protected sealed override void EmitCode(NodeFactory factory, ref ARM64Emitter en { // We need to trigger the cctor before returning the base. It is stored at the beginning of the non-GC statics region. encoder.EmitSUB(encoder.TargetRegister.Arg3, encoder.TargetRegister.Arg0, NonGCStaticsNode.GetClassConstructorContextSize(factory.Target)); - encoder.EmitLDR(encoder.TargetRegister.Arg2, encoder.TargetRegister.Arg3, (short)factory.Target.PointerSize); - encoder.EmitCMP(encoder.TargetRegister.Arg2, 1); + encoder.EmitLDR(encoder.TargetRegister.Arg2, encoder.TargetRegister.Arg3); + encoder.EmitCMP(encoder.TargetRegister.Arg2, 0); encoder.EmitRETIfEqual(); encoder.EmitMOV(encoder.TargetRegister.Arg1, encoder.TargetRegister.Result); @@ -125,8 +125,8 @@ protected sealed override void EmitCode(NodeFactory factory, ref ARM64Emitter en EmitDictionaryLookup(factory, ref encoder, encoder.TargetRegister.Arg1, encoder.TargetRegister.Arg2, nonGcRegionLookup, relocsOnly); encoder.EmitSUB(encoder.TargetRegister.Arg2, NonGCStaticsNode.GetClassConstructorContextSize(factory.Target)); - encoder.EmitLDR(encoder.TargetRegister.Arg3, encoder.TargetRegister.Arg2, (short)factory.Target.PointerSize); - encoder.EmitCMP(encoder.TargetRegister.Arg3, 1); + encoder.EmitLDR(encoder.TargetRegister.Arg3, encoder.TargetRegister.Arg2); + encoder.EmitCMP(encoder.TargetRegister.Arg3, 0); encoder.EmitRETIfEqual(); encoder.EmitMOV(encoder.TargetRegister.Arg1, encoder.TargetRegister.Result); diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_ARM64/ARM64ReadyToRunHelperNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_ARM64/ARM64ReadyToRunHelperNode.cs index 8c309fef840f..c61a3ebf7b9e 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_ARM64/ARM64ReadyToRunHelperNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_ARM64/ARM64ReadyToRunHelperNode.cs @@ -56,8 +56,8 @@ protected override void EmitCode(NodeFactory factory, ref ARM64Emitter encoder, { // We need to trigger the cctor before returning the base. It is stored at the beginning of the non-GC statics region. encoder.EmitSUB(encoder.TargetRegister.Arg3, encoder.TargetRegister.Result, NonGCStaticsNode.GetClassConstructorContextSize(factory.Target)); - encoder.EmitLDR(encoder.TargetRegister.Arg2, encoder.TargetRegister.Arg3, (short)factory.Target.PointerSize); - encoder.EmitCMP(encoder.TargetRegister.Arg2, 1); + encoder.EmitLDR(encoder.TargetRegister.Arg2, encoder.TargetRegister.Arg3); + encoder.EmitCMP(encoder.TargetRegister.Arg2, 0); encoder.EmitRETIfEqual(); encoder.EmitMOV(encoder.TargetRegister.Arg1, encoder.TargetRegister.Result); @@ -90,8 +90,8 @@ protected override void EmitCode(NodeFactory factory, ref ARM64Emitter encoder, encoder.EmitMOV(encoder.TargetRegister.Arg2, factory.TypeNonGCStaticsSymbol(target)); encoder.EmitSUB(encoder.TargetRegister.Arg2, NonGCStaticsNode.GetClassConstructorContextSize(factory.Target)); - encoder.EmitLDR(encoder.TargetRegister.Arg3, encoder.TargetRegister.Arg2, (short)factory.Target.PointerSize); - encoder.EmitCMP(encoder.TargetRegister.Arg3, 1); + encoder.EmitLDR(encoder.TargetRegister.Arg3, encoder.TargetRegister.Arg2); + encoder.EmitCMP(encoder.TargetRegister.Arg3, 0); encoder.EmitJE(factory.HelperEntrypoint(HelperEntrypoint.GetThreadStaticBaseForType)); encoder.EmitJMP(factory.HelperEntrypoint(HelperEntrypoint.EnsureClassConstructorRunAndReturnThreadStaticBase)); @@ -115,8 +115,8 @@ protected override void EmitCode(NodeFactory factory, ref ARM64Emitter encoder, // We need to trigger the cctor before returning the base. It is stored at the beginning of the non-GC statics region. encoder.EmitMOV(encoder.TargetRegister.Arg2, factory.TypeNonGCStaticsSymbol(target)); encoder.EmitSUB(encoder.TargetRegister.Arg2, NonGCStaticsNode.GetClassConstructorContextSize(factory.Target)); - encoder.EmitLDR(encoder.TargetRegister.Arg3, encoder.TargetRegister.Arg2, (short)factory.Target.PointerSize); - encoder.EmitCMP(encoder.TargetRegister.Arg3, 1); + encoder.EmitLDR(encoder.TargetRegister.Arg3, encoder.TargetRegister.Arg2); + encoder.EmitCMP(encoder.TargetRegister.Arg3, 0); encoder.EmitRETIfEqual(); encoder.EmitMOV(encoder.TargetRegister.Arg1, encoder.TargetRegister.Result); diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_LoongArch64/LoongArch64ReadyToRunGenericHelperNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_LoongArch64/LoongArch64ReadyToRunGenericHelperNode.cs index ee809996f6c9..493470b7ef2f 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_LoongArch64/LoongArch64ReadyToRunGenericHelperNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_LoongArch64/LoongArch64ReadyToRunGenericHelperNode.cs @@ -82,8 +82,8 @@ protected sealed override void EmitCode(NodeFactory factory, ref LoongArch64Emit { // We need to trigger the cctor before returning the base. It is stored at the beginning of the non-GC statics region. encoder.EmitADD(encoder.TargetRegister.Arg3, encoder.TargetRegister.Arg0, -NonGCStaticsNode.GetClassConstructorContextSize(factory.Target)); - encoder.EmitLD(encoder.TargetRegister.Arg2, encoder.TargetRegister.Arg3, factory.Target.PointerSize); - encoder.EmitXOR(encoder.TargetRegister.IntraProcedureCallScratch1, encoder.TargetRegister.Arg2, 1); + encoder.EmitLD(encoder.TargetRegister.Arg2, encoder.TargetRegister.Arg3, 0); + encoder.EmitXOR(encoder.TargetRegister.IntraProcedureCallScratch1, encoder.TargetRegister.Arg2, 0); encoder.EmitRETIfEqual(Register.R21); encoder.EmitMOV(encoder.TargetRegister.Arg1, encoder.TargetRegister.Result); diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_LoongArch64/LoongArch64ReadyToRunHelperNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_LoongArch64/LoongArch64ReadyToRunHelperNode.cs index d618787a086c..49505b9dff77 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_LoongArch64/LoongArch64ReadyToRunHelperNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_LoongArch64/LoongArch64ReadyToRunHelperNode.cs @@ -90,8 +90,8 @@ protected override void EmitCode(NodeFactory factory, ref LoongArch64Emitter enc encoder.EmitMOV(encoder.TargetRegister.Arg2, factory.TypeNonGCStaticsSymbol(target)); encoder.EmitADD(encoder.TargetRegister.Arg2, encoder.TargetRegister.Arg2, -NonGCStaticsNode.GetClassConstructorContextSize(factory.Target)); - encoder.EmitLD(encoder.TargetRegister.Arg3, encoder.TargetRegister.Arg2, factory.Target.PointerSize); - encoder.EmitXOR(encoder.TargetRegister.IntraProcedureCallScratch1, encoder.TargetRegister.Arg3, 1); + encoder.EmitLD(encoder.TargetRegister.Arg3, encoder.TargetRegister.Arg2, 0); + encoder.EmitXOR(encoder.TargetRegister.IntraProcedureCallScratch1, encoder.TargetRegister.Arg3, 0); encoder.EmitJE(encoder.TargetRegister.IntraProcedureCallScratch1, factory.HelperEntrypoint(HelperEntrypoint.GetThreadStaticBaseForType)); encoder.EmitJMP(factory.HelperEntrypoint(HelperEntrypoint.EnsureClassConstructorRunAndReturnThreadStaticBase)); @@ -115,8 +115,8 @@ protected override void EmitCode(NodeFactory factory, ref LoongArch64Emitter enc // We need to trigger the cctor before returning the base. It is stored at the beginning of the non-GC statics region. encoder.EmitMOV(encoder.TargetRegister.Arg2, factory.TypeNonGCStaticsSymbol(target)); encoder.EmitADD(encoder.TargetRegister.Arg2, encoder.TargetRegister.Arg2, -NonGCStaticsNode.GetClassConstructorContextSize(factory.Target)); - encoder.EmitLD(encoder.TargetRegister.Arg3, encoder.TargetRegister.Arg2, factory.Target.PointerSize); - encoder.EmitXOR(encoder.TargetRegister.IntraProcedureCallScratch1, encoder.TargetRegister.Arg3, 1); + encoder.EmitLD(encoder.TargetRegister.Arg3, encoder.TargetRegister.Arg2, 0); + encoder.EmitXOR(encoder.TargetRegister.IntraProcedureCallScratch1, encoder.TargetRegister.Arg3, 0); encoder.EmitRETIfEqual(Register.R21); encoder.EmitMOV(encoder.TargetRegister.Arg1, encoder.TargetRegister.Result); diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_X64/X64ReadyToRunGenericHelperNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_X64/X64ReadyToRunGenericHelperNode.cs index 3b09eb2dbc7c..4c506a3b18d5 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_X64/X64ReadyToRunGenericHelperNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_X64/X64ReadyToRunGenericHelperNode.cs @@ -98,8 +98,8 @@ protected sealed override void EmitCode(NodeFactory factory, ref X64Emitter enco // We need to trigger the cctor before returning the base. It is stored at the beginning of the non-GC statics region. int cctorContextSize = NonGCStaticsNode.GetClassConstructorContextSize(factory.Target); - AddrMode initialized = new AddrMode(encoder.TargetRegister.Arg0, null, factory.Target.PointerSize - cctorContextSize, 0, AddrModeSize.Int32); - encoder.EmitCMP(ref initialized, 1); + AddrMode initialized = new AddrMode(encoder.TargetRegister.Arg0, null, -cctorContextSize, 0, AddrModeSize.Int64); + encoder.EmitCMP(ref initialized, 0); encoder.EmitRETIfEqual(); AddrMode loadCctor = new AddrMode(encoder.TargetRegister.Arg0, null, -cctorContextSize, 0, AddrModeSize.Int64); @@ -132,8 +132,8 @@ protected sealed override void EmitCode(NodeFactory factory, ref X64Emitter enco EmitDictionaryLookup(factory, ref encoder, encoder.TargetRegister.Arg0, encoder.TargetRegister.Arg0, nonGcRegionLookup, relocsOnly); int cctorContextSize = NonGCStaticsNode.GetClassConstructorContextSize(factory.Target); - AddrMode initialized = new AddrMode(encoder.TargetRegister.Arg0, null, factory.Target.PointerSize - cctorContextSize, 0, AddrModeSize.Int32); - encoder.EmitCMP(ref initialized, 1); + AddrMode initialized = new AddrMode(encoder.TargetRegister.Arg0, null, -cctorContextSize, 0, AddrModeSize.Int64); + encoder.EmitCMP(ref initialized, 0); encoder.EmitRETIfEqual(); encoder.EmitMOV(encoder.TargetRegister.Arg1, encoder.TargetRegister.Result); diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_X64/X64ReadyToRunHelperNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_X64/X64ReadyToRunHelperNode.cs index 2c80e0b0faaf..a091fdfc9436 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_X64/X64ReadyToRunHelperNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_X64/X64ReadyToRunHelperNode.cs @@ -58,8 +58,8 @@ protected override void EmitCode(NodeFactory factory, ref X64Emitter encoder, bo // We need to trigger the cctor before returning the base. It is stored at the beginning of the non-GC statics region. encoder.EmitLEAQ(encoder.TargetRegister.Arg0, factory.TypeNonGCStaticsSymbol(target), -NonGCStaticsNode.GetClassConstructorContextSize(factory.Target)); - AddrMode initialized = new AddrMode(encoder.TargetRegister.Arg0, null, factory.Target.PointerSize, 0, AddrModeSize.Int32); - encoder.EmitCMP(ref initialized, 1); + AddrMode initialized = new AddrMode(encoder.TargetRegister.Arg0, null, 0, 0, AddrModeSize.Int64); + encoder.EmitCMP(ref initialized, 0); encoder.EmitRETIfEqual(); encoder.EmitMOV(encoder.TargetRegister.Arg1, encoder.TargetRegister.Result); @@ -92,8 +92,8 @@ protected override void EmitCode(NodeFactory factory, ref X64Emitter encoder, bo { encoder.EmitLEAQ(encoder.TargetRegister.Arg2, factory.TypeNonGCStaticsSymbol(target), - NonGCStaticsNode.GetClassConstructorContextSize(factory.Target)); - AddrMode initialized = new AddrMode(encoder.TargetRegister.Arg2, null, factory.Target.PointerSize, 0, AddrModeSize.Int32); - encoder.EmitCMP(ref initialized, 1); + AddrMode initialized = new AddrMode(encoder.TargetRegister.Arg2, null, 0, 0, AddrModeSize.Int64); + encoder.EmitCMP(ref initialized, 0); encoder.EmitJE(factory.ExternSymbol("RhpGetThreadStaticBaseForType")); encoder.EmitJMP(factory.HelperEntrypoint(HelperEntrypoint.EnsureClassConstructorRunAndReturnThreadStaticBase)); @@ -118,8 +118,8 @@ protected override void EmitCode(NodeFactory factory, ref X64Emitter encoder, bo // We need to trigger the cctor before returning the base. It is stored at the beginning of the non-GC statics region. encoder.EmitLEAQ(encoder.TargetRegister.Arg0, factory.TypeNonGCStaticsSymbol(target), -NonGCStaticsNode.GetClassConstructorContextSize(factory.Target)); - AddrMode initialized = new AddrMode(encoder.TargetRegister.Arg0, null, factory.Target.PointerSize, 0, AddrModeSize.Int32); - encoder.EmitCMP(ref initialized, 1); + AddrMode initialized = new AddrMode(encoder.TargetRegister.Arg0, null, 0, 0, AddrModeSize.Int64); + encoder.EmitCMP(ref initialized, 0); encoder.EmitRETIfEqual(); encoder.EmitMOV(encoder.TargetRegister.Arg1, encoder.TargetRegister.Result); diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_X86/X86ReadyToRunHelperNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_X86/X86ReadyToRunHelperNode.cs index 5d4c15020301..255ec2f0b016 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_X86/X86ReadyToRunHelperNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_X86/X86ReadyToRunHelperNode.cs @@ -39,8 +39,8 @@ protected override void EmitCode(NodeFactory factory, ref X86Emitter encoder, bo // We need to trigger the cctor before returning the base. It is stored at the beginning of the non-GC statics region. encoder.EmitMOV(encoder.TargetRegister.Arg0, factory.TypeNonGCStaticsSymbol(target), -NonGCStaticsNode.GetClassConstructorContextSize(factory.Target)); - AddrMode initialized = new AddrMode(encoder.TargetRegister.Arg0, null, factory.Target.PointerSize, 0, AddrModeSize.Int32); - encoder.EmitCMP(ref initialized, 1); + AddrMode initialized = new AddrMode(encoder.TargetRegister.Arg0, null, 0, 0, AddrModeSize.Int32); + encoder.EmitCMP(ref initialized, 0); encoder.EmitRETIfEqual(); encoder.EmitMOV(encoder.TargetRegister.Arg1, encoder.TargetRegister.Result);