X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmini%2Fgenerics.cs;h=19282df514e273e5f2da45e6208e835255b34b58;hb=6b104c2bc41fe0e94488f0ef461319cb3a512aa3;hp=372f08b45887b89c42be17e42ea6f1dc1fc087b6;hpb=13d6157ebffa499d2f6e78a94af12b75bfad4cd9;p=mono.git diff --git a/mono/mini/generics.cs b/mono/mini/generics.cs index 372f08b4588..19282df514e 100644 --- a/mono/mini/generics.cs +++ b/mono/mini/generics.cs @@ -1,5 +1,7 @@ using System; using System.Collections.Generic; +using System.Linq; +using System.Runtime.CompilerServices; class Tests { @@ -31,9 +33,9 @@ class Tests { } } - static int Main () + static int Main (string[] args) { - return TestDriver.RunTests (typeof (Tests)); + return TestDriver.RunTests (typeof (Tests), args); } public static int test_1_nullable_unbox () @@ -117,6 +119,33 @@ class Tests { return ldelem_any (arr); } + public static T return_ref (ref T t) { + return t; + } + + public static T ldelema_any (T[] arr) { + return return_ref (ref arr [0]); + } + + public static int test_0_ldelema () { + string[] arr = new string [1]; + + arr [0] = "Hello"; + + if (ldelema_any (arr) == "Hello") + return 0; + else + return 1; + } + + public static T[,] newarr_multi () { + return new T [1, 1]; + } + + public static int test_0_newarr_multi_dim () { + return newarr_multi ().GetType () == typeof (string[,]) ? 0 : 1; + } + interface ITest { void Foo (); @@ -177,6 +206,7 @@ class Tests { return 0; } + [Category ("!FULLAOT")] public static int test_0_generic_get_value_optimization_int () { int[] x = new int[] {100, 200}; @@ -213,6 +243,10 @@ class Tests { return 0; } + public static int test_0_nullable_ldflda () { + return GenericClass.BIsAClazz == false ? 0 : 1; + } + public struct GenericStruct { public T t; @@ -258,6 +292,15 @@ class Tests { { return x [index]; } + + protected static T NullB = default(T); + private static Nullable _BIsA = null; + public static bool BIsAClazz { + get { + _BIsA = false; + return _BIsA.Value; + } + } } public class MRO : MarshalByRefObject { @@ -290,9 +333,11 @@ class Tests { return 0; } + // FIXME: + [Category ("!FULLAOT")] public static int test_0_generic_virtual_call_on_vtype_unbox () { object o = new Object (); - IMyHandler h = new Handler(o); + IFoo h = new Handler(o); if (h.Bar () != o) return 1; @@ -350,7 +395,363 @@ class Tests { return 0; } - public class Foo + public static int test_0_ldvirtftn_generic_method () { + new Tests ().ldvirtftn (); + + return the_type == typeof (string) ? 0 : 1; + } + + public static int test_0_throw_dead_this () { + new Foo ("").throw_dead_this (); + return 0; + } + + struct S {} + + public static int test_0_inline_infinite_polymorphic_recursion () { + f(0); + + return 0; + } + + private static void f(int i) { + if(i==42) f>(i); + } + + // This cannot be made to work with full-aot, since there it is impossible to + // statically determine that Foo.Bar is needed, the code only + // references IFoo.Bar + [Category ("!FULLAOT")] + public static int test_0_generic_virtual_on_interfaces () { + Foo.count1 = 0; + Foo.count2 = 0; + Foo.count3 = 0; + + IFoo f = new Foo (""); + for (int i = 0; i < 1000; ++i) { + f.Bar (); + f.Bar (); + f.NonGeneric (); + } + + if (Foo.count1 != 1000) + return 1; + if (Foo.count2 != 1000) + return 2; + if (Foo.count3 != 1000) + return 3; + + VirtualInterfaceCallFromGenericMethod (f); + + return 0; + } + + public static int test_0_generic_virtual_on_interfaces_ref () { + Foo.count1 = 0; + Foo.count2 = 0; + Foo.count3 = 0; + Foo.count4 = 0; + + IFoo f = new Foo (""); + for (int i = 0; i < 1000; ++i) { + f.Bar (); + f.Bar (); + f.NonGeneric (); + } + + if (Foo.count2 != 1000) + return 2; + if (Foo.count3 != 1000) + return 3; + if (Foo.count4 != 1000) + return 4; + + return 0; + } + + //repro for #505375 + [Category ("!FULLAOT")] + public static int test_2_cprop_bug () { + int idx = 0; + int a = 1; + var cmp = System.Collections.Generic.Comparer.Default ; + if (cmp.Compare (a, 0) > 0) + a = 0; + do { idx++; } while (cmp.Compare (idx - 1, a) == 0); + return idx; + } + + enum MyEnumUlong : ulong { + Value_2 = 2 + } + + public static int test_0_regress_550964_constrained_enum_long () { + MyEnumUlong a = MyEnumUlong.Value_2; + MyEnumUlong b = MyEnumUlong.Value_2; + + return Pan (a, b) ? 0 : 1; + } + + static bool Pan (T a, T b) + { + return a.Equals (b); + } + + public class XElement { + public string Value { + get; set; + } + } + + public static int test_0_fullaot_linq () { + var allWords = new XElement [] { new XElement { Value = "one" } }; + var filteredWords = allWords.Where(kw => kw.Value.StartsWith("T")); + return filteredWords.Count (); + } + + public static int test_0_fullaot_comparer_t () { + var l = new SortedList (); + return l.Count; + } + + public static int test_0_fullaot_comparer_t_2 () { + var l = new Dictionary (); + return l.Count; + } + + static void enumerate (IEnumerable arr) { + foreach (var o in arr) + ; + int c = ((ICollection)arr).Count; + } + + /* Test that treating arrays as generic collections works with full-aot */ + public static int test_0_fullaot_array_wrappers () { + Tests[] arr = new Tests [10]; + enumerate (arr); + return 0; + } + + static int cctor_count = 0; + + public abstract class Beta + { + static Beta() + { + cctor_count ++; + } + } + + public class Gamma : Beta + { + static Gamma() + { + } + } + + // #519336 + public static int test_2_generic_class_init_gshared_ctor () { + new Gamma(); + new Gamma(); + + return cctor_count; + } + + static int cctor_count2 = 0; + + class ServiceController { + static ServiceController () { + cctor_count2 ++; + } + + public ServiceController () { + } + } + + static ServiceController Create() { + return new ServiceController(); + } + + // #631409 + public static int test_2_generic_class_init_gshared_ctor_from_gshared () { + Create (); + Create (); + + return cctor_count2; + } + + public static Type get_type () { + return typeof (T); + } + + public static int test_0_gshared_delegate_rgctx () { + Func t = new Func (get_type); + + if (t () == typeof (string)) + return 0; + else + return 1; + } + + // Creating a delegate from a generic method from gshared code + public static int test_0_gshared_delegate_from_gshared () { + if (gshared_delegate_from_gshared () != 0) + return 1; + if (gshared_delegate_from_gshared () != 0) + return 2; + return 0; + } + + public static int gshared_delegate_from_gshared () { + Func t = new Func (get_type); + + return t () == typeof (T) ? 0 : 1; + } + + public static int test_0_marshalbyref_call_from_gshared_virt_elim () { + /* Calling a virtual method from gshared code which is changed to a nonvirt call */ + Class1 o = new Class1 (); + o.Do (new Class2 ()); + return 0; + } + + class Pair { + public static KeyValuePair make_pair (TKey key, TValue value) + { + return new KeyValuePair (key, value); + } + + public delegate TRet Transform (TKey key, TValue value); + } + + public static int test_0_bug_620864 () { + var d = new Pair.Transform> (Pair.make_pair); + + var p = d ("FOO", typeof (int)); + if (p.Key != "FOO" || p.Value != typeof (int)) + return 1; + + return 0; + } + + + struct RecStruct { + public void foo (RecStruct> baz) { + } + } + + public static int test_0_infinite_generic_recursion () { + // Check that the AOT compile can deal with infinite generic recursion through + // parameter types + RecStruct bla; + + return 0; + } + + struct FooStruct { + } + + bool IsNull2 (object value) where T : struct { + T? item = (T?) value; + + if (item.HasValue) + return false; + + return true; + } + + public static int test_0_full_aot_nullable_unbox_from_gshared_code () { + if (!new Tests ().IsNull2 (null)) + return 1; + if (new Tests ().IsNull2 (new FooStruct ())) + return 2; + return 0; + } + + public static int test_0_partial_sharing () { + if (PartialShared1 (new List (), 1) != typeof (string)) + return 1; + if (PartialShared1 (new List (), 1) != typeof (Tests)) + return 2; + if (PartialShared2 (new List (), 1) != typeof (int)) + return 3; + if (PartialShared2 (new List (), 1) != typeof (int)) + return 4; + return 0; + } + + public static int test_6_partial_sharing_linq () { + var messages = new List (); + + messages.Add (new Message () { MessageID = 5 }); + messages.Add (new Message () { MessageID = 6 }); + + return messages.Max(i => i.MessageID); + } + + public static int test_0_partial_shared_method_in_nonshared_class () { + var c = new Class1 (); + return (c.Foo (5).GetType () == typeof (Class1)) ? 0 : 1; + } + + class Message { + public int MessageID { + get; set; + } + } + + public static Type PartialShared1 (List list, K k) { + return typeof (T); + } + + public static Type PartialShared2 (List list, K k) { + return typeof (K); + } + + public class Class1 { + public virtual void Do (Class2 t) { + t.Foo (); + } + + public virtual object Foo (T t) { + return new Class1 (); + } + } + + public interface IFace1 { + void Foo (); + } + + public class Class2 : MarshalByRefObject, IFace1 { + public void Foo () { + } + } + + + + public static void VirtualInterfaceCallFromGenericMethod (IFoo f) { + f.Bar (); + } + + public static Type the_type; + + public void ldvirtftn () { + Foo binding = new Foo (default (T)); + + binding.GenericEvent += event_handler; + binding.fire (); + } + + public virtual void event_handler (Foo sender) { + the_type = typeof (T); + } + + public interface IFoo { + void NonGeneric (); + object Bar(); + } + + public class Foo : IFoo { public Foo(T1 t1) { @@ -373,24 +774,61 @@ class Tests { } } + public void throw_dead_this () { + try { + new SomeClass().ThrowAnException(); + } + catch { + } + } + public T1 get_default () { return default (T1); } readonly T1 m_t1; - } - public interface IMyHandler { - object Bar(); + public delegate void GenericEventHandler (Foo sender); + + public event GenericEventHandler GenericEvent; + + public void fire () { + GenericEvent (this); + } + + public static int count1, count2, count3, count4; + + public void NonGeneric () { + count3 ++; + } + + public object Bar () { + if (typeof (T) == typeof (int)) + count1 ++; + else if (typeof (T) == typeof (string)) + count2 ++; + else if (typeof (T) == typeof (object)) + count4 ++; + return null; + } } - struct Handler : IMyHandler { + public class SomeClass { + public void ThrowAnException() { + throw new Exception ("Something went wrong"); + } + } + + struct Handler : IFoo { object o; public Handler(object o) { this.o = o; } + public void NonGeneric () { + } + public object Bar() { return o; } @@ -412,4 +850,134 @@ class Tests { static T Unbox (object o) { return (T) o; } + + interface IDefaultRetriever + { + T GetDefault(); + } + + class DefaultRetriever : IDefaultRetriever + { + [MethodImpl(MethodImplOptions.Synchronized)] + public T GetDefault() + { + return default(T); + } + } + + [Category ("!FULLAOT")] + public static int test_0_regress_668095_synchronized_gshared () { + return DoSomething (new DefaultRetriever ()); + } + + static int DoSomething(IDefaultRetriever foo) { + int result = foo.GetDefault(); + return result; + } + + class Response { + } + + public static int test_0_687865_isinst_with_cache_wrapper () { + object o = new object (); + if (o is Action>) + return 1; + else + return 0; + } + + enum DocType { + One, + Two, + Three + } + + class Doc { + public string Name { + get; set; + } + + public DocType Type { + get; set; + } + } + + // #2155 + public static int test_0_fullaot_sflda_cctor () { + List documents = new List(); + documents.Add(new Doc { Name = "Doc1", Type = DocType.One } ); + documents.Add(new Doc { Name = "Doc2", Type = DocType.Two } ); + documents.Add(new Doc { Name = "Doc3", Type = DocType.Three } ); + documents.Add(new Doc { Name = "Doc4", Type = DocType.One } ); + documents.Add(new Doc { Name = "Doc5", Type = DocType.Two } ); + documents.Add(new Doc { Name = "Doc6", Type = DocType.Three } ); + documents.Add(new Doc { Name = "Doc7", Type = DocType.One } ); + documents.Add(new Doc { Name = "Doc8", Type = DocType.Two } ); + documents.Add(new Doc { Name = "Doc9", Type = DocType.Three } ); + + List categories = documents.Select(d=>d.Type).Distinct().ToList().OrderBy(d => d).ToList(); + foreach(DocType cat in categories) { + List catDocs = documents.Where(d => d.Type == cat).OrderBy(d => d.Name).ToList(); + } + return 0; + } + + class A { } + + static List sources = new List(); + + // #6112 + public static int test_0_fullaot_imt () { + sources.Add(null); + sources.Add(null); + + int a = sources.Count; + var enumerator = sources.GetEnumerator() as IEnumerator; + + while (enumerator.MoveNext()) + { + object o = enumerator.Current; + } + + return 0; + } + + struct Record : Foo2.IRecord { + int counter; + int Foo2.IRecord.DoSomething () { + return counter++; + } + } + + class Foo2 where T : Foo2.IRecord { + public interface IRecord { + int DoSomething (); + } + + public static int Extract (T[] t) { + return t[0].DoSomething (); + } + } + + class Foo3 where T : IComparable { + public static int CompareTo (T[] t) { + // This is a constrained call to Enum.CompareTo () + return t[0].CompareTo (t [0]); + } + } + + public static int test_1_regress_constrained_iface_call_7571 () { + var r = new Record [10]; + Foo2.Extract (r); + return Foo2.Extract (r); + } + + enum ConstrainedEnum { + Val = 1 + } + + public static int test_0_regress_constrained_iface_call_enum () { + var r = new ConstrainedEnum [10]; + return Foo3.CompareTo (r); + } }