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

methoddescbackpatchinfo.h « vm « coreclr « src - github.com/dotnet/runtime.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 2fc5e6c8e8f1c3ccab255a5e0539a71245966566 (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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

#pragma once

#include "debugmacrosext.h"
#include "crossloaderallocatorhash.h"

#ifndef CROSSGEN_COMPILE

#define DISABLE_COPY(T) \
    T(const T &) = delete; \
    T &operator =(const T &) = delete

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// EntryPointSlots

class EntryPointSlots
{
public:
    enum SlotType : UINT8
    {
        SlotType_Normal, // pointer-sized value not in executable code
        SlotType_Vtable, // pointer-sized value not in executable code, may be relative based on MethodTable::VTableIndir2_t
        SlotType_Executable, // pointer-sized value in executable code
        SlotType_ExecutableRel32, // 32-bit value relative to the end of the slot, in executable code

        SlotType_Count,
        SlotType_Mask = SlotType_Vtable | SlotType_Executable | SlotType_ExecutableRel32
    };

#ifndef DACCESS_COMPILE
private:
    static SIZE_T GetRequiredSlotAlignment(SlotType slotType)
    {
        LIMITED_METHOD_CONTRACT;
        _ASSERTE(slotType >= SlotType_Normal);
        _ASSERTE(slotType < SlotType_Count);

        return slotType == SlotType_ExecutableRel32 ? sizeof(INT32) : sizeof(void *);
    }

public:
    static UINT_PTR ConvertSlotAndTypePairToUINT_PTR(TADDR slot, SlotType slotType)
    {
        slot |= (TADDR)slotType;
        return (UINT_PTR)slot;
    }

    static void ConvertUINT_PTRToSlotAndTypePair(UINT_PTR storedData, TADDR *pSlot, SlotType *pSlotType)
    {
        *pSlot = storedData;
        *pSlotType = (SlotType)(*pSlot & SlotType_Mask);
        *pSlot ^= *pSlotType;
    }

    static void Backpatch_Locked(TADDR slot, SlotType slotType, PCODE entryPoint);
#endif
};

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// MethodDescBackpatchInfoTracker

class MethodDescBackpatchInfoTracker
{
private:
    static CrstStatic s_lock;

    class BackpatchInfoTrackerHashTraits : public NoRemoveDefaultCrossLoaderAllocatorHashTraits<MethodDesc *, UINT_PTR>
    {
    };

    typedef CrossLoaderAllocatorHash<BackpatchInfoTrackerHashTraits> BackpatchInfoTrackerHash;

    // Contains information about slots associated with the MethodDesc that were recorded for backpatching. This field and its
    // data is protected by s_lock.
    BackpatchInfoTrackerHash m_backpatchInfoHash;

#ifndef DACCESS_COMPILE
public:
    static void StaticInitialize()
    {
        WRAPPER_NO_CONTRACT;
        s_lock.Init(CrstMethodDescBackpatchInfoTracker);
    }
#endif

    void Initialize(LoaderAllocator *pLoaderAllocator)
    {
        WRAPPER_NO_CONTRACT;
        m_backpatchInfoHash.Init(pLoaderAllocator);
    }

#ifdef _DEBUG
public:
    static bool IsLockOwnedByCurrentThread();
#endif

public:
    // To be used when the thread will remain in preemptive GC mode while holding the lock
    class ConditionalLockHolderForGCPreemp : private CrstHolderWithState
    {
    public:
        ConditionalLockHolderForGCPreemp(bool acquireLock = true)
            : CrstHolderWithState(
#ifndef DACCESS_COMPILE
                acquireLock ? &s_lock : nullptr
#else
                nullptr
#endif
                )
        {
            CONTRACTL
            {
                NOTHROW;
                GC_NOTRIGGER;
                MODE_PREEMPTIVE;
            }
            CONTRACTL_END;
        }

        DISABLE_COPY(ConditionalLockHolderForGCPreemp);
    };

#ifndef DACCESS_COMPILE
public:
    // To be used when the thread may enter cooperative GC mode while holding the lock. The thread enters a
    // forbid-suspend-for-debugger region along with acquiring the lock, such that it would not suspend for the debugger while
    // holding the lock, as that may otherwise cause a FuncEval to deadlock when trying to acquire the lock.
    class ConditionalLockHolderForGCCoop : private CrstAndForbidSuspendForDebuggerHolder
    {
    public:
        ConditionalLockHolderForGCCoop(bool acquireLock = true)
            : CrstAndForbidSuspendForDebuggerHolder(acquireLock ? &s_lock : nullptr)
        {
            CONTRACTL
            {
                NOTHROW;
                GC_NOTRIGGER;
                MODE_PREEMPTIVE;
            }
            CONTRACTL_END;
        }

        DISABLE_COPY(ConditionalLockHolderForGCCoop);
    };
#endif

public:
    MethodDescBackpatchInfoTracker()
    {
        LIMITED_METHOD_CONTRACT;
    }

#ifndef DACCESS_COMPILE
public:
    void Backpatch_Locked(MethodDesc *pMethodDesc, PCODE entryPoint);
    void AddSlotAndPatch_Locked(MethodDesc *pMethodDesc, LoaderAllocator *pLoaderAllocatorOfSlot, TADDR slot, EntryPointSlots::SlotType slotType, PCODE currentEntryPoint);
#endif

    DISABLE_COPY(MethodDescBackpatchInfoTracker);
};

#undef DISABLE_COPY

#endif // !CROSSGEN_COMPILE