diff options
author | Michal Strehovský <MichalStrehovsky@users.noreply.github.com> | 2018-07-18 13:24:56 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-07-18 13:24:56 +0300 |
commit | a394e915916c4abbff08636884124c6e82f36a8f (patch) | |
tree | e297ec7a720296cd7f54f60aa5943088d4d88d82 /src | |
parent | e2c4bc3d7889f951c231d7f131d6a7e20c034fb6 (diff) |
Make thread statics faster (#6108)
* Fix the TODO to inline `.cctor` check into the R2R helper. This avoids some method calls and stack frame setup.
* Remove array cast from the hot path. The runtime doesn't care what type the storage is, as long as it's a managed reference - in fact, it seems to be treated as an `Object` in `pCurrentThread->GetThreadStaticStorageForModule` anyway. I considered replacing the cast with an `Unsafe.As`, but just redeclaring the signatures as returning `object[]` seemed better (because now we actually guarantee the classlib won't pass anything but `object[]` to `RhSetThreadStaticStorageForModule`).
Diffstat (limited to 'src')
5 files changed, 24 insertions, 6 deletions
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_X64/X64Emitter.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_X64/X64Emitter.cs index 09ebadeaa..662867f99 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_X64/X64Emitter.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_X64/X64Emitter.cs @@ -88,6 +88,20 @@ namespace ILCompiler.DependencyAnalysis.X64 } } + public void EmitJE(ISymbolNode symbol) + { + if (symbol.RepresentsIndirectionCell) + { + throw new NotImplementedException(); + } + else + { + Builder.EmitByte(0x0f); + Builder.EmitByte(0x84); + Builder.EmitReloc(symbol, RelocType.IMAGE_REL_BASED_REL32); + } + } + public void EmitINT3() { Builder.EmitByte(0xCC); diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_X64/X64ReadyToRunHelperNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_X64/X64ReadyToRunHelperNode.cs index 026367d85..dbe8319c8 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_X64/X64ReadyToRunHelperNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_X64/X64ReadyToRunHelperNode.cs @@ -127,7 +127,11 @@ namespace ILCompiler.DependencyAnalysis else { encoder.EmitLEAQ(encoder.TargetRegister.Arg2, factory.TypeNonGCStaticsSymbol(target), - NonGCStaticsNode.GetClassConstructorContextStorageSize(factory.Target, target)); - // TODO: performance optimization - inline the check verifying whether we need to trigger the cctor + + AddrMode initialized = new AddrMode(encoder.TargetRegister.Arg2, null, factory.Target.PointerSize, 0, AddrModeSize.Int32); + encoder.EmitCMP(ref initialized, 1); + encoder.EmitJE(factory.HelperEntrypoint(HelperEntrypoint.GetThreadStaticBaseForType)); + encoder.EmitJMP(factory.HelperEntrypoint(HelperEntrypoint.EnsureClassConstructorRunAndReturnThreadStaticBase)); } } diff --git a/src/Native/Runtime/thread.cpp b/src/Native/Runtime/thread.cpp index 570581143..77cfc1904 100644 --- a/src/Native/Runtime/thread.cpp +++ b/src/Native/Runtime/thread.cpp @@ -1336,10 +1336,10 @@ Boolean Thread::SetThreadStaticStorageForModule(Object * pStorage, UInt32 module return TRUE; } -COOP_PINVOKE_HELPER(Array*, RhGetThreadStaticStorageForModule, (UInt32 moduleIndex)) +COOP_PINVOKE_HELPER(Object*, RhGetThreadStaticStorageForModule, (UInt32 moduleIndex)) { Thread * pCurrentThread = ThreadStore::RawGetCurrentThread(); - return (Array*)pCurrentThread->GetThreadStaticStorageForModule(moduleIndex); + return pCurrentThread->GetThreadStaticStorageForModule(moduleIndex); } COOP_PINVOKE_HELPER(Boolean, RhSetThreadStaticStorageForModule, (Array * pStorage, UInt32 moduleIndex)) diff --git a/src/System.Private.CoreLib/src/Internal/Runtime/ThreadStatics.cs b/src/System.Private.CoreLib/src/Internal/Runtime/ThreadStatics.cs index fc8e142cd..b125d8fa2 100644 --- a/src/System.Private.CoreLib/src/Internal/Runtime/ThreadStatics.cs +++ b/src/System.Private.CoreLib/src/Internal/Runtime/ThreadStatics.cs @@ -22,7 +22,7 @@ namespace Internal.Runtime { // Get the array that holds thread static memory blocks for each type in the given module int moduleIndex = pModuleData->ModuleIndex; - object[] storage = (object[])RuntimeImports.RhGetThreadStaticStorageForModule(moduleIndex); + object[] storage = RuntimeImports.RhGetThreadStaticStorageForModule(moduleIndex); // Check whether thread static storage has already been allocated for this module and type. if ((storage != null) && (typeTlsIndex < storage.Length) && (storage[typeTlsIndex] != null)) diff --git a/src/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs b/src/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs index 49ed62a79..acc2fd324 100644 --- a/src/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs +++ b/src/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs @@ -561,11 +561,11 @@ namespace System.Runtime #if !PROJECTN [MethodImplAttribute(MethodImplOptions.InternalCall)] [RuntimeImport(RuntimeLibrary, "RhGetThreadStaticStorageForModule")] - internal static unsafe extern Array RhGetThreadStaticStorageForModule(int moduleIndex); + internal static unsafe extern object[] RhGetThreadStaticStorageForModule(int moduleIndex); [MethodImplAttribute(MethodImplOptions.InternalCall)] [RuntimeImport(RuntimeLibrary, "RhSetThreadStaticStorageForModule")] - internal static unsafe extern bool RhSetThreadStaticStorageForModule(Array storage, int moduleIndex); + internal static unsafe extern bool RhSetThreadStaticStorageForModule(object[] storage, int moduleIndex); [MethodImplAttribute(MethodImplOptions.InternalCall)] [RuntimeImport(RuntimeLibrary, "RhCurrentNativeThreadId")] |