-
Notifications
You must be signed in to change notification settings - Fork 1
/
MiniRuntime.cs
89 lines (78 loc) · 3.67 KB
/
MiniRuntime.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
namespace Internal.Runtime.CompilerHelpers
{
// A class that the compiler looks for that has helpers to initialize the
// process. The compiler can gracefully handle the helpers not being present,
// but the class itself being absent is unhandled. Let's add an empty class.
unsafe class StartupCodeHelpers
{
//[System.Runtime.RuntimeExport("RhpReversePInvoke2")]
////static void RhpReversePInvoke2(ReversePInvokeFrame *frame) { }
// [System.Runtime.RuntimeExport("RhpReversePInvokeReturn2")]
// static void RhpReversePInvokeReturn2(ReversePInvokeFrame *frame) { }
[System.Runtime.RuntimeExport("RhpPInvoke")]
static void RhpPinvoke(System.IntPtr frame) { }
[System.Runtime.RuntimeExport("RhpPInvokeReturn")]
static void RhpPinvokeReturn(System.IntPtr frame) { }
}
}
namespace System
{
class Array<T> : Array { }
}
namespace System.Runtime
{
// Custom attribute that the compiler understands that instructs it
// to export the method under the given symbolic name.
internal sealed class RuntimeExportAttribute : Attribute
{
public RuntimeExportAttribute(string entry) { }
}
}
namespace System.Runtime.InteropServices
{
// Custom attribute that marks a class as having special "Call" intrinsics.
internal class McgIntrinsicsAttribute : Attribute { }
}
namespace System.Runtime.CompilerServices
{
// A class responsible for running static constructors. The compiler will call into this
// code to ensure static constructors run and that they only run once.
[System.Runtime.InteropServices.McgIntrinsics]
internal static class ClassConstructorRunner
{
private static unsafe IntPtr CheckStaticClassConstructionReturnNonGCStaticBase(ref StaticClassConstructionContext context, IntPtr nonGcStaticBase)
{
EnsureClassConstructorRun(ref context);
return nonGcStaticBase;
}
private static unsafe void EnsureClassConstructorRun(ref StaticClassConstructionContext context)
{
// Very simplified class constructor runner. In real world, the class constructor runner
// would need to be able to deal with potentially multiple threads racing to initialize
// a single class, and would need to be able to deal with potential deadlocks
// between class constructors.
if (context.initialized == 1)
return;
context.initialized = 1;
// Run the class constructor.
Call<int>(context.cctorMethodAddress);
}
// This is a special compiler intrinsic that calls method pointed to by pfn.
[System.Runtime.CompilerServices.Intrinsic]
public static extern T Call<T>(System.IntPtr pfn);
}
// This data structure is a contract with the compiler. It holds the address of a static
// constructor and a flag that specifies whether the constructor already executed.
[System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
public struct StaticClassConstructionContext
{
// Pointer to the code for the static class constructor method. This is initialized by the
// binder/runtime.
public IntPtr cctorMethodAddress;
// Initialization state of the class. This is initialized to 0. Every time managed code checks the
// cctor state the runtime will call the classlibrary's CheckStaticClassConstruction with this context
// structure unless initialized == 1. This check is specific to allow the classlibrary to store more
// than a binary state for each cctor if it so desires.
public int initialized;
}
}