Is the jit supposed to hoist init type checks this hard? #122605
-
|
Consider static types A with a method static class A
{
static bool IsInit;
static int LoopCount;
public static void OhGodWhy()
{
if (!IsInit)
return;
for (int i = 0; i < LoopCount; i++)
B.DoWork();
}
}
static class B
{
static B()
{
// observable side effect
}
public static void DoWork() { /* Actual code */ }
}(Note that this isn't a minimal repro as I couldn't isolate the behaviour.) Is this intended behaviour? And if so then what's causing it? 👀 I would love to learn more about how the JIT reasons, thank you for your time! 🙂 |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 5 replies
-
|
In practice, a type is often considered touched when a method referencing the type get touched. The timing of static constructor is non-deterministic. It's not suggested to depend on its side effect. |
Beta Was this translation helpful? Give feedback.
-
|
Is class
There is also this comment in the JIT explaining that when a type is marked You can see in the source JIT source several places where the presence of |
Beta Was this translation helpful? Give feedback.
It sounds like related to eager bound of P/Inovke. If the P/Invoke is bound earlier, the .cctor of the type also need to be run earlier.
To be precise - there is not really a precise initialization semantic. It's only guarantee to be earlier than required point, and the implementation detail tries to be as late as possible to make it more predictable.