diff options
Diffstat (limited to 'tests/src/JIT/Methodical/largeframes/skip7/skippage7.cs')
-rw-r--r-- | tests/src/JIT/Methodical/largeframes/skip7/skippage7.cs | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/tests/src/JIT/Methodical/largeframes/skip7/skippage7.cs b/tests/src/JIT/Methodical/largeframes/skip7/skippage7.cs new file mode 100644 index 0000000000..0949ca7db5 --- /dev/null +++ b/tests/src/JIT/Methodical/largeframes/skip7/skippage7.cs @@ -0,0 +1,101 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// Exercise stack probing after localloc, on architectures with fixed outgoing argument +// space. Some implementations did not probe after re-establishing the outgoing argument +// space after a localloc. +// +// We need to create a large enough outgoing argument space to skip a guard page. To actually +// see a problem on Windows, we need to skip 3 guard pages. Since structs are passed by +// reference on arm64/x64, we have to have a huge number of small arguments: over 1536 +// "long" arguments. For arm32, structs are passed by value, so we can just pass a very large +// struct. This test case is for the arm32 case. + +namespace BigFrames +{ + + [StructLayout(LayoutKind.Explicit)] + public struct LargeStruct + { + [FieldOffset(0)] + public int i1; + [FieldOffset(65512)] + public int i2; + } + + public class Test + { + public static int iret = 1; + + [MethodImplAttribute(MethodImplOptions.NoInlining)] + public static void BigArgSpace(LargeStruct s) + { + long result = s.i1 + s.i2; + Console.Write("BigArgSpace: "); + Console.WriteLine(result); + } + + [MethodImplAttribute(MethodImplOptions.NoInlining)] + public static void SmallArgSpace(long i1, long i2, long i3, long i4, long i5, long i6, long i7, long i8, long i9, long i10) + { + long result = i1 + i2 + i3 + i4 + i5 + i6 + i7 + i8 + i9 + i10; + Console.Write("SmallArgSpace: "); + Console.WriteLine(result); + } + + [MethodImplAttribute(MethodImplOptions.NoInlining)] + public unsafe static void Test1(int n) + { + Console.WriteLine("Enter Test1"); + LargeStruct s = new LargeStruct(); + s.i1 = 7; + s.i2 = 9; + BigArgSpace(s); + + // Localloc some space; this moves the outgoing argument space. + + if (n < 1) n = 1; + int* a = stackalloc int[n * 4096]; + a[0] = 7; + int i; + + for (i=1; i < 5; ++i) + { + a[i] = i + a[i - 1]; + } + + // Now call a function that touches the potentially un-probed + // outgoing argument space. + + SmallArgSpace(1, 2, 3, 4, 5, 6, 7, 8, 9, a[4]); + + iret = 100; + } + + [MethodImplAttribute(MethodImplOptions.NoInlining)] + public static void Escape(ref LargeStruct s) + { + } + + public static int Main() + { + Test1(1); // force JIT of this + Test1(80); + + if (iret == 100) + { + Console.WriteLine("TEST PASSED"); + } + else + { + Console.WriteLine("TEST FAILED"); + } + return iret; + } + } +} |