summaryrefslogtreecommitdiff
path: root/packaging/0002-UMEntryThunk-store-freed-thunks-into-FIFO-free-list.patch
blob: 8ee6d76e31f06071840df8562b9264ccd9f5bbb0 (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
From 51ffa6ba338dded7be2a0147a8e477d28b35b159 Mon Sep 17 00:00:00 2001
From: Konstantin Baladurin <k.baladurin@partner.samsung.com>
Date: Fri, 12 Jan 2018 18:55:10 +0300
Subject: [PATCH 02/47] UMEntryThunk: store freed thunks into FIFO free list

Use free list to delay reusing deleted thunks. It improves
collected delegate calls diagnostic.
---
 src/vm/dllimportcallback.cpp | 87 ++++++++++++++++++++++++++++++++++++++++++--
 src/vm/dllimportcallback.h   | 10 ++++-
 2 files changed, 91 insertions(+), 6 deletions(-)

diff --git a/src/vm/dllimportcallback.cpp b/src/vm/dllimportcallback.cpp
index c3e6a4e..fe03f47 100644
--- a/src/vm/dllimportcallback.cpp
+++ b/src/vm/dllimportcallback.cpp
@@ -33,6 +33,79 @@ struct UM2MThunk_Args
     int argLen;
 };
 
+class UMEntryThunkFreeList
+{
+public:
+    UMEntryThunkFreeList(size_t threshold) :
+        m_threshold(threshold),
+        m_count(0),
+        m_pHead(NULL),
+        m_pTail(NULL)
+    {
+        WRAPPER_NO_CONTRACT;
+
+        m_crst.Init(CrstLeafLock, CRST_UNSAFE_ANYMODE);
+    }
+
+    UMEntryThunk *GetUMEntryThunk()
+    {
+        WRAPPER_NO_CONTRACT;
+
+        if (m_count < m_threshold)
+            return NULL;
+
+        CrstHolder ch(&m_crst);
+
+        UMEntryThunk *pThunk = m_pHead;
+
+        if (pThunk == NULL)
+            return NULL;
+
+        m_pHead = m_pHead->m_pNextFreeThunk;
+        --m_count;
+
+        return pThunk;
+    }
+
+    void AddToList(UMEntryThunk *pThunk)
+    {
+        CONTRACTL
+        {
+            NOTHROW;
+        }
+        CONTRACTL_END;
+
+        CrstHolder ch(&m_crst);
+
+        if (m_pHead == NULL)
+        {
+            m_pHead = pThunk;
+            m_pTail = pThunk;
+        }
+        else
+        {
+            m_pTail->m_pNextFreeThunk = pThunk;
+            m_pTail = pThunk;
+        }
+
+        pThunk->m_pNextFreeThunk = NULL;
+
+        ++m_count;
+    }
+
+private:
+    // Used to delay reusing freed thunks
+    size_t m_threshold;
+    size_t m_count;
+    UMEntryThunk *m_pHead;
+    UMEntryThunk *m_pTail;
+    CrstStatic m_crst;
+};
+
+#define DEFAULT_THUNK_FREE_LIST_THRESHOLD 64
+
+static UMEntryThunkFreeList s_thunkFreeList(DEFAULT_THUNK_FREE_LIST_THRESHOLD);
+
 EXTERN_C void STDCALL UM2MThunk_WrapperHelper(void *pThunkArgs,
                                               int argLen,
                                               void *pAddr,
@@ -1111,20 +1184,26 @@ UMEntryThunk* UMEntryThunk::CreateUMEntryThunk()
 
     UMEntryThunk * p;
 
-    // On the phone, use loader heap to save memory commit of regular executable heap
-    p = (UMEntryThunk *)(void *)SystemDomain::GetGlobalLoaderAllocator()->GetExecutableHeap()->AllocMem(S_SIZE_T(sizeof(UMEntryThunk)));
+    p = s_thunkFreeList.GetUMEntryThunk();
+
+    if (p == NULL)
+        p = (UMEntryThunk *)(void *)SystemDomain::GetGlobalLoaderAllocator()->GetExecutableHeap()->AllocMem(S_SIZE_T(sizeof(UMEntryThunk)));
 
     RETURN p;
 }
 
 void UMEntryThunk::Terminate()
 {
-    WRAPPER_NO_CONTRACT;
+    CONTRACTL
+    {
+        NOTHROW;
+    }
+    CONTRACTL_END;
 
     _ASSERTE(!SystemDomain::GetGlobalLoaderAllocator()->GetExecutableHeap()->IsZeroInit());
     m_code.Poison();
 
-    SystemDomain::GetGlobalLoaderAllocator()->GetExecutableHeap()->BackoutMem(this, sizeof(UMEntryThunk));
+    s_thunkFreeList.AddToList(this);
 }
 
 VOID UMEntryThunk::FreeUMEntryThunk(UMEntryThunk* p)
diff --git a/src/vm/dllimportcallback.h b/src/vm/dllimportcallback.h
index 5838e49..d820a76 100644
--- a/src/vm/dllimportcallback.h
+++ b/src/vm/dllimportcallback.h
@@ -250,6 +250,7 @@ class UMEntryThunk
 {
     friend class CheckAsmOffsets;
     friend class NDirectStubLinker;
+    friend class UMEntryThunkFreeList;
 
 private:
 #ifdef _DEBUG
@@ -526,8 +527,13 @@ private:
     // Field is NULL for a static method.
     OBJECTHANDLE            m_pObjectHandle;
 
-    // Pointer to the shared structure containing everything else
-    PTR_UMThunkMarshInfo    m_pUMThunkMarshInfo;
+    union
+    {
+        // Pointer to the shared structure containing everything else
+        PTR_UMThunkMarshInfo    m_pUMThunkMarshInfo;
+        // Pointer to the next UMEntryThunk in the free list. Used when it is freed.
+        UMEntryThunk *m_pNextFreeThunk;
+    };
 
     ADID                    m_dwDomainId;   // appdomain of module (cached for fast access)
 #ifdef _DEBUG
-- 
2.7.4