X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmini%2Fobjects.cs;h=a16871b226c11a4b0c8f148328e4a6dafffd529f;hb=1e726ce7a38a92860acab28f4427813d2ba14c13;hp=8cabc1005ece63519cfb962176a4a0b12b086b2f;hpb=7015b812166d0992223b5dc4421deab637500265;p=mono.git diff --git a/mono/mini/objects.cs b/mono/mini/objects.cs index 8cabc1005ec..a16871b226c 100644 --- a/mono/mini/objects.cs +++ b/mono/mini/objects.cs @@ -1,4 +1,5 @@ using System; +using System.Text; using System.Reflection; using System.Runtime.InteropServices; using System.Runtime.CompilerServices; @@ -99,13 +100,25 @@ enum SampleEnum { C } +struct Alpha { + public long a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v; +} + +struct Beta { + public Alpha a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v; +} + +struct Gamma { + public Beta a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v; +} + class Tests { - static int Main () { - return TestDriver.RunTests (typeof (Tests)); + public static int Main (string[] args) { + return TestDriver.RunTests (typeof (Tests), args); } - static int test_0_return () { + public static int test_0_return () { Simple s; s.a = 1; s.b = 2; @@ -114,14 +127,14 @@ class Tests { return s.a - 1; } - static int test_0_string_access () { + public static int test_0_string_access () { string s = "Hello"; if (s [1] != 'e') return 1; return 0; } - static int test_0_string_virtual_call () { + public static int test_0_string_virtual_call () { string s = "Hello"; string s2 = s.ToString (); if (s2 [1] != 'e') @@ -129,23 +142,23 @@ class Tests { return 0; } - static int test_0_iface_call () { + public static int test_0_iface_call () { string s = "Hello"; object o = ((ICloneable)s).Clone (); return 0; } - static int test_5_newobj () { + public static int test_5_newobj () { Sample s = new Sample (5); return s.a; } - static int test_4_box () { + public static int test_4_box () { object obj = 4; return (int)obj; } - static int test_0_enum_unbox () { + public static int test_0_enum_unbox () { SampleEnum x = SampleEnum.A; object o = x; @@ -166,7 +179,7 @@ class Tests { return r; } - static int test_3_return_struct () { + public static int test_3_return_struct () { Simple v = get_simple (1); if (v.a != 1) @@ -185,7 +198,7 @@ class Tests { return get_simple (v); } - static int test_2_return_struct_virtual () { + public static int test_2_return_struct_virtual () { Tests t = new Tests (); Simple v = t.v_get_simple (2); @@ -216,7 +229,7 @@ class Tests { return 0; } - static int test_5_pass_struct () { + public static int test_5_pass_struct () { Simple v = get_simple (1); if (receive_simple (7, v, 9) != 0) return 0; @@ -225,6 +238,14 @@ class Tests { return 5; } + static Simple s_v; + public static int test_5_pass_static_struct () { + s_v = get_simple (1); + if (receive_simple (7, s_v, 9) != 0) + return 0; + return 5; + } + // Test alignment of small structs static Small get_small (byte v) { @@ -248,20 +269,184 @@ class Tests { return 0; } - static int test_5_pass_small_struct () { + static int receive_small_sparc_many_args (int a, int a2, int a3, int a4, int a5, int a6, Small v, int b) { + if (v.b1 != 1) + return 1; + if (v.b2 != 2) + return 2; + return 0; + } + + public static int test_5_pass_small_struct () { Small v = get_small (1); if (receive_small (7, v, 9) != 0) return 0; if (receive_small (7, get_small (1), 9) != 0) return 1; + if (receive_small_sparc_many_args (1, 2, 3, 4, 5, 6, v, 9) != 0) + return 2; v = return_small (v); if (v.b1 != 1) - return 2; - if (v.b2 != 2) return 3; + if (v.b2 != 2) + return 4; return 5; } + // 64-bits, 32-bit aligned + struct struct1 { + public int a; + public int b; + }; + + static int check_struct1(struct1 x) { + if (x.a != 1) + return 1; + if (x.b != 2) + return 2; + return 0; + } + + static int pass_struct1(int a, int b, struct1 x) { + if (a != 3) + return 3; + if (b != 4) + return 4; + return check_struct1(x); + } + + static int pass_struct1(int a, struct1 x) { + if (a != 3) + return 3; + return check_struct1(x); + } + + static int pass_struct1(struct1 x) { + return check_struct1(x); + } + + public static int test_0_struct1_args () { + int r; + struct1 x; + + x.a = 1; + x.b = 2; + if ((r = check_struct1(x)) != 0) + return r; + if ((r = pass_struct1(x)) != 0) + return r + 10; + if ((r = pass_struct1(3, x)) != 0) + return r + 20; + if ((r = pass_struct1(3, 4, x)) != 0) + return r + 30; + return 0; + } + + // 64-bits, 64-bit aligned + struct struct2 { + public long a; + }; + + static int check_struct2(struct2 x) { + if (x.a != 1) + return 1; + return 0; + } + + static int pass_struct2(int a, int b, int c, struct2 x) { + if (a != 3) + return 3; + if (b != 4) + return 4; + if (c != 5) + return 5; + return check_struct2(x); + } + + static int pass_struct2(int a, int b, struct2 x) { + if (a != 3) + return 3; + if (b != 4) + return 4; + return check_struct2(x); + } + + static int pass_struct2(int a, struct2 x) { + if (a != 3) + return 3; + return check_struct2(x); + } + + static int pass_struct2(struct2 x) { + return check_struct2(x); + } + + public static int test_0_struct2_args () { + int r; + struct2 x; + + x.a = 1; + if ((r = check_struct2(x)) != 0) + return r; + if ((r = pass_struct2(x)) != 0) + return r + 10; + if ((r = pass_struct2(3, x)) != 0) + return r + 20; + if ((r = pass_struct2(3, 4, x)) != 0) + return r + 30; + if ((r = pass_struct2(3, 4, 5, x)) != 0) + return r + 40; + return 0; + } + + // 128 bits + struct Struct3 { + public long i, j, k, l; + } + + static int pass_struct3 (int i, int j, int k, int l, int m, int n, int o, int p, Struct3 s, int q) { + if (s.i + s.j + s.k + s.l != 10) + return 1; + else + return 0; + } + + public static int test_0_struct3_args () { + Struct3 s = new Struct3 (); + s.i = 1; + s.j = 2; + s.k = 3; + s.l = 4; + + return pass_struct3 (1, 2, 3, 4, 5, 6, 7, 8, s, 9); + } + + // Struct with unaligned size on 64 bit machines + struct Struct4 { + public int i, j, k, l, m; + public int i1, i2, i3, i4, i5, i6; + } + + static int pass_struct4 (Struct4 s) { + if (s.i + s.j + s.k + s.l + s.m != 15) + return 1; + else + return 0; + } + + public static int test_0_struct4_args () { + Struct4 s = new Struct4 (); + s.i = 1; + s.j = 2; + s.k = 3; + s.l = 4; + s.m = 5; + + return pass_struct4 (s); + } + + + struct AStruct { public int i; @@ -275,13 +460,13 @@ class Tests { } // Test that vtypes are unboxed during a virtual call - static int test_44_unbox_trampoline () { + public static int test_44_unbox_trampoline () { AStruct s = new AStruct (44); object o = s; return o.GetHashCode (); } - static int test_0_unbox_trampoline2 () { + public static int test_0_unbox_trampoline2 () { int i = 12; object o = i; @@ -295,7 +480,7 @@ class Tests { } // Test fields with big offsets - static int test_0_fields_with_big_offsets () { + public static int test_0_fields_with_big_offsets () { StructWithBigOffsets s = new StructWithBigOffsets (); StructWithBigOffsets s2 = new StructWithBigOffsets (); @@ -365,7 +550,7 @@ class Tests { } - static int test_0_seektest () { + public static int test_0_seektest () { TestRegA t = new TestRegA (); return (int)t.Seek (0); } @@ -378,7 +563,7 @@ class Tests { class Duper: Super { } - static int test_0_null_cast () { + public static int test_0_null_cast () { object o = null; Super s = (Super)o; @@ -386,7 +571,7 @@ class Tests { return 0; } - static int test_0_super_cast () { + public static int test_0_super_cast () { Duper d = new Duper (); Super sup = d; Object o = d; @@ -408,7 +593,7 @@ class Tests { return 0; } - static int test_0_super_cast_array () { + public static int test_0_super_cast_array () { Duper[] d = new Duper [0]; Super[] sup = d; Object[] o = d; @@ -430,7 +615,7 @@ class Tests { return 0; } - static int test_0_multi_array_cast () { + public static int test_0_multi_array_cast () { Duper[,] d = new Duper [1, 1]; object[,] o = d; @@ -444,7 +629,7 @@ class Tests { return 0; } - static int test_0_vector_array_cast () { + public static int test_0_vector_array_cast () { Array arr1 = Array.CreateInstance (typeof (int), new int[] {1}, new int[] {0}); Array arr2 = Array.CreateInstance (typeof (int), new int[] {1}, new int[] {10}); @@ -468,10 +653,14 @@ class Tests { if (arr2 is int[]) return 4; + int [,] [] arr3 = new int [1, 1] []; + object o = arr3; + int [,] [] arr4 = (int [,] [])o; + return 0; } - static int test_0_enum_array_cast () { + public static int test_0_enum_array_cast () { TypeCode[] tc = new TypeCode [0]; object[] oa; ValueType[] vta; @@ -512,7 +701,7 @@ class Tests { return 0; } - static int test_0_more_cast_corner_cases () { + public static int test_0_more_cast_corner_cases () { ValueType[] vta = new ValueType [0]; Enum[] ea = new Enum [0]; Array a = vta; @@ -590,7 +779,7 @@ class Tests { return 0; } - static int test_0_cast_iface_array () { + public static int test_0_cast_iface_array () { object o = new ICloneable [0]; object o2 = new Duper [0]; object t; @@ -646,7 +835,7 @@ class Tests { return ((day-1) + temp + (365* (year-1)) + ((year-1)/4) - ((year-1)/100) + ((year-1)/400)); } - static int test_719162_complex_div () { + public static int test_719162_complex_div () { int adays = AbsoluteDays (1970, 1, 1); return adays; } @@ -661,7 +850,7 @@ class Tests { return 5; } - static int test_2_static_delegate () { + public static int test_2_static_delegate () { GetIntDel del = new GetIntDel (return4); int v = del (); if (v != 4) @@ -669,7 +858,7 @@ class Tests { return 2; } - static int test_2_instance_delegate () { + public static int test_2_instance_delegate () { Tests t = new Tests (); GetIntDel del = new GetIntDel (t.return5); int v = del (); @@ -678,7 +867,7 @@ class Tests { return 2; } - static int test_1_store_decimal () { + public static int test_1_store_decimal () { decimal[,] a = {{1}}; if (a[0,0] != 1m) @@ -686,7 +875,7 @@ class Tests { return 1; } - static int test_2_intptr_stobj () { + public static int test_2_intptr_stobj () { System.IntPtr [] arr = { new System.IntPtr () }; if (arr [0] != (System.IntPtr)0) @@ -702,7 +891,7 @@ class Tests { * Test that evaluation of complex arguments does not overwrite the * arguments already in outgoing registers. */ - static int test_155_regalloc () { + public static int test_155_regalloc () { int a = 10; int b = 10; @@ -722,7 +911,7 @@ class Tests { return true; } - static int test_2_large_struct_pass () + public static int test_2_large_struct_pass () { Large a, b, c, d; a = new Large (); @@ -843,7 +1032,7 @@ class Tests { static uint dum_de_dum = 1; - static int test_0_long_arg_opt () + public static int test_0_long_arg_opt () { return Foo (0x1234567887654321, dum_de_dum); } @@ -859,7 +1048,7 @@ class Tests { return 0; } - static int test_0_long_ret_opt () + public static int test_0_long_ret_opt () { ulong x = X (); if (x != 0x1234567887654321) @@ -887,9 +1076,10 @@ class Tests { counter = 10; return true; } - static int test_0_cond_branch_side_effects () { + public static int test_0_cond_branch_side_effects () { counter = 5; - if (WriteStuff()); + if (WriteStuff()) { + } if (counter == 10) return 0; return 1; @@ -939,7 +1129,7 @@ ncells ) { } } - static int test_0_calls_opcode_emulation () { + public static int test_0_calls_opcode_emulation () { // Test that emulated opcodes do not clobber arguments already in // out registers checked { @@ -949,25 +1139,25 @@ ncells ) { return 0; } - static int test_0_intrins_string_length () { + public static int test_0_intrins_string_length () { string s = "ABC"; return (s.Length == 3) ? 0 : 1; } - static int test_0_intrins_string_chars () { + public static int test_0_intrins_string_chars () { string s = "ABC"; return (s [0] == 'A' && s [1] == 'B' && s [2] == 'C') ? 0 : 1; } - static int test_0_intrins_object_gettype () { + public static int test_0_intrins_object_gettype () { object o = 1; return (o.GetType () == typeof (int)) ? 0 : 1; } - static int test_0_intrins_object_gethashcode () { + public static int test_0_intrins_object_gethashcode () { object o = new Object (); return (o.GetHashCode () == o.GetHashCode ()) ? 0 : 1; @@ -976,40 +1166,434 @@ ncells ) { class FooClass { } - static int test_0_intrins_object_ctor () { + public static int test_0_intrins_object_ctor () { object o = new FooClass (); return (o != null) ? 0 : 1; } - static int test_0_intrins_array_rank () { + public static int test_0_intrins_array_rank () { int[,] a = new int [10, 10]; return (a.Rank == 2) ? 0 : 1; } - static int test_0_intrins_array_length () { + public static int test_0_intrins_array_length () { int[,] a = new int [10, 10]; Array a2 = a; return (a2.Length == 100) ? 0 : 1; } - static int test_0_intrins_runtimehelpers_offset_to_string_data () { + public static int test_0_intrins_runtimehelpers_offset_to_string_data () { int i = RuntimeHelpers.OffsetToStringData; return i - i; } + public static int test_0_intrins_string_setchar () { + StringBuilder sb = new StringBuilder ("ABC"); + + sb [1] = 'D'; + + return sb.ToString () == "ADC" ? 0 : 1; + } + public class Bar { bool allowLocation = true; Foo f = new Foo (); } - static int test_0_regress_78990_unaligned_structs () { + public static int test_0_regress_78990_unaligned_structs () { new Bar (); return 0; } + + public static unsafe int test_97_negative_index () { + char[] arr = new char[] {'a', 'b'}; + fixed (char *p = arr) { + char *i = p + 2; + char a = i[-2]; + return a; + } + } + + /* bug #82281 */ + public static int test_0_unsigned_right_shift_imm0 () { + uint temp = 0; + byte[] data = new byte[256]; + for (int i = 0; i < 1; i ++) + temp = (uint)(data[temp >> 24] | data[temp >> 0]); + return 0; + } + + class Foo2 { + public virtual int foo () { + return 0; + } + } + + sealed class Bar2 : Foo2 { + public override int foo () { + return 0; + } + } + + public static int test_0_abcrem_check_this_removal () { + Bar2 b = new Bar2 (); + + // The check_this generated here by the JIT should be removed + b.foo (); + + return 0; + } + + static int invoke_twice (Bar2 b) { + b.foo (); + // The check_this generated here by the JIT should be removed + b.foo (); + + return 0; + } + + public static int test_0_abcrem_check_this_removal2 () { + Bar2 b = new Bar2 (); + + invoke_twice (b); + + return 0; + } + + /* #346563 */ + public static int test_0_array_access_64_bit () { + int[] arr2 = new int [10]; + for (int i = 0; i < 10; ++i) + arr2 [i] = i; + string s = "ABCDEFGH"; + + byte[] arr = new byte [4]; + arr [0] = 252; + arr [1] = 255; + arr [2] = 255; + arr [3] = 255; + + int len = arr [0] | (arr [1] << 8) | (arr [2] << 16) | (arr [3] << 24); + int len2 = - (len + 2); + + // Test array and string access with a 32 bit value whose upper 32 bits are + // undefined + // len2 = 3 + if (arr2 [len2] != 2) + return 1; + if (s [len2] != 'C') + return 2; + return 0; + } + + public static float return_float () { + return 1.4e-45f; + } + + public static int test_0_float_return_spill () { + // The return value of return_float () is spilled because of the + // boxing call + object o = return_float (); + float f = return_float (); + return (float)o == f ? 0 : 1; + } + + class R4Holder { + public static float pi = 3.14f; + + public float float_field; + } + + public static int test_0_ldsfld_soft_float () { + if (R4Holder.pi == 3.14f) + return 0; + else + return 1; + } + + public static int test_0_ldfld_stfld_soft_float () { + R4Holder h = new R4Holder (); + h.float_field = 3.14f; + + if (h.float_field == 3.14f) + return 0; + else + return 1; + } + + class R4HolderRemote : MarshalByRefObject { + public static float pi = 3.14f; + + public float float_field; + } + + public static int test_0_ldfld_stfld_soft_float_remote () { + R4HolderRemote h = new R4HolderRemote (); + h.float_field = 3.14f; + + if (h.float_field == 3.14f) + return 0; + else + return 1; + } + + public static int test_0_locals_soft_float () { + float f = 0.0f; + + f = 3.14f; + + if (f == 3.14f) + return 0; + else + return 1; + } + + struct AStruct2 { + public int i; + public int j; + } + + static float pass_vtype_return_float (AStruct2 s) { + return s.i + s.j == 6 ? 1.0f : -1.0f; + } + + public static int test_0_vtype_arg_soft_float () { + return pass_vtype_return_float (new AStruct2 () { i = 2, j = 4 }) > 0.0 ? 0 : 1; + } + + static int range_check_strlen (int i, string s) { + if (i < 0 || i > s.Length) + return 1; + else + return 0; + } + + public static int test_0_range_check_opt () { + if (range_check_strlen (0, "A") != 0) + return 1; + if (range_check_strlen (1, "A") != 0) + return 2; + if (range_check_strlen (2, "A") != 1) + return 3; + if (range_check_strlen (-100, "A") != 1) + return 4; + return 0; + } + + static int test_0_array_get_set_soft_float () { + float[,] arr = new float [2, 2]; + arr [0, 0] = 256f; + return arr [0, 0] == 256f ? 0 : 1; + } + + //repro for #506915 + struct Bug506915 { public int val; } + static int test_2_ldobj_stobj_optization () + { + int i = 99; + var a = new Bug506915 (); + var b = new Bug506915 (); + if (i.GetHashCode () == 99) + i = 44; + var array = new Bug506915 [2]; + array [0].val = 2; + array [1] = (i == 0) ? a : array [0]; + + return array [1].val; + } + + /* mcs can't compile this (#646744) */ +#if FALSE + static void InitMe (out Gamma noMercyWithTheStack) { + noMercyWithTheStack = new Gamma (); + } + + static int FunNoInline () { + int x = 99; + if (x > 344 && x < 22) + return 333; + return x; + } + + static float DoNothingButDontInline (float a, int b) { + if (b > 0) + return a; + else if (b < 0 && b > 10) + return 444.0f; + return a; + } + + /* + * The local register allocator emits loadr8_membase and storer8_membase + * to do spilling. This code is generated after mono_arch_lowering_pass so + * mono_arch_output_basic_block must know how to deal with big offsets. + * This only happens because the call in middle forces the temp for "(float)obj" + * to be spilled. + */ + public static int test_0_float_load_and_store_with_big_offset () + { + object obj = 1.0f; + Gamma noMercyWithTheStack; + float res; + + InitMe (out noMercyWithTheStack); + + res = DoNothingButDontInline ((float)obj, FunNoInline ()); + + if (!(res == 1.0f)) + return 1; + return 0; + } +#endif + + struct VTypePhi { + public int i; + } + + static int vtype_phi (VTypePhi v1, VTypePhi v2, bool first) { + VTypePhi v = first ? v1 : v2; + + return v.i; + } + + static int test_0_vtype_phi () + { + VTypePhi v1 = new VTypePhi () { i = 1 }; + VTypePhi v2 = new VTypePhi () { i = 2 }; + + if (vtype_phi (v1, v2, true) != 1) + return 1; + if (vtype_phi (v1, v2, false) != 2) + return 2; + + return 0; + } + + [MethodImplAttribute (MethodImplOptions.NoInlining)] + static void UseValue (int index) + { + } + + [MethodImplAttribute (MethodImplOptions.NoInlining)] + static bool IsFalse () + { + return false; + } + + static int test_0_llvm_moving_faulting_loads () + { + int[] indexes = null; + + if (IsFalse ()) { + indexes = new int[0]; + } + + while (IsFalse ()) { + UseValue (indexes[0]); + UseValue (indexes[0]); + } + + return 0; + } + + public static bool flag; + + class B { + + internal static B[] d; + + static B () { + flag = true; + } + } + + [MethodImplAttribute (MethodImplOptions.NoInlining)] + static int regress_679467_inner () { + if (flag == true) + return 1; + var o = B.d; + var o2 = B.d; + return 0; + } + + /* + * FIXME: This fails with AOT #703317. + */ + /* + static int test_0_multiple_cctor_calls_regress_679467 () { + flag = false; + return regress_679467_inner (); + } + */ + + static int test_0_char_ctor () { + string s = new String (new char[] { 'A', 'B' }, 0, 1); + return 0; + } + + static object mInstance = null; + + [MethodImpl(MethodImplOptions.Synchronized)] + public static object getInstance() { + if (mInstance == null) + mInstance = new object(); + return mInstance; + } + + static int test_0_synchronized () { + getInstance (); + return 0; + } + + struct BStruct { + public Type t; + } + + class Del { + public static BStruct foo () { + return new BStruct () { t = typeof (T) }; + } + } + + delegate BStruct ADelegate (); + + static int test_0_regress_10601 () { + var act = (ADelegate)(Del.foo); + BStruct b = act (); + if (b.t != typeof (string)) + return 1; + return 0; + } + + static int test_0_regress_11058 () { + int foo = -252674008; + int foo2 = (int)(foo ^ 0xF0F0F0F0); // = 28888 + var arr = new byte[foo2].Length; + return 0; + } + + public static void do_throw () { + throw new Exception (); + } + + [MethodImplAttribute (MethodImplOptions.NoInlining)] + static void empty () { + } + + // #11297 + public static int test_0_llvm_inline_throw () { + try { + empty (); + } catch (Exception ex) { + do_throw (); + } + + return 0; + } }