diff options
author | Alexander Kyte <alexander.kyte@xamarin.com> | 2015-04-01 00:18:40 +0300 |
---|---|---|
committer | Duncan Mak <duncan.mak@xamarin.com> | 2015-05-27 00:14:56 +0300 |
commit | 7cec9613b4cc2abb10be61c1279606ee8d070669 (patch) | |
tree | 6bbfcff8a45e28f3001130e19470e54c71867178 | |
parent | d136b7923f60ef59bced6fad1c9a6c0c3b8c616a (diff) |
[runtime] Don't set flag to skip future initialization on half-baked classeshotfix-29639
-rw-r--r-- | mono/metadata/class.c | 8 | ||||
-rw-r--r-- | mono/tests/Makefile.am | 1 | ||||
-rw-r--r-- | mono/tests/dynamic-generic-size.cs | 61 |
3 files changed, 69 insertions, 1 deletions
diff --git a/mono/metadata/class.c b/mono/metadata/class.c index b70897dccb0..1296ed12123 100644 --- a/mono/metadata/class.c +++ b/mono/metadata/class.c @@ -6049,7 +6049,13 @@ mono_generic_class_get_class (MonoGenericClass *gclass) mono_generic_class_setup_parent (klass, gklass); if (gclass->is_dynamic) { - klass->inited = 1; + /* + * We don't need to do any init workf with unbaked typebuilders. Generic instances created at this point will be later unregistered and/or fixed. + * This is to avoid work that would probably give wrong results as fields change as we build the TypeBuilder. + * See remove_instantiations_of_and_ensure_contents in reflection.c and its usage in reflection.c to understand the fixup stage of SRE banking. + */ + if (!gklass->wastypebuilder) + klass->inited = 1; mono_class_setup_supertypes (klass); diff --git a/mono/tests/Makefile.am b/mono/tests/Makefile.am index 6a1a76a8fd2..8b0ab538b69 100644 --- a/mono/tests/Makefile.am +++ b/mono/tests/Makefile.am @@ -307,6 +307,7 @@ BASE_TEST_CS_SRC= \ generic-typedef.2.cs \ generic-marshalbyref.2.cs \ generic-xdomain.2.cs \ + dynamic-generic-size.cs \ bug-431413.2.cs \ bug-459285.2.cs \ generic-virtual-invoke.2.cs \ diff --git a/mono/tests/dynamic-generic-size.cs b/mono/tests/dynamic-generic-size.cs new file mode 100644 index 00000000000..3a26f728d10 --- /dev/null +++ b/mono/tests/dynamic-generic-size.cs @@ -0,0 +1,61 @@ +using System; +using System.Threading; +using System.Reflection; +using System.Reflection.Emit; +using System.Collections.Generic; + +namespace GenericSize +{ + class GenericSize + { + static int Iterations = 10000; + static AssemblyBuilder assembly; + static ModuleBuilder module; + static string ASSEMBLY_NAME = "MonoTests.System.Reflection.Emit.TypeBuilderTest"; + + static void SetUp () + { + AssemblyName assemblyName = new AssemblyName (); + assemblyName.Name = ASSEMBLY_NAME; + + assembly = + Thread.GetDomain ().DefineDynamicAssembly (assemblyName, AssemblyBuilderAccess.Run); + + module = assembly.DefineDynamicModule ("module1"); + } + + static int Main() + { + SetUp (); + + TypeBuilder tb = module.DefineType ("Test", TypeAttributes.Public); + tb.DefineGenericParameters ("T"); + var tb_ctor = tb.DefineDefaultConstructor (MethodAttributes.Public); + + var tb2 = module.DefineType ("Test2", TypeAttributes.Public); + var g0 = tb2.DefineGenericParameters ("T"); + + var mb = tb2.DefineMethod ("Foo", MethodAttributes.Public | MethodAttributes.Static, typeof (object), new Type [0]); + + var il = mb.GetILGenerator(); + il.Emit(OpCodes.Newobj, TypeBuilder.GetConstructor (tb.MakeGenericType (g0), tb_ctor)); + il.Emit(OpCodes.Ret); + + var t1 = tb.CreateType (); + var t2 = tb2.CreateType (); + + var ginst = t2.MakeGenericType (typeof (string)); + var method = ginst.GetMethod ("Foo", BindingFlags.Public | BindingFlags.Static); + + var lst = new List<Object>(); + + for (int i = 0; i < GenericSize.Iterations; i++) { + lst.Add (method.Invoke (null, null)); + if (i % 15 == 0) + GC.Collect(); + } + + return 0; + } + } +} |