-
Notifications
You must be signed in to change notification settings - Fork 2.7k
Conversation
2cb0bfb
to
b2026f3
Compare
I expect these are there because in a world of Security{Safe}Critical and SecurityTransparent, initializing a static SecurityCritical field can only be done from a Security{Safe}Critical static cctor, and to attribute it appropriately you need the explicit cctor. For mscorlib in CoreCLR, I'm not sure if that matters. @AlexGhiondea or @jkotas can probably comment more authoritatively. |
Ah, that would make sense. |
@stephentoub would something like this work? Have put the initializers in a |
@ericeil might be the best to comment. |
This seems reasonable to me. |
4ec573b
to
8f15732
Compare
Rebased and squished |
I am not sure I understand the advantage of this change. Sure, we don't have a static constructor that does seems to do nothing, but this will make it way harder to understand the way transparency works in those cases. While for now we found the code that called it and marked it appropriately, i think that has a couple of problems:
Can you please explain what advantage this change has over leaving it as-is? |
There is cost to having an explicit static cctor, in that the C# compiler will then not mark the type as beforefieldinit, and the backend compiler will be forced to add initialization checks to static methods on the type. It's something static analysis rules have checked for: https://msdn.microsoft.com/en-us/library/ms182275.aspx I don't know whether it makes a measurable difference in this particular case. |
There is a gotcha that the first function that is called and does field access has the initialization checks compiled into it; while any later function does not. Seeing if I can rearrange. |
This does not mattet. mscorlib is always expected to be precompiled using crossgen in production - all static access has this check in precompiled code. |
😭 might as well close then |
I just meant that reordering does not matter. There may be still benefit on your change by avoiding the cctor check in static methods that do not access any fields - have not looked whether there are any. |
@jkotas can initialize the four delegates to non-capturing lambdas, drop some of the static functions and a lot of the casts? That work in the native realm? |
1046906
to
fd66096
Compare
Initalize threadpool statics in SecuritySafeCritical path
@@ -1882,8 +1883,7 @@ private static void EnsureVMInitialized() | |||
[System.Security.SecuritySafeCritical] | |||
internal static void NotifyWorkItemProgress() | |||
{ | |||
if (!ThreadPoolGlobals.vmTpInitialized) | |||
ThreadPool.InitializeVMTp(ref ThreadPoolGlobals.enableWorkerTracking); | |||
EnsureVMInitialized(); | |||
NotifyWorkItemProgressNative(); | |||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Was the behaviour correct to not set ThreadPoolGlobals.vmTpInitialized = true;
at this point previously?
Last change drops the auto.cctor entirely (which is different from the explicit non-beforefieldinit .cctor) and may mean no runtime guards are needed on the static fields? |
@benaadams do you have some performance numbers to show what this change will do? |
@AlexGhiondea these functions are called several million times a second so it is a hot path for performance. However, I haven't managed to validate it yet. I disassembled and stepped through both versions (non-native image) and this version has slightly fewer instructions but there isn't that much change due to the magic of the jitter. I'm going to have to compare and benchmark the native images which will take a bit longer. |
Closing, measured and integrated in #5943 |
Do
ThreadPoolGlobals
,QueueUserWorkItemCallback
and_ThreadPoolWaitOrTimerCallback
need empty static constructors?