Implement RuntimeHelpers.PrepareMethod/PrepareDelegate for CoreCLR (#16382)
[platform/upstream/coreclr.git] / src / mscorlib / src / System / Runtime / CompilerServices / RuntimeHelpers.cs
1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
4
5 ////////////////////////////////////////////////////////////////////////////////
6 ////////////////////////////////////////////////////////////////////////////////
7 //
8 // RuntimeHelpers
9 //    This class defines a set of static methods that provide support for compilers.
10 //
11 //
12
13 namespace System.Runtime.CompilerServices
14 {
15     using System;
16     using System.Security;
17     using System.Runtime;
18     using System.Runtime.CompilerServices;
19     using System.Runtime.InteropServices;
20     using System.Runtime.ConstrainedExecution;
21     using System.Runtime.Serialization;
22     using System.Threading;
23     using System.Runtime.Versioning;
24
25     public static class RuntimeHelpers
26     {
27         // Exposed here as a more appropriate place than on FormatterServices itself,
28         // which is a high level reflection heavy type.
29         public static Object GetUninitializedObject(Type type)
30         {
31             return FormatterServices.GetUninitializedObject(type);
32         }
33
34         [MethodImplAttribute(MethodImplOptions.InternalCall)]
35         public static extern void InitializeArray(Array array, RuntimeFieldHandle fldHandle);
36
37         // GetObjectValue is intended to allow value classes to be manipulated as 'Object'
38         // but have aliasing behavior of a value class.  The intent is that you would use
39         // this function just before an assignment to a variable of type 'Object'.  If the
40         // value being assigned is a mutable value class, then a shallow copy is returned 
41         // (because value classes have copy semantics), but otherwise the object itself
42         // is returned.  
43         //
44         // Note: VB calls this method when they're about to assign to an Object
45         // or pass it as a parameter.  The goal is to make sure that boxed 
46         // value types work identical to unboxed value types - ie, they get 
47         // cloned when you pass them around, and are always passed by value.  
48         // Of course, reference types are not cloned.
49         //
50         [MethodImplAttribute(MethodImplOptions.InternalCall)]
51         public static extern Object GetObjectValue(Object obj);
52
53         // RunClassConstructor causes the class constructor for the given type to be triggered
54         // in the current domain.  After this call returns, the class constructor is guaranteed to
55         // have at least been started by some thread.  In the absence of class constructor
56         // deadlock conditions, the call is further guaranteed to have completed.
57         //
58         // This call will generate an exception if the specified class constructor threw an 
59         // exception when it ran. 
60
61         [MethodImplAttribute(MethodImplOptions.InternalCall)]
62         private static extern void _RunClassConstructor(RuntimeType type);
63
64         public static void RunClassConstructor(RuntimeTypeHandle type)
65         {
66             _RunClassConstructor(type.GetRuntimeType());
67         }
68
69         // RunModuleConstructor causes the module constructor for the given type to be triggered
70         // in the current domain.  After this call returns, the module constructor is guaranteed to
71         // have at least been started by some thread.  In the absence of module constructor
72         // deadlock conditions, the call is further guaranteed to have completed.
73         //
74         // This call will generate an exception if the specified module constructor threw an 
75         // exception when it ran. 
76
77         [MethodImplAttribute(MethodImplOptions.InternalCall)]
78         private static extern void _RunModuleConstructor(System.Reflection.RuntimeModule module);
79
80         public static void RunModuleConstructor(ModuleHandle module)
81         {
82             _RunModuleConstructor(module.GetRuntimeModule());
83         }
84
85
86         [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
87         internal static extern void _CompileMethod(IRuntimeMethodInfo method);
88
89         [MethodImplAttribute(MethodImplOptions.InternalCall)]
90         private static unsafe extern void _PrepareMethod(IRuntimeMethodInfo method, IntPtr* pInstantiation, int cInstantiation);
91
92         public static void PrepareMethod(RuntimeMethodHandle method) 
93         {
94             unsafe
95             {
96                 _PrepareMethod(method.GetMethodInfo(), null, 0);
97             }
98         }
99
100         public static void PrepareMethod(RuntimeMethodHandle method, RuntimeTypeHandle[] instantiation)
101         {
102             unsafe
103             {
104                 int length;
105                 IntPtr[] instantiationHandles = RuntimeTypeHandle.CopyRuntimeTypeHandles(instantiation, out length);
106                 fixed (IntPtr* pInstantiation = instantiationHandles)
107                 {
108                     _PrepareMethod(method.GetMethodInfo(), pInstantiation, length);
109                     GC.KeepAlive(instantiation);
110                 }
111             }
112         }
113
114         public static void PrepareContractedDelegate(Delegate d) { }
115
116         [MethodImplAttribute(MethodImplOptions.InternalCall)]
117         public static extern void PrepareDelegate(Delegate d);
118
119         [MethodImplAttribute(MethodImplOptions.InternalCall)]
120         public static extern int GetHashCode(Object o);
121
122         [MethodImplAttribute(MethodImplOptions.InternalCall)]
123         public new static extern bool Equals(Object o1, Object o2);
124
125         public static int OffsetToStringData
126         {
127             // This offset is baked in by string indexer intrinsic, so there is no harm
128             // in getting it baked in here as well.
129             [System.Runtime.Versioning.NonVersionable]
130             get
131             {
132                 // Number of bytes from the address pointed to by a reference to
133                 // a String to the first 16-bit character in the String.  Skip 
134                 // over the MethodTable pointer, & String 
135                 // length.  Of course, the String reference points to the memory 
136                 // after the sync block, so don't count that.  
137                 // This property allows C#'s fixed statement to work on Strings.
138                 // On 64 bit platforms, this should be 12 (8+4) and on 32 bit 8 (4+4).
139 #if BIT64
140                 return 12;
141 #else // 32
142                 return 8;
143 #endif // BIT64
144             }
145         }
146
147         // This method ensures that there is sufficient stack to execute the average Framework function.
148         // If there is not enough stack, then it throws System.InsufficientExecutionStackException.
149         // Note: this method is not part of the CER support, and is not to be confused with ProbeForSufficientStack
150         // below.
151         [MethodImplAttribute(MethodImplOptions.InternalCall)]
152         public static extern void EnsureSufficientExecutionStack();
153
154         // This method ensures that there is sufficient stack to execute the average Framework function.
155         // If there is not enough stack, then it return false.
156         // Note: this method is not part of the CER support, and is not to be confused with ProbeForSufficientStack
157         // below.
158         [MethodImplAttribute(MethodImplOptions.InternalCall)]
159         public static extern bool TryEnsureSufficientExecutionStack();
160
161         public static void ProbeForSufficientStack()
162         {
163         }
164
165         // This method is a marker placed immediately before a try clause to mark the corresponding catch and finally blocks as
166         // constrained. There's no code here other than the probe because most of the work is done at JIT time when we spot a call to this routine.
167         public static void PrepareConstrainedRegions()
168         {
169             ProbeForSufficientStack();
170         }
171
172         // When we detect a CER with no calls, we can point the JIT to this non-probing version instead
173         // as we don't need to probe.
174         public static void PrepareConstrainedRegionsNoOP()
175         {
176         }
177
178         public delegate void TryCode(Object userData);
179
180         public delegate void CleanupCode(Object userData, bool exceptionThrown);
181
182         [MethodImplAttribute(MethodImplOptions.InternalCall)]
183         public static extern void ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, Object userData);
184
185         internal static void ExecuteBackoutCodeHelper(Object backoutCode, Object userData, bool exceptionThrown)
186         {
187             ((CleanupCode)backoutCode)(userData, exceptionThrown);
188         }
189
190         /// <returns>true if given type is reference type or value type that contains references</returns>
191         static public bool IsReferenceOrContainsReferences<T>()
192         {
193             // The body of this function will be replaced by the EE with unsafe code!!!
194             // See getILIntrinsicImplementation for how this happens.
195             throw new InvalidOperationException();
196         }
197     }
198 }
199