protected override IntPtr InternalGetStaticsBasePointer(StaticsBaseBlock statics_base_block) { if (get_statics_base_pointer_func == null) { var fields = typeof(T).GetFields(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly); FieldInfo gc_static_field_info = null; FieldInfo non_gc_static_field_info = null; FieldInfo thread_gc_static_field_info = null; FieldInfo thread_non_gc_static_field_info = null; foreach (var item in fields) { if (item.IsLiteral) { continue; } switch (TypeHelper.GetStaticBaseBlock(item)) { case StaticsBaseBlock.GC: gc_static_field_info ??= item; break; case StaticsBaseBlock.NonGC: non_gc_static_field_info ??= item; break; case StaticsBaseBlock.ThreadGC: thread_gc_static_field_info ??= item; break; case StaticsBaseBlock.ThreadNonGC: thread_non_gc_static_field_info ??= item; break; } } if (gc_static_field_info == null && non_gc_static_field_info == null && thread_gc_static_field_info == null && thread_non_gc_static_field_info == null) { return(IntPtr.Zero); } get_statics_base_pointer_func = DynamicAssembly.BuildDynamicMethod <GetStaticsBasePointerFunc>((dym, ilGen) => { if (gc_static_field_info != null) { ilGen.LoadArgument(0); ilGen.LoadFieldAddress(gc_static_field_info); ilGen.LoadConstant(TypeHelper.OffsetOf(gc_static_field_info)); ilGen.Subtract(); ilGen.StoreValue(typeof(IntPtr)); } if (non_gc_static_field_info != null) { ilGen.LoadArgument(1); ilGen.LoadFieldAddress(non_gc_static_field_info); ilGen.LoadConstant(TypeHelper.OffsetOf(non_gc_static_field_info)); ilGen.Subtract(); ilGen.StoreValue(typeof(IntPtr)); } if (thread_gc_static_field_info != null) { ilGen.LoadArgument(2); ilGen.LoadFieldAddress(thread_gc_static_field_info); ilGen.LoadConstant(TypeHelper.OffsetOf(thread_gc_static_field_info)); ilGen.Subtract(); ilGen.StoreValue(typeof(IntPtr)); } if (thread_non_gc_static_field_info != null) { ilGen.LoadArgument(3); ilGen.LoadFieldAddress(thread_non_gc_static_field_info); ilGen.LoadConstant(TypeHelper.OffsetOf(thread_non_gc_static_field_info)); ilGen.Subtract(); ilGen.StoreValue(typeof(IntPtr)); } ilGen.Return(); }, typeof(T).Module, true); } get_statics_base_pointer_func( out var gc_statics_base_pointer, out var non_gc_statics_base_pointer, out var thread_gc_statics_base_pointer, out var thread_non_gc_statics_base_pointer ); return(statics_base_block switch { StaticsBaseBlock.GC => gc_statics_base_pointer, StaticsBaseBlock.NonGC => non_gc_statics_base_pointer, StaticsBaseBlock.ThreadGC => thread_gc_statics_base_pointer, StaticsBaseBlock.ThreadNonGC => thread_non_gc_statics_base_pointer, _ => throw new NotSupportedException(), });
public static void GetAllFieldOffsetByEmit(Type type) { var fields = TypeHelper.GetFields(type, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly); DynamicAssembly.BuildDynamicMethod <Action>((_, ilGen) => { var obj_address = ilGen.DeclareLocal(typeof(IntPtr)); var gc_static_base_address = ilGen.DeclareLocal(typeof(IntPtr)); var non_gc_static_base_address = ilGen.DeclareLocal(typeof(IntPtr)); ilGen.LoadConstant((IntPtr)(-1)); // max ptr ilGen.StoreLocal(gc_static_base_address); ilGen.LoadConstant((IntPtr)(-1)); // max ptr ilGen.StoreLocal(non_gc_static_base_address); /* 分配一个模拟实例 */ ilGen.LoadConstant(8); ilGen.LocalAllocate(); ilGen.StoreLocal(obj_address); foreach (var item in fields) { /* 跳过常量 */ if (item.IsLiteral) { continue; } if (item.IsStatic) { if (item.FieldType.IsValueType) { ilGen.LoadFieldAddress(item); ilGen.LoadLocal(non_gc_static_base_address); ilGen.Call(MethodOf <IntPtr, IntPtr, IntPtr>(Min)); ilGen.StoreLocal(non_gc_static_base_address); } else { ilGen.LoadFieldAddress(item); ilGen.LoadLocal(gc_static_base_address); ilGen.Call(MethodOf <IntPtr, IntPtr, IntPtr>(Min)); ilGen.StoreLocal(gc_static_base_address); } } } foreach (var item in fields) { /* 跳过常量 */ if (item.IsLiteral) { continue; } /* 加载字段 Id */ ilGen.LoadConstant(item.FieldHandle.Value); if (item.IsStatic) { // Offset = Address - Base Address. if (item.FieldType.IsValueType) { ilGen.LoadFieldAddress(item); ilGen.LoadLocal(non_gc_static_base_address); ilGen.Subtract(); } else { ilGen.LoadFieldAddress(item); ilGen.LoadLocal(gc_static_base_address); ilGen.Subtract(); } } else { /* Offset = Address - Instance. */ ilGen.LoadLocal(obj_address); ilGen.LoadFieldAddress(item); ilGen.LoadLocal(obj_address); ilGen.Subtract(); /* if class then Offset -= sizeof TypeHandle. */ if (type.IsClass) { ilGen.LoadConstant(TypeHelper.GetObjectValueByteOffset()); ilGen.Subtract(); } } ilGen.ConvertInt32(); ilGen.Call(MethodOf <IntPtr, int>(Add)); } ilGen.Return(); }, type.Module, true)(); }