예제 #1
0
            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.DefineDynamicMethod <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(),
                });
예제 #2
0
        public static void GetAllFieldOffsetByEmit(Type type)
        {
            var fields = TypeHelper.GetFields(type, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly);

            DynamicAssembly.DefineDynamicMethod <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)();
        }