Welcome to mirror list, hosted at ThFree Co, Russian Federation.

MethodBaseGetCurrentMethodThunk.cs « Stubs « IL « TypeSystem « Common « tools « coreclr « src - github.com/dotnet/runtime.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 82a729dc3eb2dbc1372ad4225d3ffbac826c0dd9 (plain)
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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using Internal.TypeSystem;

using Debug = System.Diagnostics.Debug;

namespace Internal.IL.Stubs
{
    /// <summary>
    /// Thunk that replaces calls to MethodBase.GetCurrentMethod in user code. The purpose of the thunk
    /// is to LDTOKEN the method considered "current method" and call into the class library to
    /// retrieve the associated MethodBase object instance.
    /// </summary>
    internal partial class MethodBaseGetCurrentMethodThunk : ILStubMethod
    {
        public MethodBaseGetCurrentMethodThunk(MethodDesc method)
        {
            Debug.Assert(method.IsTypicalMethodDefinition);

            Method = method;
            Signature = new MethodSignature(MethodSignatureFlags.Static, 0,
                Context.SystemModule.GetKnownType("System.Reflection", "MethodBase"), TypeDesc.EmptyTypes);
        }

        public override TypeSystemContext Context
        {
            get
            {
                return Method.Context;
            }
        }

        public MethodDesc Method
        {
            get;
        }

        public override string Name
        {
            get
            {
                return Method.Name;
            }
        }

        public override string DiagnosticName
        {
            get
            {
                return Method.DiagnosticName;
            }
        }

        public override TypeDesc OwningType
        {
            get
            {
                return Method.OwningType;
            }
        }

        public override MethodSignature Signature
        {
            get;
        }

        public override MethodIL EmitIL()
        {
            ILEmitter emit = new ILEmitter();
            ILCodeStream codeStream = emit.NewCodeStream();

            codeStream.Emit(ILOpcode.ldtoken, emit.NewToken(Method));

            string helperName;
            if (Method.OwningType.HasInstantiation)
            {
                codeStream.Emit(ILOpcode.ldtoken, emit.NewToken(Method.OwningType));
                helperName = "GetCurrentMethodGeneric";
            }
            else
                helperName = "GetCurrentMethodNonGeneric";

            MethodDesc classlibHelper = Context.GetHelperEntryPoint("ReflectionHelpers", helperName);

            codeStream.Emit(ILOpcode.call, emit.NewToken(classlibHelper));
            codeStream.Emit(ILOpcode.ret);

            return emit.Link(this);
        }
    }

    internal class MethodBaseGetCurrentMethodThunkCache
    {
        private Unifier _cache;

        public MethodBaseGetCurrentMethodThunkCache()
        {
            _cache = new Unifier();
        }

        public MethodDesc GetHelper(MethodDesc currentMethod)
        {
            return _cache.GetOrCreateValue(currentMethod.GetTypicalMethodDefinition());
        }

        private class Unifier : LockFreeReaderHashtable<MethodDesc, MethodBaseGetCurrentMethodThunk>
        {
            protected override int GetKeyHashCode(MethodDesc key)
            {
                return key.GetHashCode();
            }
            protected override int GetValueHashCode(MethodBaseGetCurrentMethodThunk value)
            {
                return value.Method.GetHashCode();
            }
            protected override bool CompareKeyToValue(MethodDesc key, MethodBaseGetCurrentMethodThunk value)
            {
                return key == value.Method;
            }
            protected override bool CompareValueToValue(MethodBaseGetCurrentMethodThunk value1, MethodBaseGetCurrentMethodThunk value2)
            {
                return value1.Method == value2.Method;
            }
            protected override MethodBaseGetCurrentMethodThunk CreateValueFromKey(MethodDesc key)
            {
                return new MethodBaseGetCurrentMethodThunk(key);
            }
        }
    }
}