This source file includes following definitions.
- alloc_chunk
- free_chunk
- alloc_chunk
- free_chunk
- sljit_insert_free_block
- sljit_remove_free_block
- sljit_malloc_exec
- sljit_free_exec
- sljit_free_unused_memory_exec
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 #define CHUNK_SIZE 0x10000
70
71
72
73
74
75
76
77
78
79
80
81
82 #ifdef _WIN32
83
84 static SLJIT_INLINE void* alloc_chunk(sljit_uw size)
85 {
86 return VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
87 }
88
89 static SLJIT_INLINE void free_chunk(void* chunk, sljit_uw size)
90 {
91 SLJIT_UNUSED_ARG(size);
92 VirtualFree(chunk, 0, MEM_RELEASE);
93 }
94
95 #else
96
97 static SLJIT_INLINE void* alloc_chunk(sljit_uw size)
98 {
99 void* retval;
100
101 #ifdef MAP_ANON
102 retval = mmap(NULL, size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANON, -1, 0);
103 #else
104 if (dev_zero < 0) {
105 if (open_dev_zero())
106 return NULL;
107 }
108 retval = mmap(NULL, size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, dev_zero, 0);
109 #endif
110
111 return (retval != MAP_FAILED) ? retval : NULL;
112 }
113
114 static SLJIT_INLINE void free_chunk(void* chunk, sljit_uw size)
115 {
116 munmap(chunk, size);
117 }
118
119 #endif
120
121
122
123
124
125 #define CHUNK_MASK (~(CHUNK_SIZE - 1))
126
127 struct block_header {
128 sljit_uw size;
129 sljit_uw prev_size;
130 };
131
132 struct free_block {
133 struct block_header header;
134 struct free_block *next;
135 struct free_block *prev;
136 sljit_uw size;
137 };
138
139 #define AS_BLOCK_HEADER(base, offset) \
140 ((struct block_header*)(((sljit_ub*)base) + offset))
141 #define AS_FREE_BLOCK(base, offset) \
142 ((struct free_block*)(((sljit_ub*)base) + offset))
143 #define MEM_START(base) ((void*)(((sljit_ub*)base) + sizeof(struct block_header)))
144 #define ALIGN_SIZE(size) (((size) + sizeof(struct block_header) + 7) & ~7)
145
146 static struct free_block* free_blocks;
147 static sljit_uw allocated_size;
148 static sljit_uw total_size;
149
150 static SLJIT_INLINE void sljit_insert_free_block(struct free_block *free_block, sljit_uw size)
151 {
152 free_block->header.size = 0;
153 free_block->size = size;
154
155 free_block->next = free_blocks;
156 free_block->prev = 0;
157 if (free_blocks)
158 free_blocks->prev = free_block;
159 free_blocks = free_block;
160 }
161
162 static SLJIT_INLINE void sljit_remove_free_block(struct free_block *free_block)
163 {
164 if (free_block->next)
165 free_block->next->prev = free_block->prev;
166
167 if (free_block->prev)
168 free_block->prev->next = free_block->next;
169 else {
170 SLJIT_ASSERT(free_blocks == free_block);
171 free_blocks = free_block->next;
172 }
173 }
174
175 SLJIT_API_FUNC_ATTRIBUTE void* sljit_malloc_exec(sljit_uw size)
176 {
177 struct block_header *header;
178 struct block_header *next_header;
179 struct free_block *free_block;
180 sljit_uw chunk_size;
181
182 allocator_grab_lock();
183 if (size < sizeof(struct free_block))
184 size = sizeof(struct free_block);
185 size = ALIGN_SIZE(size);
186
187 free_block = free_blocks;
188 while (free_block) {
189 if (free_block->size >= size) {
190 chunk_size = free_block->size;
191 if (chunk_size > size + 64) {
192
193 chunk_size -= size;
194 free_block->size = chunk_size;
195 header = AS_BLOCK_HEADER(free_block, chunk_size);
196 header->prev_size = chunk_size;
197 AS_BLOCK_HEADER(header, size)->prev_size = size;
198 }
199 else {
200 sljit_remove_free_block(free_block);
201 header = (struct block_header*)free_block;
202 size = chunk_size;
203 }
204 allocated_size += size;
205 header->size = size;
206 allocator_release_lock();
207 return MEM_START(header);
208 }
209 free_block = free_block->next;
210 }
211
212 chunk_size = (size + sizeof(struct block_header) + CHUNK_SIZE - 1) & CHUNK_MASK;
213 header = (struct block_header*)alloc_chunk(chunk_size);
214 if (!header) {
215 allocator_release_lock();
216 return NULL;
217 }
218
219 chunk_size -= sizeof(struct block_header);
220 total_size += chunk_size;
221
222 header->prev_size = 0;
223 if (chunk_size > size + 64) {
224
225 allocated_size += size;
226 header->size = size;
227 chunk_size -= size;
228
229 free_block = AS_FREE_BLOCK(header, size);
230 free_block->header.prev_size = size;
231 sljit_insert_free_block(free_block, chunk_size);
232 next_header = AS_BLOCK_HEADER(free_block, chunk_size);
233 }
234 else {
235
236 allocated_size += chunk_size;
237 header->size = chunk_size;
238 next_header = AS_BLOCK_HEADER(header, chunk_size);
239 }
240 next_header->size = 1;
241 next_header->prev_size = chunk_size;
242 allocator_release_lock();
243 return MEM_START(header);
244 }
245
246 SLJIT_API_FUNC_ATTRIBUTE void sljit_free_exec(void* ptr)
247 {
248 struct block_header *header;
249 struct free_block* free_block;
250
251 allocator_grab_lock();
252 header = AS_BLOCK_HEADER(ptr, -(sljit_sw)sizeof(struct block_header));
253 allocated_size -= header->size;
254
255
256
257
258
259 free_block = AS_FREE_BLOCK(header, -(sljit_sw)header->prev_size);
260 if (SLJIT_UNLIKELY(!free_block->header.size)) {
261 free_block->size += header->size;
262 header = AS_BLOCK_HEADER(free_block, free_block->size);
263 header->prev_size = free_block->size;
264 }
265 else {
266 free_block = (struct free_block*)header;
267 sljit_insert_free_block(free_block, header->size);
268 }
269
270 header = AS_BLOCK_HEADER(free_block, free_block->size);
271 if (SLJIT_UNLIKELY(!header->size)) {
272 free_block->size += ((struct free_block*)header)->size;
273 sljit_remove_free_block((struct free_block*)header);
274 header = AS_BLOCK_HEADER(free_block, free_block->size);
275 header->prev_size = free_block->size;
276 }
277
278
279 if (SLJIT_UNLIKELY(!free_block->header.prev_size && header->size == 1)) {
280
281 if (total_size - free_block->size > (allocated_size * 3 / 2)) {
282 total_size -= free_block->size;
283 sljit_remove_free_block(free_block);
284 free_chunk(free_block, free_block->size + sizeof(struct block_header));
285 }
286 }
287
288 allocator_release_lock();
289 }
290
291 SLJIT_API_FUNC_ATTRIBUTE void sljit_free_unused_memory_exec(void)
292 {
293 struct free_block* free_block;
294 struct free_block* next_free_block;
295
296 allocator_grab_lock();
297
298 free_block = free_blocks;
299 while (free_block) {
300 next_free_block = free_block->next;
301 if (!free_block->header.prev_size &&
302 AS_BLOCK_HEADER(free_block, free_block->size)->size == 1) {
303 total_size -= free_block->size;
304 sljit_remove_free_block(free_block);
305 free_chunk(free_block, free_block->size + sizeof(struct block_header));
306 }
307 free_block = next_free_block;
308 }
309
310 SLJIT_ASSERT((total_size && free_blocks) || (!total_size && !free_blocks));
311 allocator_release_lock();
312 }