summaryrefslogtreecommitdiff
path: root/src/vm/methoddescbackpatchinfo.h
blob: c5d92a29da53069189f5e2bdd41ad3b6c2d58155 (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
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#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();
#endif

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

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

public:
    class ConditionalLockHolder : CrstHolderWithState
    {
    public:
        ConditionalLockHolder(bool acquireLock = true)
            : CrstHolderWithState(
#ifndef DACCESS_COMPILE
                acquireLock ? &MethodDescBackpatchInfoTracker::s_lock : nullptr
#else
                nullptr
#endif
                )
        {
            LIMITED_METHOD_CONTRACT;
        }
    };

public:
    MethodDescBackpatchInfoTracker()
    {
        LIMITED_METHOD_CONTRACT;
    }

#ifdef _DEBUG
public:
    static bool MayHaveEntryPointSlotsToBackpatch(PTR_MethodDesc methodDesc);
#endif

#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);
public:
#endif

    friend class ConditionalLockHolder;

    DISABLE_COPY(MethodDescBackpatchInfoTracker);
};

#undef DISABLE_COPY

#endif // !CROSSGEN_COMPILE