From 766874ec28a77fc15c217cf1eff6c84d222c3c98 Mon Sep 17 00:00:00 2001 From: Allan Targino <13934447+allantargino@users.noreply.github.com> Date: Fri, 24 Sep 2021 14:03:29 -0300 Subject: [PATCH] Using optimized ILGenerator.Emit function in Dependency Injection MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We were doing some local optimizations with MSIL’s Stloc and Ldloc, but the very same ones are already present in an override of the ILGenerator.Emit function, so we can remove them. This PR also fixes the use of Ldloca that was generating additional nop operations. fix #59624 --- .../ILEmit/ILEmitResolverBuilder.cs | 110 ++++++------------ 1 file changed, 35 insertions(+), 75 deletions(-) diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ILEmit/ILEmitResolverBuilder.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ILEmit/ILEmitResolverBuilder.cs index 878ba33bbc0c60..98a79d2ef89f98 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ILEmit/ILEmitResolverBuilder.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ILEmit/ILEmitResolverBuilder.cs @@ -286,25 +286,32 @@ private ILEmitResolverBuilderRuntimeContext GenerateMethodBody(ServiceCallSite c // if (scope.IsRootScope) // { - // return CallSiteRuntimeResolver.Instance.Resolve(callSite, scope); + // return CallSiteRuntimeResolver.Instance.Resolve(callSite, scope); // } - // var cacheKey = scopedCallSite.CacheKey; - // try - // { + // var cacheKey = scopedCallSite.CacheKey; + // object sync; + // bool lockTaken; + // object result; + // try + // { // var resolvedServices = scope.ResolvedServices; - // Monitor.Enter(resolvedServices, out var lockTaken); - // if (!resolvedServices.TryGetValue(cacheKey, out value) + // sync = scope.Sync; + // Monitor.Enter(sync, ref lockTaken); + // if (!resolvedServices.TryGetValue(cacheKey, out result) // { - // value = [createvalue]; - // CaptureDisposable(value); - // resolvedServices.Add(cacheKey, value); + // result = [createvalue]; + // CaptureDisposable(result); + // resolvedServices.Add(cacheKey, result); // } // } // finally // { - // if (lockTaken) Monitor.Exit(scope.ResolvedServices); + // if (lockTaken) + // { + // Monitor.Exit(sync); + // } // } - // return value; + // return result; if (callSite.Cache.Location == CallSiteResultCacheLocation.Scope) { @@ -333,7 +340,7 @@ private ILEmitResolverBuilderRuntimeContext GenerateMethodBody(ServiceCallSite c context.Generator.MarkLabel(defaultLabel); AddCacheKey(context, callSite.Cache.Key); // and store to local - Stloc(context.Generator, cacheKeyLocal.LocalIndex); + context.Generator.Emit(OpCodes.Stloc, cacheKeyLocal); context.Generator.BeginExceptionBlock(); @@ -342,28 +349,28 @@ private ILEmitResolverBuilderRuntimeContext GenerateMethodBody(ServiceCallSite c // .ResolvedServices context.Generator.Emit(OpCodes.Callvirt, ResolvedServicesGetter); // Store resolved services - Stloc(context.Generator, resolvedServicesLocal.LocalIndex); + context.Generator.Emit(OpCodes.Stloc, resolvedServicesLocal); // scope context.Generator.Emit(OpCodes.Ldarg_1); // .Sync context.Generator.Emit(OpCodes.Callvirt, ScopeLockGetter); // Store syncLocal - Stloc(context.Generator, syncLocal.LocalIndex); + context.Generator.Emit(OpCodes.Stloc, syncLocal); // Load syncLocal - Ldloc(context.Generator, syncLocal.LocalIndex); + context.Generator.Emit(OpCodes.Ldloc, syncLocal); // Load address of lockTaken - context.Generator.Emit(OpCodes.Ldloca_S, lockTakenLocal.LocalIndex); + context.Generator.Emit(OpCodes.Ldloca, lockTakenLocal); // Monitor.Enter context.Generator.Emit(OpCodes.Call, ServiceLookupHelpers.MonitorEnterMethodInfo); // Load resolved services - Ldloc(context.Generator, resolvedServicesLocal.LocalIndex); + context.Generator.Emit(OpCodes.Ldloc, resolvedServicesLocal); // Load cache key - Ldloc(context.Generator, cacheKeyLocal.LocalIndex); + context.Generator.Emit(OpCodes.Ldloc, cacheKeyLocal); // Load address of result local - context.Generator.Emit(OpCodes.Ldloca_S, resultLocal.LocalIndex); + context.Generator.Emit(OpCodes.Ldloca, resultLocal); // .TryGetValue context.Generator.Emit(OpCodes.Callvirt, ServiceLookupHelpers.TryGetValueMethodInfo); @@ -372,23 +379,23 @@ private ILEmitResolverBuilderRuntimeContext GenerateMethodBody(ServiceCallSite c // Create value VisitCallSiteMain(callSite, context); - Stloc(context.Generator, resultLocal.LocalIndex); + context.Generator.Emit(OpCodes.Stloc, resultLocal); if (callSite.CaptureDisposable) { BeginCaptureDisposable(context); - Ldloc(context.Generator, resultLocal.LocalIndex); + context.Generator.Emit(OpCodes.Ldloc, resultLocal); EndCaptureDisposable(context); // Pop value returned by CaptureDisposable off the stack generator.Emit(OpCodes.Pop); } // load resolvedServices - Ldloc(context.Generator, resolvedServicesLocal.LocalIndex); + context.Generator.Emit(OpCodes.Ldloc, resolvedServicesLocal); // load cache key - Ldloc(context.Generator, cacheKeyLocal.LocalIndex); + context.Generator.Emit(OpCodes.Ldloc, cacheKeyLocal); // load value - Ldloc(context.Generator, resultLocal.LocalIndex); + context.Generator.Emit(OpCodes.Ldloc, resultLocal); // .Add context.Generator.Emit(OpCodes.Callvirt, ServiceLookupHelpers.AddMethodInfo); @@ -397,11 +404,11 @@ private ILEmitResolverBuilderRuntimeContext GenerateMethodBody(ServiceCallSite c context.Generator.BeginFinallyBlock(); // load lockTaken - Ldloc(context.Generator, lockTakenLocal.LocalIndex); + context.Generator.Emit(OpCodes.Ldloc, lockTakenLocal); // return if not context.Generator.Emit(OpCodes.Brfalse, returnLabel); // Load syncLocal - Ldloc(context.Generator, syncLocal.LocalIndex); + context.Generator.Emit(OpCodes.Ldloc, syncLocal); // Monitor.Exit context.Generator.Emit(OpCodes.Call, ServiceLookupHelpers.MonitorExitMethodInfo); @@ -409,9 +416,8 @@ private ILEmitResolverBuilderRuntimeContext GenerateMethodBody(ServiceCallSite c context.Generator.EndExceptionBlock(); - // load value - Ldloc(context.Generator, resultLocal.LocalIndex); + context.Generator.Emit(OpCodes.Ldloc, resultLocal); // return context.Generator.Emit(OpCodes.Ret); } @@ -436,54 +442,8 @@ private static void BeginCaptureDisposable(ILEmitResolverBuilderContext argument private static void EndCaptureDisposable(ILEmitResolverBuilderContext argument) { - // Call CaptureDisposabl we expect calee and arguments to be on the stackcontext.Generator.BeginExceptionBlock + // When calling CaptureDisposable we expect callee and arguments to be on the stackcontext.Generator.BeginExceptionBlock argument.Generator.Emit(OpCodes.Callvirt, ServiceLookupHelpers.CaptureDisposableMethodInfo); } - - private void Ldloc(ILGenerator generator, int index) - { - switch (index) - { - case 0: generator.Emit(OpCodes.Ldloc_0); - return; - case 1: generator.Emit(OpCodes.Ldloc_1); - return; - case 2: generator.Emit(OpCodes.Ldloc_2); - return; - case 3: generator.Emit(OpCodes.Ldloc_3); - return; - } - - if (index < byte.MaxValue) - { - generator.Emit(OpCodes.Ldloc_S, (byte)index); - return; - } - - generator.Emit(OpCodes.Ldloc, index); - } - - private void Stloc(ILGenerator generator, int index) - { - switch (index) - { - case 0: generator.Emit(OpCodes.Stloc_0); - return; - case 1: generator.Emit(OpCodes.Stloc_1); - return; - case 2: generator.Emit(OpCodes.Stloc_2); - return; - case 3: generator.Emit(OpCodes.Stloc_3); - return; - } - - if (index < byte.MaxValue) - { - generator.Emit(OpCodes.Stloc_S, (byte)index); - return; - } - - generator.Emit(OpCodes.Stloc, index); - } } }