diff options
Diffstat (limited to 'src/mscorlib/src/System/Runtime/CompilerServices/jithelpers.cs')
-rw-r--r-- | src/mscorlib/src/System/Runtime/CompilerServices/jithelpers.cs | 223 |
1 files changed, 223 insertions, 0 deletions
diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/jithelpers.cs b/src/mscorlib/src/System/Runtime/CompilerServices/jithelpers.cs new file mode 100644 index 0000000000..cbafe783ec --- /dev/null +++ b/src/mscorlib/src/System/Runtime/CompilerServices/jithelpers.cs @@ -0,0 +1,223 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +//////////////////////////////////////////////////////////////////////////////// +// JitHelpers +// Low-level Jit Helpers +//////////////////////////////////////////////////////////////////////////////// + +using System; +using System.Threading; +using System.Runtime; +using System.Runtime.Versioning; +using System.Diagnostics.Contracts; +using System.Runtime.InteropServices; +using System.Security; + +namespace System.Runtime.CompilerServices { + + // Wrapper for address of a string variable on stack + internal struct StringHandleOnStack + { + private IntPtr m_ptr; + + internal StringHandleOnStack(IntPtr pString) + { + m_ptr = pString; + } + } + + // Wrapper for address of a object variable on stack + internal struct ObjectHandleOnStack + { + private IntPtr m_ptr; + + internal ObjectHandleOnStack(IntPtr pObject) + { + m_ptr = pObject; + } + } + + // Wrapper for StackCrawlMark + internal struct StackCrawlMarkHandle + { + private IntPtr m_ptr; + + internal StackCrawlMarkHandle(IntPtr stackMark) + { + m_ptr = stackMark; + } + } + + // Helper class to assist with unsafe pinning of arbitrary objects. The typical usage pattern is: + // fixed (byte * pData = &JitHelpers.GetPinningHelper(value).m_data) + // { + // ... pData is what Object::GetData() returns in VM ... + // } + internal class PinningHelper + { + public byte m_data; + } + + [FriendAccessAllowed] + internal static class JitHelpers + { + // The special dll name to be used for DllImport of QCalls + internal const string QCall = "QCall"; + + // Wraps object variable into a handle. Used to return managed strings from QCalls. + // s has to be a local variable on the stack. + [SecurityCritical] + static internal StringHandleOnStack GetStringHandleOnStack(ref string s) + { + return new StringHandleOnStack(UnsafeCastToStackPointer(ref s)); + } + + // Wraps object variable into a handle. Used to pass managed object references in and out of QCalls. + // o has to be a local variable on the stack. + [SecurityCritical] + static internal ObjectHandleOnStack GetObjectHandleOnStack<T>(ref T o) where T : class + { + return new ObjectHandleOnStack(UnsafeCastToStackPointer(ref o)); + } + + // Wraps StackCrawlMark into a handle. Used to pass StackCrawlMark to QCalls. + // stackMark has to be a local variable on the stack. + [SecurityCritical] + static internal StackCrawlMarkHandle GetStackCrawlMarkHandle(ref StackCrawlMark stackMark) + { + return new StackCrawlMarkHandle(UnsafeCastToStackPointer(ref stackMark)); + } + +#if _DEBUG + [SecurityCritical] + [FriendAccessAllowed] + static internal T UnsafeCast<T>(Object o) where T : class + { + T ret = UnsafeCastInternal<T>(o); + Contract.Assert(ret == (o as T), "Invalid use of JitHelpers.UnsafeCast!"); + return ret; + } + + // The IL body of this method is not critical, but its body will be replaced with unsafe code, so + // this method is effectively critical + [SecurityCritical] + static private T UnsafeCastInternal<T>(Object o) where T : class + { + // The body of this function will be replaced by the EE with unsafe code that just returns o!!! + // See getILIntrinsicImplementation for how this happens. + throw new InvalidOperationException(); + } + + static internal int UnsafeEnumCast<T>(T val) where T : struct // Actually T must be 4 byte (or less) enum + { + Contract.Assert(typeof(T).IsEnum + && (Enum.GetUnderlyingType(typeof(T)) == typeof(int) + || Enum.GetUnderlyingType(typeof(T)) == typeof(uint) + || Enum.GetUnderlyingType(typeof(T)) == typeof(short) + || Enum.GetUnderlyingType(typeof(T)) == typeof(ushort) + || Enum.GetUnderlyingType(typeof(T)) == typeof(byte) + || Enum.GetUnderlyingType(typeof(T)) == typeof(sbyte)), + "Error, T must be an 4 byte (or less) enum JitHelpers.UnsafeEnumCast!"); + return UnsafeEnumCastInternal<T>(val); + } + + static private int UnsafeEnumCastInternal<T>(T val) where T : struct // Actually T must be 4 (or less) byte enum + { + // should be return (int) val; but C# does not allow, runtime does this magically + // See getILIntrinsicImplementation for how this happens. + throw new InvalidOperationException(); + } + + static internal long UnsafeEnumCastLong<T>(T val) where T : struct // Actually T must be 8 byte enum + { + Contract.Assert(typeof(T).IsEnum + && (Enum.GetUnderlyingType(typeof(T)) == typeof(long) + || Enum.GetUnderlyingType(typeof(T)) == typeof(ulong)), + "Error, T must be an 8 byte enum JitHelpers.UnsafeEnumCastLong!"); + return UnsafeEnumCastLongInternal<T>(val); + } + + static private long UnsafeEnumCastLongInternal<T>(T val) where T : struct // Actually T must be 8 byte enum + { + // should be return (int) val; but C# does not allow, runtime does this magically + // See getILIntrinsicImplementation for how this happens. + throw new InvalidOperationException(); + } + + // Internal method for getting a raw pointer for handles in JitHelpers. + // The reference has to point into a local stack variable in order so it can not be moved by the GC. + [SecurityCritical] + static internal IntPtr UnsafeCastToStackPointer<T>(ref T val) + { + IntPtr p = UnsafeCastToStackPointerInternal<T>(ref val); + Contract.Assert(IsAddressInStack(p), "Pointer not in the stack!"); + return p; + } + + [SecurityCritical] + static private IntPtr UnsafeCastToStackPointerInternal<T>(ref T val) + { + // The body of this function will be replaced by the EE with unsafe code that just returns val!!! + // See getILIntrinsicImplementation for how this happens. + throw new InvalidOperationException(); + } +#else // _DEBUG + // The IL body of this method is not critical, but its body will be replaced with unsafe code, so + // this method is effectively critical + [SecurityCritical] + [FriendAccessAllowed] + static internal T UnsafeCast<T>(Object o) where T : class + { + // The body of this function will be replaced by the EE with unsafe code that just returns o!!! + // See getILIntrinsicImplementation for how this happens. + throw new InvalidOperationException(); + } + + static internal int UnsafeEnumCast<T>(T val) where T : struct // Actually T must be 4 byte (or less) enum + { + // should be return (int) val; but C# does not allow, runtime does this magically + // See getILIntrinsicImplementation for how this happens. + throw new InvalidOperationException(); + } + + static internal long UnsafeEnumCastLong<T>(T val) where T : struct // Actually T must be 8 byte enum + { + // should be return (long) val; but C# does not allow, runtime does this magically + // See getILIntrinsicImplementation for how this happens. + throw new InvalidOperationException(); + } + + [SecurityCritical] + static internal IntPtr UnsafeCastToStackPointer<T>(ref T val) + { + // The body of this function will be replaced by the EE with unsafe code that just returns o!!! + // See getILIntrinsicImplementation for how this happens. + throw new InvalidOperationException(); + } +#endif // _DEBUG + + // Set the given element in the array without any type or range checks + [SecurityCritical] + [MethodImplAttribute(MethodImplOptions.InternalCall)] + extern static internal void UnsafeSetArrayElement(Object[] target, int index, Object element); + + // Used for unsafe pinning of arbitrary objects. + [System.Security.SecurityCritical] // auto-generated + static internal PinningHelper GetPinningHelper(Object o) + { + // This cast is really unsafe - call the private version that does not assert in debug +#if _DEBUG + return UnsafeCastInternal<PinningHelper>(o); +#else + return UnsafeCast<PinningHelper>(o); +#endif + } + +#if _DEBUG + [SecurityCritical] + [MethodImplAttribute(MethodImplOptions.InternalCall)] + extern static bool IsAddressInStack(IntPtr ptr); +#endif + } +} |