From 6392292ef37ca22d70fc002ff117370508dbb6be Mon Sep 17 00:00:00 2001 From: Jakob Botsch Nielsen <jakob.botsch.nielsen@gmail.com> Date: Thu, 1 Aug 2024 21:33:07 +0200 Subject: [PATCH 1/3] JIT: Make sure static ctor flag check uses a volatile load Otherwise the hardware is allowed to reorder loads of its static fields to happen before the initialization check. --- src/coreclr/jit/helperexpansion.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/coreclr/jit/helperexpansion.cpp b/src/coreclr/jit/helperexpansion.cpp index 1580a3fbba362e..089ba3978be65e 100644 --- a/src/coreclr/jit/helperexpansion.cpp +++ b/src/coreclr/jit/helperexpansion.cpp @@ -1418,6 +1418,7 @@ bool Compiler::fgExpandStaticInitForCall(BasicBlock** pBlock, Statement* stmt, G // Don't fold ADD(CNS1, CNS2) here since the result won't be reloc-friendly for AOT GenTree* offsetNode = gtNewOperNode(GT_ADD, TYP_I_IMPL, baseAddr, gtNewIconNode(isInitOffset)); isInitedActualValueNode = gtNewIndir(TYP_I_IMPL, offsetNode, GTF_IND_NONFAULTING); + isInitedActualValueNode->gtFlags |= GTF_IND_VOLATILE; // 0 means "initialized" on NativeAOT isInitedExpectedValue = gtNewIconNode(0, TYP_I_IMPL); @@ -1427,6 +1428,7 @@ bool Compiler::fgExpandStaticInitForCall(BasicBlock** pBlock, Statement* stmt, G assert(isInitOffset == 0); isInitedActualValueNode = gtNewIndOfIconHandleNode(TYP_INT, (size_t)flagAddr.addr, GTF_ICON_GLOBAL_PTR, false); + isInitedActualValueNode->gtFlags |= GTF_IND_VOLATILE; // Check ClassInitFlags::INITIALIZED_FLAG bit isInitedActualValueNode = gtNewOperNode(GT_AND, TYP_INT, isInitedActualValueNode, gtNewIconNode(1)); From c81e50bda284a879ba025fe99dd2fafb0efb6713 Mon Sep 17 00:00:00 2001 From: Jakob Botsch Nielsen <jakob.botsch.nielsen@gmail.com> Date: Thu, 1 Aug 2024 21:37:48 +0200 Subject: [PATCH 2/3] Nit --- src/coreclr/jit/helperexpansion.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/coreclr/jit/helperexpansion.cpp b/src/coreclr/jit/helperexpansion.cpp index 089ba3978be65e..6f8b8456db428e 100644 --- a/src/coreclr/jit/helperexpansion.cpp +++ b/src/coreclr/jit/helperexpansion.cpp @@ -1417,8 +1417,7 @@ bool Compiler::fgExpandStaticInitForCall(BasicBlock** pBlock, Statement* stmt, G // Don't fold ADD(CNS1, CNS2) here since the result won't be reloc-friendly for AOT GenTree* offsetNode = gtNewOperNode(GT_ADD, TYP_I_IMPL, baseAddr, gtNewIconNode(isInitOffset)); - isInitedActualValueNode = gtNewIndir(TYP_I_IMPL, offsetNode, GTF_IND_NONFAULTING); - isInitedActualValueNode->gtFlags |= GTF_IND_VOLATILE; + isInitedActualValueNode = gtNewIndir(TYP_I_IMPL, offsetNode, GTF_IND_NONFAULTING | GTF_IND_VOLATILE); // 0 means "initialized" on NativeAOT isInitedExpectedValue = gtNewIconNode(0, TYP_I_IMPL); From ee9f88b03b77920e5eed331fdef277231f93453c Mon Sep 17 00:00:00 2001 From: Jakob Botsch Nielsen <jakob.botsch.nielsen@gmail.com> Date: Fri, 2 Aug 2024 17:07:02 +0200 Subject: [PATCH 3/3] Set GTF_ORDER_SIDEEFF --- src/coreclr/jit/helperexpansion.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/coreclr/jit/helperexpansion.cpp b/src/coreclr/jit/helperexpansion.cpp index 6f8b8456db428e..3d5678d2743b42 100644 --- a/src/coreclr/jit/helperexpansion.cpp +++ b/src/coreclr/jit/helperexpansion.cpp @@ -1428,6 +1428,7 @@ bool Compiler::fgExpandStaticInitForCall(BasicBlock** pBlock, Statement* stmt, G isInitedActualValueNode = gtNewIndOfIconHandleNode(TYP_INT, (size_t)flagAddr.addr, GTF_ICON_GLOBAL_PTR, false); isInitedActualValueNode->gtFlags |= GTF_IND_VOLATILE; + isInitedActualValueNode->SetHasOrderingSideEffect(); // Check ClassInitFlags::INITIALIZED_FLAG bit isInitedActualValueNode = gtNewOperNode(GT_AND, TYP_INT, isInitedActualValueNode, gtNewIconNode(1));