| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
#pragma once |
|
2
|
|
|
|
|
|
|
#include |
|
3
|
|
|
|
|
|
|
#include |
|
4
|
|
|
|
|
|
|
#include |
|
5
|
|
|
|
|
|
|
#include |
|
6
|
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
namespace panda { |
|
8
|
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
namespace detail { |
|
10
|
|
|
|
|
|
|
void* __get_global_ptr (const std::type_info& ti, const char* name, void* val); |
|
11
|
|
|
|
|
|
|
void* __get_global_tls_ptr (const std::type_info& ti, const char* name, void* val); |
|
12
|
|
|
|
|
|
|
} |
|
13
|
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
template |
|
15
|
10
|
|
|
|
|
|
inline T* get_global_ptr (T* val, const char* name = NULL) { |
|
16
|
10
|
|
|
|
|
|
return reinterpret_cast(detail::__get_global_ptr(typeid(CLASS), name, reinterpret_cast(val))); |
|
17
|
|
|
|
|
|
|
} |
|
18
|
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
template |
|
20
|
|
|
|
|
|
|
inline T* get_global_tls_ptr (T* val, const char* name = NULL) { |
|
21
|
|
|
|
|
|
|
return reinterpret_cast(detail::__get_global_tls_ptr(typeid(CLASS), name, reinterpret_cast(val))); |
|
22
|
|
|
|
|
|
|
} |
|
23
|
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
#define PANDA_GLOBAL_MEMBER_PTR(CLASS, TYPE, accessor, defval) \ |
|
25
|
|
|
|
|
|
|
static TYPE accessor () { \ |
|
26
|
|
|
|
|
|
|
static TYPE ptr; \ |
|
27
|
|
|
|
|
|
|
if (!ptr) ptr = panda::get_global_ptr(defval, #accessor); \ |
|
28
|
|
|
|
|
|
|
return ptr; \ |
|
29
|
|
|
|
|
|
|
} |
|
30
|
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
#define PANDA_GLOBAL_MEMBER(CLASS, TYPE, accessor, defval) \ |
|
32
|
|
|
|
|
|
|
static TYPE& accessor () { \ |
|
33
|
|
|
|
|
|
|
static TYPE* ptr; \ |
|
34
|
|
|
|
|
|
|
if (!ptr) { \ |
|
35
|
|
|
|
|
|
|
static TYPE val = defval; \ |
|
36
|
|
|
|
|
|
|
ptr = panda::get_global_ptr(&val, #accessor); \ |
|
37
|
|
|
|
|
|
|
} \ |
|
38
|
|
|
|
|
|
|
return *ptr; \ |
|
39
|
|
|
|
|
|
|
} |
|
40
|
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
#define PANDA_GLOBAL_MEMBER_AS_PTR(CLASS, TYPE, accessor, defval) \ |
|
42
|
|
|
|
|
|
|
static TYPE* accessor () { \ |
|
43
|
|
|
|
|
|
|
static TYPE* ptr; \ |
|
44
|
|
|
|
|
|
|
if (!ptr) { \ |
|
45
|
|
|
|
|
|
|
static TYPE val = defval; \ |
|
46
|
|
|
|
|
|
|
ptr = panda::get_global_ptr(&val, #accessor); \ |
|
47
|
|
|
|
|
|
|
} \ |
|
48
|
|
|
|
|
|
|
return ptr; \ |
|
49
|
|
|
|
|
|
|
} |
|
50
|
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
#define PANDA_TLS_MEMBER_PTR(CLASS, TYPE, accessor, defval) \ |
|
52
|
|
|
|
|
|
|
static TYPE accessor () { \ |
|
53
|
|
|
|
|
|
|
static thread_local TYPE _ptr; \ |
|
54
|
|
|
|
|
|
|
TYPE ptr = _ptr; \ |
|
55
|
|
|
|
|
|
|
if (!ptr) ptr = _ptr = panda::get_global_tls_ptr(defval, #accessor); \ |
|
56
|
|
|
|
|
|
|
return ptr; \ |
|
57
|
|
|
|
|
|
|
} |
|
58
|
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
#define PANDA_TLS_MEMBER(CLASS, TYPE, accessor, defval) \ |
|
60
|
|
|
|
|
|
|
static TYPE& accessor () { \ |
|
61
|
|
|
|
|
|
|
static thread_local TYPE* _ptr; \ |
|
62
|
|
|
|
|
|
|
TYPE* ptr = _ptr; \ |
|
63
|
|
|
|
|
|
|
if (!ptr) { \ |
|
64
|
|
|
|
|
|
|
static thread_local TYPE val = defval; \ |
|
65
|
|
|
|
|
|
|
ptr = _ptr = panda::get_global_tls_ptr(&val, #accessor); \ |
|
66
|
|
|
|
|
|
|
} \ |
|
67
|
|
|
|
|
|
|
return *ptr; \ |
|
68
|
|
|
|
|
|
|
} |
|
69
|
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
#define PANDA_TLS_MEMBER_AS_PTR(CLASS, TYPE, accessor, defval) \ |
|
71
|
|
|
|
|
|
|
static TYPE* accessor () { \ |
|
72
|
|
|
|
|
|
|
static thread_local TYPE* _ptr; \ |
|
73
|
|
|
|
|
|
|
TYPE* ptr = _ptr; \ |
|
74
|
|
|
|
|
|
|
if (!ptr) { \ |
|
75
|
|
|
|
|
|
|
static thread_local TYPE val = defval; \ |
|
76
|
|
|
|
|
|
|
ptr = _ptr = panda::get_global_tls_ptr(&val, #accessor); \ |
|
77
|
|
|
|
|
|
|
} \ |
|
78
|
|
|
|
|
|
|
return ptr; \ |
|
79
|
|
|
|
|
|
|
} |
|
80
|
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
struct MemoryPool { |
|
82
|
|
|
|
|
|
|
MemoryPool (size_t blocksize) : first_free(NULL) { |
|
83
|
|
|
|
|
|
|
this->blocksize = round_up(blocksize); |
|
84
|
|
|
|
|
|
|
} |
|
85
|
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
void* allocate () { |
|
87
|
|
|
|
|
|
|
if (!first_free) grow(); |
|
88
|
|
|
|
|
|
|
void* ret = first_free; |
|
89
|
|
|
|
|
|
|
first_free = *((void**)ret); |
|
90
|
|
|
|
|
|
|
return ret; |
|
91
|
|
|
|
|
|
|
} |
|
92
|
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
void deallocate (void* elem) { |
|
94
|
|
|
|
|
|
|
#ifdef TEST_FULL |
|
95
|
|
|
|
|
|
|
if(!is_mine(elem)) abort(); // protection for debugging, normally you MUST NEVER pass a pointer that wasn't created via current mempool |
|
96
|
|
|
|
|
|
|
#endif |
|
97
|
|
|
|
|
|
|
*((void**)elem) = first_free; |
|
98
|
|
|
|
|
|
|
first_free = elem; |
|
99
|
|
|
|
|
|
|
} |
|
100
|
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
~MemoryPool (); |
|
102
|
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
private: |
|
104
|
|
|
|
|
|
|
struct Pool { |
|
105
|
|
|
|
|
|
|
char* list; |
|
106
|
|
|
|
|
|
|
size_t size; |
|
107
|
|
|
|
|
|
|
size_t len; |
|
108
|
|
|
|
|
|
|
}; |
|
109
|
|
|
|
|
|
|
size_t blocksize; |
|
110
|
|
|
|
|
|
|
std::vector pools; |
|
111
|
|
|
|
|
|
|
void* first_free; |
|
112
|
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
void grow (); |
|
114
|
|
|
|
|
|
|
bool is_mine (void* elem); |
|
115
|
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
inline static size_t round_up (size_t size) { |
|
117
|
|
|
|
|
|
|
assert(size > 0); |
|
118
|
|
|
|
|
|
|
const size_t factor = sizeof(void*); |
|
119
|
|
|
|
|
|
|
if ((size & (factor-1)) == 0) return size; |
|
120
|
|
|
|
|
|
|
size += factor; |
|
121
|
|
|
|
|
|
|
size &= ~((size_t)(factor-1)); |
|
122
|
|
|
|
|
|
|
return size; |
|
123
|
|
|
|
|
|
|
} |
|
124
|
|
|
|
|
|
|
}; |
|
125
|
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
template |
|
127
|
|
|
|
|
|
|
struct StaticMemoryPool { |
|
128
|
|
|
|
|
|
|
PANDA_GLOBAL_MEMBER_PTR(StaticMemoryPool, MemoryPool*, global_instance, new MemoryPool(BLOCKSIZE)); |
|
129
|
|
|
|
|
|
|
PANDA_TLS_MEMBER_PTR (StaticMemoryPool, MemoryPool*, instance, new MemoryPool(BLOCKSIZE)); |
|
130
|
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
static void* allocate () { return instance()->allocate(); } |
|
132
|
|
|
|
|
|
|
static void deallocate (void* p) { instance()->deallocate(p); } |
|
133
|
|
|
|
|
|
|
}; |
|
134
|
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
template <> struct StaticMemoryPool<7> : StaticMemoryPool<8> {}; |
|
136
|
|
|
|
|
|
|
template <> struct StaticMemoryPool<6> : StaticMemoryPool<8> {}; |
|
137
|
|
|
|
|
|
|
template <> struct StaticMemoryPool<5> : StaticMemoryPool<8> {}; |
|
138
|
|
|
|
|
|
|
template <> struct StaticMemoryPool<4> : StaticMemoryPool<8> {}; |
|
139
|
|
|
|
|
|
|
template <> struct StaticMemoryPool<3> : StaticMemoryPool<8> {}; |
|
140
|
|
|
|
|
|
|
template <> struct StaticMemoryPool<2> : StaticMemoryPool<8> {}; |
|
141
|
|
|
|
|
|
|
template <> struct StaticMemoryPool<1> : StaticMemoryPool<8> {}; |
|
142
|
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
struct DynamicMemoryPool { |
|
145
|
|
|
|
|
|
|
static DynamicMemoryPool* global_instance () { return _global_instance; } |
|
146
|
|
|
|
|
|
|
|
|
147
|
|
|
|
|
|
|
PANDA_TLS_MEMBER_PTR(DynamicMemoryPool, DynamicMemoryPool*, instance, new DynamicMemoryPool()); |
|
148
|
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
DynamicMemoryPool (); |
|
150
|
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
void* allocate (size_t size) { |
|
152
|
|
|
|
|
|
|
if (size == 0) return NULL; |
|
153
|
|
|
|
|
|
|
MemoryPool* pool; |
|
154
|
|
|
|
|
|
|
if (size <= 1024) { |
|
155
|
|
|
|
|
|
|
pool = small_pools[(size-1)>>2]; |
|
156
|
|
|
|
|
|
|
if (!pool) pool = small_pools[(size-1)>>2] = new MemoryPool((((size-1)>>2) + 1)<<2); |
|
157
|
|
|
|
|
|
|
} |
|
158
|
|
|
|
|
|
|
else if (size <= 16384) { |
|
159
|
|
|
|
|
|
|
pool = medium_pools[(size-1)>>6]; |
|
160
|
|
|
|
|
|
|
if (!pool) pool = medium_pools[(size-1)>>6] = new MemoryPool((((size-1)>>6) + 1)<<6); |
|
161
|
|
|
|
|
|
|
} |
|
162
|
|
|
|
|
|
|
else if (size <= 262144) { |
|
163
|
|
|
|
|
|
|
pool = big_pools[(size-1)>>10]; |
|
164
|
|
|
|
|
|
|
if (!pool) pool = big_pools[(size-1)>>10] = new MemoryPool((((size-1)>>10) + 1)<<10); |
|
165
|
|
|
|
|
|
|
} |
|
166
|
|
|
|
|
|
|
else throw std::invalid_argument("ObjectAllocator: object size cannot exceed 256k"); |
|
167
|
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
return pool->allocate(); |
|
169
|
|
|
|
|
|
|
} |
|
170
|
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
void deallocate (void* ptr, size_t size) { |
|
172
|
|
|
|
|
|
|
if (ptr == NULL || size == 0) return; |
|
173
|
|
|
|
|
|
|
MemoryPool* pool; |
|
174
|
|
|
|
|
|
|
if (size <= 1024) pool = small_pools[(size-1)>>2]; |
|
175
|
|
|
|
|
|
|
else if (size <= 16384) pool = medium_pools[(size-1)>>6]; |
|
176
|
|
|
|
|
|
|
else if (size <= 262144) pool = big_pools[(size-1)>>10]; |
|
177
|
|
|
|
|
|
|
else throw std::invalid_argument("ObjectAllocator: object size cannot exceed 256k"); |
|
178
|
|
|
|
|
|
|
pool->deallocate(ptr); |
|
179
|
|
|
|
|
|
|
} |
|
180
|
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
~DynamicMemoryPool (); |
|
182
|
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
private: |
|
184
|
|
|
|
|
|
|
static constexpr const int POOLS_CNT = 256; |
|
185
|
|
|
|
|
|
|
static DynamicMemoryPool* _global_instance; |
|
186
|
|
|
|
|
|
|
MemoryPool* small_pools[POOLS_CNT]; |
|
187
|
|
|
|
|
|
|
MemoryPool* medium_pools[POOLS_CNT]; |
|
188
|
|
|
|
|
|
|
MemoryPool* big_pools[POOLS_CNT]; |
|
189
|
|
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
}; |
|
191
|
|
|
|
|
|
|
|
|
192
|
|
|
|
|
|
|
template |
|
193
|
|
|
|
|
|
|
struct AllocatedObject { |
|
194
|
|
|
|
|
|
|
static void* operator new (size_t, void* p) { return p; } |
|
195
|
|
|
|
|
|
|
|
|
196
|
|
|
|
|
|
|
static void* operator new (size_t size) { |
|
197
|
|
|
|
|
|
|
if (size == sizeof(TARGET)) return StaticMemoryPool::allocate(); |
|
198
|
|
|
|
|
|
|
else return DynamicMemoryPool::instance()->allocate(size); |
|
199
|
|
|
|
|
|
|
} |
|
200
|
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
static void operator delete (void* p, size_t size) { |
|
202
|
|
|
|
|
|
|
if (size == sizeof(TARGET)) StaticMemoryPool::deallocate(p); |
|
203
|
|
|
|
|
|
|
else DynamicMemoryPool::instance()->deallocate(p, size); |
|
204
|
|
|
|
|
|
|
} |
|
205
|
|
|
|
|
|
|
}; |
|
206
|
|
|
|
|
|
|
|
|
207
|
|
|
|
|
|
|
template |
|
208
|
|
|
|
|
|
|
struct AllocatedObject { |
|
209
|
|
|
|
|
|
|
static void* operator new (size_t, void* p) { return p; } |
|
210
|
|
|
|
|
|
|
|
|
211
|
|
|
|
|
|
|
static void* operator new (size_t size) { |
|
212
|
|
|
|
|
|
|
if (size == sizeof(TARGET)) return StaticMemoryPool::global_instance()->allocate(); |
|
213
|
|
|
|
|
|
|
else return DynamicMemoryPool::global_instance()->allocate(size); |
|
214
|
|
|
|
|
|
|
} |
|
215
|
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
static void operator delete (void* p, size_t size) { |
|
217
|
|
|
|
|
|
|
if (size == sizeof(TARGET)) StaticMemoryPool::global_instance()->deallocate(p); |
|
218
|
|
|
|
|
|
|
else DynamicMemoryPool::global_instance()->deallocate(p, size); |
|
219
|
|
|
|
|
|
|
} |
|
220
|
|
|
|
|
|
|
}; |
|
221
|
|
|
|
|
|
|
|
|
222
|
|
|
|
|
|
|
} |