@@ -8218,25 +8218,33 @@ public static T GetFirst<T>(this IEnumerable<T> source)
82188218 [RequiresUnreferencedCode(Trimming.Message)]
82198219 public static class ILGeneratorTools
82208220 {
8221+ /// <summary>Configuration option to disable the pooling</summary>
8222+ public static bool DisableILGeneratorPooling;
8223+ /// <summary>Configuration option to disable the ILGenerator Emit debug output</summary>
8224+ public static bool DisableDemit;
8225+
82218226#if DEMIT
82228227 [MethodImpl((MethodImplOptions)256)]
82238228 public static void Demit(this ILGenerator il, OpCode opcode, [CallerMemberName] string emitterName = "", [CallerLineNumber] int emitterLine = 0)
82248229 {
82258230 il.Emit(opcode);
8231+ if (DisableDemit) return;
82268232 Debug.WriteLine($"{opcode} -- {emitterName}:{emitterLine}");
82278233 }
82288234
82298235 [MethodImpl((MethodImplOptions)256)]
82308236 public static void Demit(this ILGenerator il, OpCode opcode, Type type, [CallerMemberName] string emitterName = null, [CallerLineNumber] int emitterLine = 0)
82318237 {
82328238 il.Emit(opcode, type);
8239+ if (DisableDemit) return;
82338240 Debug.WriteLine($"{opcode} {type.ToCode(stripNamespace: true)} -- {emitterName}:{emitterLine}");
82348241 }
82358242
82368243 [MethodImpl((MethodImplOptions)256)]
82378244 public static void Demit(this ILGenerator il, OpCode opcode, FieldInfo value, [CallerMemberName] string emitterName = null, [CallerLineNumber] int emitterLine = 0)
82388245 {
82398246 il.Emit(opcode, value);
8247+ if (DisableDemit) return;
82408248
82418249 var declType = value.DeclaringType?.ToCode(stripNamespace: true) ?? "";
82428250 var fieldType = value.FieldType.ToCode(stripNamespace: true);
@@ -8247,6 +8255,7 @@ public static void Demit(this ILGenerator il, OpCode opcode, FieldInfo value, [C
82478255 public static void Demit(this ILGenerator il, OpCode opcode, MethodInfo value, [CallerMemberName] string emitterName = null, [CallerLineNumber] int emitterLine = 0)
82488256 {
82498257 il.Emit(opcode, value);
8258+ if (DisableDemit) return;
82508259
82518260 var declType = value.DeclaringType?.ToCode(stripNamespace: true) ?? "";
82528261 var retType = value.ReturnType.ToCode(stripNamespace: true);
@@ -8260,6 +8269,7 @@ public static void Demit(this ILGenerator il, OpCode opcode, MethodInfo value, [
82608269 public static void Demit(this ILGenerator il, OpCode opcode, ConstructorInfo value, [CallerMemberName] string emitterName = null, [CallerLineNumber] int emitterLine = 0)
82618270 {
82628271 il.Emit(opcode, value);
8272+ if (DisableDemit) return;
82638273
82648274 var declType = value.DeclaringType?.ToCode(stripNamespace: true) ?? "";
82658275 var signature = value.ToString();
@@ -8273,6 +8283,7 @@ public static void Demit(this ILGenerator il, OpCode opcode, Label value,
82738283 [CallerArgumentExpression("value")] string valueName = null, [CallerMemberName] string emitterName = null, [CallerLineNumber] int emitterLine = 0)
82748284 {
82758285 il.Emit(opcode, value);
8286+ if (DisableDemit) return;
82768287 Debug.WriteLine($"{opcode} {valueName ?? value.ToString()} -- {emitterName}:{emitterLine}");
82778288 }
82788289
@@ -8281,62 +8292,71 @@ public static void DmarkLabel(this ILGenerator il, Label value,
82818292 [CallerArgumentExpression("value")] string valueName = null, [CallerMemberName] string emitterName = null, [CallerLineNumber] int emitterLine = 0)
82828293 {
82838294 il.MarkLabel(value);
8295+ if (DisableDemit) return;
82848296 Debug.WriteLine($"{valueName ?? value.ToString()} -- {emitterName}:{emitterLine}: ");
82858297 }
82868298
82878299 [MethodImpl((MethodImplOptions)256)]
82888300 public static void Demit(this ILGenerator il, OpCode opcode, byte value, [CallerMemberName] string emitterName = null, [CallerLineNumber] int emitterLine = 0)
82898301 {
82908302 il.Emit(opcode, value);
8303+ if (DisableDemit) return;
82918304 Debug.WriteLine($"{opcode} {value} -- {emitterName}:{emitterLine}");
82928305 }
82938306
82948307 [MethodImpl((MethodImplOptions)256)]
82958308 public static void Demit(this ILGenerator il, OpCode opcode, sbyte value, [CallerMemberName] string emitterName = null, [CallerLineNumber] int emitterLine = 0)
82968309 {
82978310 il.Emit(opcode, value);
8311+ if (DisableDemit) return;
82988312 Debug.WriteLine($"{opcode} {value} -- {emitterName}:{emitterLine}");
82998313 }
83008314
83018315 [MethodImpl((MethodImplOptions)256)]
83028316 public static void Demit(this ILGenerator il, OpCode opcode, short value, [CallerMemberName] string emitterName = null, [CallerLineNumber] int emitterLine = 0)
83038317 {
83048318 il.Emit(opcode, value);
8319+ if (DisableDemit) return;
83058320 Debug.WriteLine($"{opcode} {value} -- {emitterName}:{emitterLine}");
83068321 }
83078322
83088323 [MethodImpl((MethodImplOptions)256)]
83098324 public static void Demit(this ILGenerator il, OpCode opcode, int value, [CallerMemberName] string emitterName = null, [CallerLineNumber] int emitterLine = 0)
83108325 {
83118326 il.Emit(opcode, value);
8327+ if (DisableDemit) return;
83128328 Debug.WriteLine($"{opcode} {value} -- {emitterName}:{emitterLine}");
83138329 }
83148330
83158331 [MethodImpl((MethodImplOptions)256)]
83168332 public static void Demit(this ILGenerator il, OpCode opcode, long value, [CallerMemberName] string emitterName = null, [CallerLineNumber] int emitterLine = 0)
83178333 {
83188334 il.Emit(opcode, value);
8335+ if (DisableDemit) return;
83198336 Debug.WriteLine($"{opcode} {value} -- {emitterName}:{emitterLine}");
83208337 }
83218338
83228339 [MethodImpl((MethodImplOptions)256)]
83238340 public static void Demit(this ILGenerator il, OpCode opcode, float value, [CallerMemberName] string emitterName = null, [CallerLineNumber] int emitterLine = 0)
83248341 {
83258342 il.Emit(opcode, value);
8343+ if (DisableDemit) return;
83268344 Debug.WriteLine($"{opcode} {value} -- {emitterName}:{emitterLine}");
83278345 }
83288346
83298347 [MethodImpl((MethodImplOptions)256)]
83308348 public static void Demit(this ILGenerator il, OpCode opcode, double value, [CallerMemberName] string emitterName = null, [CallerLineNumber] int emitterLine = 0)
83318349 {
83328350 il.Emit(opcode, value);
8351+ if (DisableDemit) return;
83338352 Debug.WriteLine($"{opcode} {value} -- {emitterName}:{emitterLine}");
83348353 }
83358354
83368355 [MethodImpl((MethodImplOptions)256)]
83378356 public static void Demit(this ILGenerator il, string value, OpCode opcode, [CallerMemberName] string emitterName = null, [CallerLineNumber] int emitterLine = 0)
83388357 {
83398358 il.Emit(opcode, value);
8359+ if (DisableDemit) return;
83408360 Debug.WriteLine($"{opcode} {value} -- {emitterName}:{emitterLine}");
83418361 }
83428362
@@ -8422,10 +8442,10 @@ public static ILGenerator RentPooledOrNewILGenerator(DynamicMethod dynMethod, Ty
84228442
84238443 /// <summary>Should be called only after call to DynamicMethod.CreateDelegate</summary>
84248444 [MethodImpl((MethodImplOptions)256)]
8425- public static void FreePooledILGenerator(DynamicMethod _ , ILGenerator il)
8445+ public static void FreePooledILGenerator(DynamicMethod dynMethod , ILGenerator il)
84268446 {
84278447 // todo: @wip #475 might be required to avoid the undefined behavior when the previous DynamicMethod is still linked to the wrong ILGenerator
8428- // IlGeneratorField .SetValue(dynMethod, null);
8448+ // ILGeneratorField .SetValue(dynMethod, null);
84298449
84308450 if (DynamicMethodHacks.ReuseDynamicILGenerator != null)
84318451 _pooledILGenerator = il;
@@ -8453,18 +8473,27 @@ public static ILGenerator RentPooledOrNewILGenerator(DynamicMethod dynMethod, Ty
84538473 internal static SignatureHelper _pooledSignatureHelper;
84548474#pragma warning restore CS0649
84558475
8476+ internal static FieldInfo ILGeneratorField;
8477+ internal static Type DynamicILGeneratorType;
8478+
84568479 static DynamicMethodHacks()
84578480 {
84588481 const BindingFlags instanceNonPublic = BindingFlags.Instance | BindingFlags.NonPublic;
84598482 const BindingFlags instancePublic = BindingFlags.Instance | BindingFlags.Public;
84608483 const BindingFlags staticNonPublic = BindingFlags.Static | BindingFlags.NonPublic;
84618484 const BindingFlags staticPublic = BindingFlags.Static | BindingFlags.Public;
84628485
8463- var _iLGeneratorField = typeof(DynamicMethod).GetField("_ilGenerator", instanceNonPublic);
8464- if (_iLGeneratorField == null)
8465- return; // nothing to look here
8486+ ILGeneratorField = typeof(DynamicMethod).GetField("_ilGenerator", instanceNonPublic);
8487+ if (ILGeneratorField == null)
8488+ return; // nothing to do here
8489+
8490+ DynamicILGeneratorType = ILGeneratorField.FieldType;
84668491
8467- var DynamicILGeneratorType = _iLGeneratorField.FieldType;
8492+ // Avoid demit polluting the output of the the initialization phase
8493+ var prevDemitValue = ILGeneratorTools.DisableDemit;
8494+ ILGeneratorTools.DisableDemit = true;
8495+
8496+ if (!ILGeneratorTools.DisableILGeneratorPooling)
84688497 {
84698498 // ## 1. Reuse the DynamicILGenerator
84708499 //
@@ -8756,7 +8785,7 @@ internal static SignatureHelper GetMethodSigHelper(
87568785 il.Emit(OpCodes.Call, SignatureHelper_GetSignatureMethod);
87578786 ExpressionCompiler.EmittingVisitor.EmitStoreLocalVariable(il, sigBytesVar);
87588787
8759- // return the signature helper to the pool
8788+ // free the signature helper to the pool
87608789 ExpressionCompiler.EmittingVisitor.EmitLoadLocalVariable(il, sigHelperVar);
87618790 il.Emit(OpCodes.Stsfld, pooledSignatureHelperField);
87628791
@@ -8821,7 +8850,7 @@ internal byte[] GetSignature(bool appendEndOfSig)
88218850 // store the reused ILGenerator to
88228851 il.Emit(OpCodes.Ldarg_1);
88238852 il.Emit(OpCodes.Ldarg_2);
8824- il.Emit(OpCodes.Stfld, _iLGeneratorField );
8853+ il.Emit(OpCodes.Stfld, ILGeneratorField );
88258854
88268855 il.Emit(OpCodes.Ret);
88278856
@@ -8872,9 +8901,9 @@ public virtual LocalBuilder DeclareLocal(Type localType, bool pinned)
88728901
88738902 // looking for the `SignatureHelper.AddArgument(Type argument, bool pinned)`
88748903 var typeAndBoolParamTypes = ExpressionCompiler.RentPooledOrNewParamTypes(typeof(Type), typeof(bool));
8875- var SignaturHelper_AddArgumentMethod = typeof(SignatureHelper).GetMethod("AddArgument", typeAndBoolParamTypes);
8904+ var SignatureHelper_AddArgumentMethod = typeof(SignatureHelper).GetMethod("AddArgument", typeAndBoolParamTypes);
88768905 ExpressionCompiler.FreePooledParamTypes(typeAndBoolParamTypes);
8877- if (SignaturHelper_AddArgumentMethod == null)
8906+ if (SignatureHelper_AddArgumentMethod == null)
88788907 goto endOfGetNextVar;
88798908
88808909 // our own helper - always available
@@ -8884,14 +8913,15 @@ public virtual LocalBuilder DeclareLocal(Type localType, bool pinned)
88848913 var paramTypes = ExpressionCompiler.RentPooledOrNewParamTypes(typeof(ExpressionCompiler.ArrayClosure), typeof(ILGenerator), typeof(Type));
88858914 var dynMethod = new DynamicMethod(string.Empty, typeof(int), paramTypes, typeof(ExpressionCompiler.ArrayClosure), true);
88868915
8887- var il = RentPooledOrNewILGenerator(dynMethod, typeof(int), paramTypes);
8916+ // it does not use the pooled il generator here, to isolate this variable hack from the il generator pooling hack and for the better problem diagnostics
8917+ var il = dynMethod.GetILGenerator(); // todo: @wip set the stream size
88888918
88898919 // emitting `il.m_localSignature.AddArgument(type);`
88908920 il.Emit(OpCodes.Ldarg_1); // load `il` argument (arg_0 is the empty closure object)
88918921 il.Emit(OpCodes.Ldfld, m_localSignatureField);
88928922 il.Emit(OpCodes.Ldarg_2); // load `type` argument
88938923 il.Emit(OpCodes.Ldc_I4_0); // load `pinned: false` argument
8894- il.Emit(OpCodes.Call, SignaturHelper_AddArgumentMethod );
8924+ il.Emit(OpCodes.Call, SignatureHelper_AddArgumentMethod );
88958925
88968926 // emitting `return PostInc(ref il.LocalCount);`
88978927 il.Emit(OpCodes.Ldarg_1); // load `il` argument
@@ -8903,11 +8933,13 @@ public virtual LocalBuilder DeclareLocal(Type localType, bool pinned)
89038933 GetNextLocalVarLocation = (Func<ILGenerator, Type, int>)
89048934 dynMethod.CreateDelegate(typeof(Func<ILGenerator, Type, int>), ExpressionCompiler.EmptyArrayClosure);
89058935
8906- FreePooledILGenerator(dynMethod, il);
89078936 ExpressionCompiler.FreePooledParamTypes(paramTypes);
89088937 endOfGetNextVar:;
89098938 }
89108939
8940+ // Restore the demit
8941+ ILGeneratorTools.DisableDemit = prevDemitValue;
8942+
89118943 // ## 3 TBD
89128944 //
89138945 // todo: @perf do batch Emit by manually calling `EnsureCapacity` once then `InternalEmit` multiple times
0 commit comments