X Tutup
using System; using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Threading; namespace Python.Runtime { /// /// Several places in the runtime generate code on the fly to support /// dynamic functionality. The CodeGenerator class manages the dynamic /// assembly used for code generation and provides utility methods for /// certain repetitive tasks. /// internal class CodeGenerator { private readonly AssemblyBuilder aBuilder; private readonly ModuleBuilder mBuilder; const string NamePrefix = "__Python_Runtime_Generated_"; internal CodeGenerator() { var aname = new AssemblyName { Name = GetUniqueAssemblyName(NamePrefix + "Assembly") }; var aa = AssemblyBuilderAccess.Run; aBuilder = Thread.GetDomain().DefineDynamicAssembly(aname, aa); mBuilder = aBuilder.DefineDynamicModule(NamePrefix + "Module"); } /// /// DefineType is a shortcut utility to get a new TypeBuilder. /// internal TypeBuilder DefineType(string name) { var attrs = TypeAttributes.Public; return mBuilder.DefineType(name, attrs); } /// /// DefineType is a shortcut utility to get a new TypeBuilder. /// internal TypeBuilder DefineType(string name, Type basetype) { var attrs = TypeAttributes.Public; return mBuilder.DefineType(name, attrs, basetype); } /// /// Generates code, that copies potentially modified objects in args array /// back to the corresponding byref arguments /// internal static void GenerateMarshalByRefsBack(ILGenerator il, IReadOnlyList argTypes) { // assumes argument array is in loc_0 for (int i = 0; i < argTypes.Count; ++i) { var type = argTypes[i]; if (type.IsByRef) { type = type.GetElementType(); il.Emit(OpCodes.Ldarg, i + 1); // for stobj/stind later at the end il.Emit(OpCodes.Ldloc_0); il.Emit(OpCodes.Ldc_I4, i); il.Emit(OpCodes.Ldelem_Ref); if (type.IsValueType) { il.Emit(OpCodes.Unbox_Any, type); il.Emit(OpCodes.Stobj, type); } else { il.Emit(OpCodes.Castclass, type); il.Emit(OpCodes.Stind_Ref); } } } } static string GetUniqueAssemblyName(string name) { var taken = new HashSet(AppDomain.CurrentDomain .GetAssemblies() .Select(a => a.GetName().Name)); for (int i = 0; i < int.MaxValue; i++) { string candidate = name + i.ToString(CultureInfo.InvariantCulture); if (!taken.Contains(candidate)) return candidate; } throw new NotSupportedException("Too many assemblies"); } } }
X Tutup