1*22dc650dSSadaf Ebrahimi /*
2*22dc650dSSadaf Ebrahimi * Stack-less Just-In-Time compiler
3*22dc650dSSadaf Ebrahimi *
4*22dc650dSSadaf Ebrahimi * Copyright Zoltan Herczeg ([email protected]). All rights reserved.
5*22dc650dSSadaf Ebrahimi *
6*22dc650dSSadaf Ebrahimi * Redistribution and use in source and binary forms, with or without modification, are
7*22dc650dSSadaf Ebrahimi * permitted provided that the following conditions are met:
8*22dc650dSSadaf Ebrahimi *
9*22dc650dSSadaf Ebrahimi * 1. Redistributions of source code must retain the above copyright notice, this list of
10*22dc650dSSadaf Ebrahimi * conditions and the following disclaimer.
11*22dc650dSSadaf Ebrahimi *
12*22dc650dSSadaf Ebrahimi * 2. Redistributions in binary form must reproduce the above copyright notice, this list
13*22dc650dSSadaf Ebrahimi * of conditions and the following disclaimer in the documentation and/or other materials
14*22dc650dSSadaf Ebrahimi * provided with the distribution.
15*22dc650dSSadaf Ebrahimi *
16*22dc650dSSadaf Ebrahimi * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
17*22dc650dSSadaf Ebrahimi * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18*22dc650dSSadaf Ebrahimi * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
19*22dc650dSSadaf Ebrahimi * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20*22dc650dSSadaf Ebrahimi * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
21*22dc650dSSadaf Ebrahimi * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
22*22dc650dSSadaf Ebrahimi * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23*22dc650dSSadaf Ebrahimi * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
24*22dc650dSSadaf Ebrahimi * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25*22dc650dSSadaf Ebrahimi */
26*22dc650dSSadaf Ebrahimi
27*22dc650dSSadaf Ebrahimi /* ------------------------------------------------------------------------ */
28*22dc650dSSadaf Ebrahimi /* Locks */
29*22dc650dSSadaf Ebrahimi /* ------------------------------------------------------------------------ */
30*22dc650dSSadaf Ebrahimi
31*22dc650dSSadaf Ebrahimi /* Executable Allocator */
32*22dc650dSSadaf Ebrahimi
33*22dc650dSSadaf Ebrahimi #if (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR) \
34*22dc650dSSadaf Ebrahimi && !(defined SLJIT_WX_EXECUTABLE_ALLOCATOR && SLJIT_WX_EXECUTABLE_ALLOCATOR)
35*22dc650dSSadaf Ebrahimi #if (defined SLJIT_SINGLE_THREADED && SLJIT_SINGLE_THREADED)
36*22dc650dSSadaf Ebrahimi #define SLJIT_ALLOCATOR_LOCK()
37*22dc650dSSadaf Ebrahimi #define SLJIT_ALLOCATOR_UNLOCK()
38*22dc650dSSadaf Ebrahimi #elif !(defined _WIN32)
39*22dc650dSSadaf Ebrahimi #include <pthread.h>
40*22dc650dSSadaf Ebrahimi
41*22dc650dSSadaf Ebrahimi static pthread_mutex_t allocator_lock = PTHREAD_MUTEX_INITIALIZER;
42*22dc650dSSadaf Ebrahimi
43*22dc650dSSadaf Ebrahimi #define SLJIT_ALLOCATOR_LOCK() pthread_mutex_lock(&allocator_lock)
44*22dc650dSSadaf Ebrahimi #define SLJIT_ALLOCATOR_UNLOCK() pthread_mutex_unlock(&allocator_lock)
45*22dc650dSSadaf Ebrahimi #else /* windows */
46*22dc650dSSadaf Ebrahimi static HANDLE allocator_lock;
47*22dc650dSSadaf Ebrahimi
allocator_grab_lock(void)48*22dc650dSSadaf Ebrahimi static SLJIT_INLINE void allocator_grab_lock(void)
49*22dc650dSSadaf Ebrahimi {
50*22dc650dSSadaf Ebrahimi HANDLE lock;
51*22dc650dSSadaf Ebrahimi if (SLJIT_UNLIKELY(!InterlockedCompareExchangePointer(&allocator_lock, NULL, NULL))) {
52*22dc650dSSadaf Ebrahimi lock = CreateMutex(NULL, FALSE, NULL);
53*22dc650dSSadaf Ebrahimi if (InterlockedCompareExchangePointer(&allocator_lock, lock, NULL))
54*22dc650dSSadaf Ebrahimi CloseHandle(lock);
55*22dc650dSSadaf Ebrahimi }
56*22dc650dSSadaf Ebrahimi WaitForSingleObject(allocator_lock, INFINITE);
57*22dc650dSSadaf Ebrahimi }
58*22dc650dSSadaf Ebrahimi
59*22dc650dSSadaf Ebrahimi #define SLJIT_ALLOCATOR_LOCK() allocator_grab_lock()
60*22dc650dSSadaf Ebrahimi #define SLJIT_ALLOCATOR_UNLOCK() ReleaseMutex(allocator_lock)
61*22dc650dSSadaf Ebrahimi #endif /* thread implementation */
62*22dc650dSSadaf Ebrahimi #endif /* SLJIT_EXECUTABLE_ALLOCATOR && !SLJIT_WX_EXECUTABLE_ALLOCATOR */
63*22dc650dSSadaf Ebrahimi
64*22dc650dSSadaf Ebrahimi /* ------------------------------------------------------------------------ */
65*22dc650dSSadaf Ebrahimi /* Stack */
66*22dc650dSSadaf Ebrahimi /* ------------------------------------------------------------------------ */
67*22dc650dSSadaf Ebrahimi
68*22dc650dSSadaf Ebrahimi #if ((defined SLJIT_UTIL_STACK && SLJIT_UTIL_STACK) \
69*22dc650dSSadaf Ebrahimi && !(defined SLJIT_UTIL_SIMPLE_STACK_ALLOCATION && SLJIT_UTIL_SIMPLE_STACK_ALLOCATION)) \
70*22dc650dSSadaf Ebrahimi || ((defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR) \
71*22dc650dSSadaf Ebrahimi && !((defined SLJIT_PROT_EXECUTABLE_ALLOCATOR && SLJIT_PROT_EXECUTABLE_ALLOCATOR) \
72*22dc650dSSadaf Ebrahimi || (defined SLJIT_WX_EXECUTABLE_ALLOCATOR && SLJIT_WX_EXECUTABLE_ALLOCATOR)))
73*22dc650dSSadaf Ebrahimi
74*22dc650dSSadaf Ebrahimi #ifndef _WIN32
75*22dc650dSSadaf Ebrahimi /* Provides mmap function. */
76*22dc650dSSadaf Ebrahimi #include <sys/types.h>
77*22dc650dSSadaf Ebrahimi #include <sys/mman.h>
78*22dc650dSSadaf Ebrahimi
79*22dc650dSSadaf Ebrahimi #ifndef MAP_ANON
80*22dc650dSSadaf Ebrahimi #ifdef MAP_ANONYMOUS
81*22dc650dSSadaf Ebrahimi #define MAP_ANON MAP_ANONYMOUS
82*22dc650dSSadaf Ebrahimi #endif /* MAP_ANONYMOUS */
83*22dc650dSSadaf Ebrahimi #endif /* !MAP_ANON */
84*22dc650dSSadaf Ebrahimi
85*22dc650dSSadaf Ebrahimi #ifndef MAP_ANON
86*22dc650dSSadaf Ebrahimi
87*22dc650dSSadaf Ebrahimi #include <fcntl.h>
88*22dc650dSSadaf Ebrahimi
89*22dc650dSSadaf Ebrahimi #ifdef O_CLOEXEC
90*22dc650dSSadaf Ebrahimi #define SLJIT_CLOEXEC O_CLOEXEC
91*22dc650dSSadaf Ebrahimi #else /* !O_CLOEXEC */
92*22dc650dSSadaf Ebrahimi #define SLJIT_CLOEXEC 0
93*22dc650dSSadaf Ebrahimi #endif /* O_CLOEXEC */
94*22dc650dSSadaf Ebrahimi
95*22dc650dSSadaf Ebrahimi /* Some old systems do not have MAP_ANON. */
96*22dc650dSSadaf Ebrahimi static int dev_zero = -1;
97*22dc650dSSadaf Ebrahimi
98*22dc650dSSadaf Ebrahimi #if (defined SLJIT_SINGLE_THREADED && SLJIT_SINGLE_THREADED)
99*22dc650dSSadaf Ebrahimi
open_dev_zero(void)100*22dc650dSSadaf Ebrahimi static SLJIT_INLINE int open_dev_zero(void)
101*22dc650dSSadaf Ebrahimi {
102*22dc650dSSadaf Ebrahimi dev_zero = open("/dev/zero", O_RDWR | SLJIT_CLOEXEC);
103*22dc650dSSadaf Ebrahimi
104*22dc650dSSadaf Ebrahimi return dev_zero < 0;
105*22dc650dSSadaf Ebrahimi }
106*22dc650dSSadaf Ebrahimi
107*22dc650dSSadaf Ebrahimi #else /* !SLJIT_SINGLE_THREADED */
108*22dc650dSSadaf Ebrahimi
109*22dc650dSSadaf Ebrahimi #include <pthread.h>
110*22dc650dSSadaf Ebrahimi
111*22dc650dSSadaf Ebrahimi static pthread_mutex_t dev_zero_mutex = PTHREAD_MUTEX_INITIALIZER;
112*22dc650dSSadaf Ebrahimi
open_dev_zero(void)113*22dc650dSSadaf Ebrahimi static SLJIT_INLINE int open_dev_zero(void)
114*22dc650dSSadaf Ebrahimi {
115*22dc650dSSadaf Ebrahimi pthread_mutex_lock(&dev_zero_mutex);
116*22dc650dSSadaf Ebrahimi if (SLJIT_UNLIKELY(dev_zero < 0))
117*22dc650dSSadaf Ebrahimi dev_zero = open("/dev/zero", O_RDWR | SLJIT_CLOEXEC);
118*22dc650dSSadaf Ebrahimi
119*22dc650dSSadaf Ebrahimi pthread_mutex_unlock(&dev_zero_mutex);
120*22dc650dSSadaf Ebrahimi return dev_zero < 0;
121*22dc650dSSadaf Ebrahimi }
122*22dc650dSSadaf Ebrahimi
123*22dc650dSSadaf Ebrahimi #endif /* SLJIT_SINGLE_THREADED */
124*22dc650dSSadaf Ebrahimi #undef SLJIT_CLOEXEC
125*22dc650dSSadaf Ebrahimi #endif /* !MAP_ANON */
126*22dc650dSSadaf Ebrahimi #endif /* !_WIN32 */
127*22dc650dSSadaf Ebrahimi #endif /* open_dev_zero */
128*22dc650dSSadaf Ebrahimi
129*22dc650dSSadaf Ebrahimi #if (defined SLJIT_UTIL_STACK && SLJIT_UTIL_STACK) \
130*22dc650dSSadaf Ebrahimi || (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR)
131*22dc650dSSadaf Ebrahimi
132*22dc650dSSadaf Ebrahimi #ifdef _WIN32
133*22dc650dSSadaf Ebrahimi
get_page_alignment(void)134*22dc650dSSadaf Ebrahimi static SLJIT_INLINE sljit_uw get_page_alignment(void) {
135*22dc650dSSadaf Ebrahimi SYSTEM_INFO si;
136*22dc650dSSadaf Ebrahimi static sljit_uw sljit_page_align = 0;
137*22dc650dSSadaf Ebrahimi if (!sljit_page_align) {
138*22dc650dSSadaf Ebrahimi GetSystemInfo(&si);
139*22dc650dSSadaf Ebrahimi sljit_page_align = (sljit_uw)si.dwPageSize - 1;
140*22dc650dSSadaf Ebrahimi }
141*22dc650dSSadaf Ebrahimi return sljit_page_align;
142*22dc650dSSadaf Ebrahimi }
143*22dc650dSSadaf Ebrahimi
144*22dc650dSSadaf Ebrahimi #else
145*22dc650dSSadaf Ebrahimi
146*22dc650dSSadaf Ebrahimi #include <unistd.h>
147*22dc650dSSadaf Ebrahimi
get_page_alignment(void)148*22dc650dSSadaf Ebrahimi static SLJIT_INLINE sljit_uw get_page_alignment(void) {
149*22dc650dSSadaf Ebrahimi static sljit_uw sljit_page_align = 0;
150*22dc650dSSadaf Ebrahimi
151*22dc650dSSadaf Ebrahimi sljit_sw align;
152*22dc650dSSadaf Ebrahimi
153*22dc650dSSadaf Ebrahimi if (!sljit_page_align) {
154*22dc650dSSadaf Ebrahimi #ifdef _SC_PAGESIZE
155*22dc650dSSadaf Ebrahimi align = sysconf(_SC_PAGESIZE);
156*22dc650dSSadaf Ebrahimi #else
157*22dc650dSSadaf Ebrahimi align = getpagesize();
158*22dc650dSSadaf Ebrahimi #endif
159*22dc650dSSadaf Ebrahimi /* Should never happen. */
160*22dc650dSSadaf Ebrahimi if (align < 0)
161*22dc650dSSadaf Ebrahimi align = 4096;
162*22dc650dSSadaf Ebrahimi sljit_page_align = (sljit_uw)align - 1;
163*22dc650dSSadaf Ebrahimi }
164*22dc650dSSadaf Ebrahimi return sljit_page_align;
165*22dc650dSSadaf Ebrahimi }
166*22dc650dSSadaf Ebrahimi
167*22dc650dSSadaf Ebrahimi #endif /* _WIN32 */
168*22dc650dSSadaf Ebrahimi
169*22dc650dSSadaf Ebrahimi #endif /* get_page_alignment() */
170*22dc650dSSadaf Ebrahimi
171*22dc650dSSadaf Ebrahimi #if (defined SLJIT_UTIL_STACK && SLJIT_UTIL_STACK)
172*22dc650dSSadaf Ebrahimi
173*22dc650dSSadaf Ebrahimi #if (defined SLJIT_UTIL_SIMPLE_STACK_ALLOCATION && SLJIT_UTIL_SIMPLE_STACK_ALLOCATION)
174*22dc650dSSadaf Ebrahimi
sljit_allocate_stack(sljit_uw start_size,sljit_uw max_size,void * allocator_data)175*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE struct sljit_stack* SLJIT_FUNC sljit_allocate_stack(sljit_uw start_size, sljit_uw max_size, void *allocator_data)
176*22dc650dSSadaf Ebrahimi {
177*22dc650dSSadaf Ebrahimi struct sljit_stack *stack;
178*22dc650dSSadaf Ebrahimi void *ptr;
179*22dc650dSSadaf Ebrahimi
180*22dc650dSSadaf Ebrahimi SLJIT_UNUSED_ARG(allocator_data);
181*22dc650dSSadaf Ebrahimi
182*22dc650dSSadaf Ebrahimi if (start_size > max_size || start_size < 1)
183*22dc650dSSadaf Ebrahimi return NULL;
184*22dc650dSSadaf Ebrahimi
185*22dc650dSSadaf Ebrahimi stack = (struct sljit_stack*)SLJIT_MALLOC(sizeof(struct sljit_stack), allocator_data);
186*22dc650dSSadaf Ebrahimi if (stack == NULL)
187*22dc650dSSadaf Ebrahimi return NULL;
188*22dc650dSSadaf Ebrahimi
189*22dc650dSSadaf Ebrahimi ptr = SLJIT_MALLOC(max_size, allocator_data);
190*22dc650dSSadaf Ebrahimi if (ptr == NULL) {
191*22dc650dSSadaf Ebrahimi SLJIT_FREE(stack, allocator_data);
192*22dc650dSSadaf Ebrahimi return NULL;
193*22dc650dSSadaf Ebrahimi }
194*22dc650dSSadaf Ebrahimi
195*22dc650dSSadaf Ebrahimi stack->min_start = (sljit_u8 *)ptr;
196*22dc650dSSadaf Ebrahimi stack->end = stack->min_start + max_size;
197*22dc650dSSadaf Ebrahimi stack->start = stack->end - start_size;
198*22dc650dSSadaf Ebrahimi stack->top = stack->end;
199*22dc650dSSadaf Ebrahimi return stack;
200*22dc650dSSadaf Ebrahimi }
201*22dc650dSSadaf Ebrahimi
sljit_free_stack(struct sljit_stack * stack,void * allocator_data)202*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE void SLJIT_FUNC sljit_free_stack(struct sljit_stack *stack, void *allocator_data)
203*22dc650dSSadaf Ebrahimi {
204*22dc650dSSadaf Ebrahimi SLJIT_UNUSED_ARG(allocator_data);
205*22dc650dSSadaf Ebrahimi SLJIT_FREE((void*)stack->min_start, allocator_data);
206*22dc650dSSadaf Ebrahimi SLJIT_FREE(stack, allocator_data);
207*22dc650dSSadaf Ebrahimi }
208*22dc650dSSadaf Ebrahimi
sljit_stack_resize(struct sljit_stack * stack,sljit_u8 * new_start)209*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_u8 *SLJIT_FUNC sljit_stack_resize(struct sljit_stack *stack, sljit_u8 *new_start)
210*22dc650dSSadaf Ebrahimi {
211*22dc650dSSadaf Ebrahimi if ((new_start < stack->min_start) || (new_start >= stack->end))
212*22dc650dSSadaf Ebrahimi return NULL;
213*22dc650dSSadaf Ebrahimi stack->start = new_start;
214*22dc650dSSadaf Ebrahimi return new_start;
215*22dc650dSSadaf Ebrahimi }
216*22dc650dSSadaf Ebrahimi
217*22dc650dSSadaf Ebrahimi #else /* !SLJIT_UTIL_SIMPLE_STACK_ALLOCATION */
218*22dc650dSSadaf Ebrahimi
219*22dc650dSSadaf Ebrahimi #ifdef _WIN32
220*22dc650dSSadaf Ebrahimi
sljit_free_stack(struct sljit_stack * stack,void * allocator_data)221*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE void SLJIT_FUNC sljit_free_stack(struct sljit_stack *stack, void *allocator_data)
222*22dc650dSSadaf Ebrahimi {
223*22dc650dSSadaf Ebrahimi SLJIT_UNUSED_ARG(allocator_data);
224*22dc650dSSadaf Ebrahimi VirtualFree((void*)stack->min_start, 0, MEM_RELEASE);
225*22dc650dSSadaf Ebrahimi SLJIT_FREE(stack, allocator_data);
226*22dc650dSSadaf Ebrahimi }
227*22dc650dSSadaf Ebrahimi
228*22dc650dSSadaf Ebrahimi #else /* !_WIN32 */
229*22dc650dSSadaf Ebrahimi
sljit_free_stack(struct sljit_stack * stack,void * allocator_data)230*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE void SLJIT_FUNC sljit_free_stack(struct sljit_stack *stack, void *allocator_data)
231*22dc650dSSadaf Ebrahimi {
232*22dc650dSSadaf Ebrahimi SLJIT_UNUSED_ARG(allocator_data);
233*22dc650dSSadaf Ebrahimi munmap((void*)stack->min_start, (size_t)(stack->end - stack->min_start));
234*22dc650dSSadaf Ebrahimi SLJIT_FREE(stack, allocator_data);
235*22dc650dSSadaf Ebrahimi }
236*22dc650dSSadaf Ebrahimi
237*22dc650dSSadaf Ebrahimi #endif /* _WIN32 */
238*22dc650dSSadaf Ebrahimi
sljit_allocate_stack(sljit_uw start_size,sljit_uw max_size,void * allocator_data)239*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE struct sljit_stack* SLJIT_FUNC sljit_allocate_stack(sljit_uw start_size, sljit_uw max_size, void *allocator_data)
240*22dc650dSSadaf Ebrahimi {
241*22dc650dSSadaf Ebrahimi struct sljit_stack *stack;
242*22dc650dSSadaf Ebrahimi void *ptr;
243*22dc650dSSadaf Ebrahimi sljit_uw page_align;
244*22dc650dSSadaf Ebrahimi
245*22dc650dSSadaf Ebrahimi SLJIT_UNUSED_ARG(allocator_data);
246*22dc650dSSadaf Ebrahimi
247*22dc650dSSadaf Ebrahimi if (start_size > max_size || start_size < 1)
248*22dc650dSSadaf Ebrahimi return NULL;
249*22dc650dSSadaf Ebrahimi
250*22dc650dSSadaf Ebrahimi stack = (struct sljit_stack*)SLJIT_MALLOC(sizeof(struct sljit_stack), allocator_data);
251*22dc650dSSadaf Ebrahimi if (stack == NULL)
252*22dc650dSSadaf Ebrahimi return NULL;
253*22dc650dSSadaf Ebrahimi
254*22dc650dSSadaf Ebrahimi /* Align max_size. */
255*22dc650dSSadaf Ebrahimi page_align = get_page_alignment();
256*22dc650dSSadaf Ebrahimi max_size = (max_size + page_align) & ~page_align;
257*22dc650dSSadaf Ebrahimi
258*22dc650dSSadaf Ebrahimi #ifdef _WIN32
259*22dc650dSSadaf Ebrahimi ptr = VirtualAlloc(NULL, max_size, MEM_RESERVE, PAGE_READWRITE);
260*22dc650dSSadaf Ebrahimi if (!ptr) {
261*22dc650dSSadaf Ebrahimi SLJIT_FREE(stack, allocator_data);
262*22dc650dSSadaf Ebrahimi return NULL;
263*22dc650dSSadaf Ebrahimi }
264*22dc650dSSadaf Ebrahimi
265*22dc650dSSadaf Ebrahimi stack->min_start = (sljit_u8 *)ptr;
266*22dc650dSSadaf Ebrahimi stack->end = stack->min_start + max_size;
267*22dc650dSSadaf Ebrahimi stack->start = stack->end;
268*22dc650dSSadaf Ebrahimi
269*22dc650dSSadaf Ebrahimi if (sljit_stack_resize(stack, stack->end - start_size) == NULL) {
270*22dc650dSSadaf Ebrahimi sljit_free_stack(stack, allocator_data);
271*22dc650dSSadaf Ebrahimi return NULL;
272*22dc650dSSadaf Ebrahimi }
273*22dc650dSSadaf Ebrahimi #else /* !_WIN32 */
274*22dc650dSSadaf Ebrahimi #ifdef MAP_ANON
275*22dc650dSSadaf Ebrahimi ptr = mmap(NULL, max_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
276*22dc650dSSadaf Ebrahimi #else /* !MAP_ANON */
277*22dc650dSSadaf Ebrahimi if (SLJIT_UNLIKELY((dev_zero < 0) && open_dev_zero())) {
278*22dc650dSSadaf Ebrahimi SLJIT_FREE(stack, allocator_data);
279*22dc650dSSadaf Ebrahimi return NULL;
280*22dc650dSSadaf Ebrahimi }
281*22dc650dSSadaf Ebrahimi ptr = mmap(NULL, max_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, dev_zero, 0);
282*22dc650dSSadaf Ebrahimi #endif /* MAP_ANON */
283*22dc650dSSadaf Ebrahimi if (ptr == MAP_FAILED) {
284*22dc650dSSadaf Ebrahimi SLJIT_FREE(stack, allocator_data);
285*22dc650dSSadaf Ebrahimi return NULL;
286*22dc650dSSadaf Ebrahimi }
287*22dc650dSSadaf Ebrahimi stack->min_start = (sljit_u8 *)ptr;
288*22dc650dSSadaf Ebrahimi stack->end = stack->min_start + max_size;
289*22dc650dSSadaf Ebrahimi stack->start = stack->end - start_size;
290*22dc650dSSadaf Ebrahimi #endif /* _WIN32 */
291*22dc650dSSadaf Ebrahimi
292*22dc650dSSadaf Ebrahimi stack->top = stack->end;
293*22dc650dSSadaf Ebrahimi return stack;
294*22dc650dSSadaf Ebrahimi }
295*22dc650dSSadaf Ebrahimi
sljit_stack_resize(struct sljit_stack * stack,sljit_u8 * new_start)296*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_u8 *SLJIT_FUNC sljit_stack_resize(struct sljit_stack *stack, sljit_u8 *new_start)
297*22dc650dSSadaf Ebrahimi {
298*22dc650dSSadaf Ebrahimi #if defined _WIN32 || defined(POSIX_MADV_DONTNEED)
299*22dc650dSSadaf Ebrahimi sljit_uw aligned_old_start;
300*22dc650dSSadaf Ebrahimi sljit_uw aligned_new_start;
301*22dc650dSSadaf Ebrahimi sljit_uw page_align;
302*22dc650dSSadaf Ebrahimi #endif
303*22dc650dSSadaf Ebrahimi
304*22dc650dSSadaf Ebrahimi if ((new_start < stack->min_start) || (new_start >= stack->end))
305*22dc650dSSadaf Ebrahimi return NULL;
306*22dc650dSSadaf Ebrahimi
307*22dc650dSSadaf Ebrahimi #ifdef _WIN32
308*22dc650dSSadaf Ebrahimi page_align = get_page_alignment();
309*22dc650dSSadaf Ebrahimi
310*22dc650dSSadaf Ebrahimi aligned_new_start = (sljit_uw)new_start & ~page_align;
311*22dc650dSSadaf Ebrahimi aligned_old_start = ((sljit_uw)stack->start) & ~page_align;
312*22dc650dSSadaf Ebrahimi if (aligned_new_start != aligned_old_start) {
313*22dc650dSSadaf Ebrahimi if (aligned_new_start < aligned_old_start) {
314*22dc650dSSadaf Ebrahimi if (!VirtualAlloc((void*)aligned_new_start, aligned_old_start - aligned_new_start, MEM_COMMIT, PAGE_READWRITE))
315*22dc650dSSadaf Ebrahimi return NULL;
316*22dc650dSSadaf Ebrahimi }
317*22dc650dSSadaf Ebrahimi else {
318*22dc650dSSadaf Ebrahimi if (!VirtualFree((void*)aligned_old_start, aligned_new_start - aligned_old_start, MEM_DECOMMIT))
319*22dc650dSSadaf Ebrahimi return NULL;
320*22dc650dSSadaf Ebrahimi }
321*22dc650dSSadaf Ebrahimi }
322*22dc650dSSadaf Ebrahimi #elif defined(POSIX_MADV_DONTNEED)
323*22dc650dSSadaf Ebrahimi if (stack->start < new_start) {
324*22dc650dSSadaf Ebrahimi page_align = get_page_alignment();
325*22dc650dSSadaf Ebrahimi
326*22dc650dSSadaf Ebrahimi aligned_new_start = (sljit_uw)new_start & ~page_align;
327*22dc650dSSadaf Ebrahimi aligned_old_start = ((sljit_uw)stack->start) & ~page_align;
328*22dc650dSSadaf Ebrahimi
329*22dc650dSSadaf Ebrahimi if (aligned_new_start > aligned_old_start) {
330*22dc650dSSadaf Ebrahimi posix_madvise((void*)aligned_old_start, aligned_new_start - aligned_old_start, POSIX_MADV_DONTNEED);
331*22dc650dSSadaf Ebrahimi #ifdef MADV_FREE
332*22dc650dSSadaf Ebrahimi madvise((void*)aligned_old_start, aligned_new_start - aligned_old_start, MADV_FREE);
333*22dc650dSSadaf Ebrahimi #endif /* MADV_FREE */
334*22dc650dSSadaf Ebrahimi }
335*22dc650dSSadaf Ebrahimi }
336*22dc650dSSadaf Ebrahimi #endif /* _WIN32 */
337*22dc650dSSadaf Ebrahimi
338*22dc650dSSadaf Ebrahimi stack->start = new_start;
339*22dc650dSSadaf Ebrahimi return new_start;
340*22dc650dSSadaf Ebrahimi }
341*22dc650dSSadaf Ebrahimi
342*22dc650dSSadaf Ebrahimi #endif /* SLJIT_UTIL_SIMPLE_STACK_ALLOCATION */
343*22dc650dSSadaf Ebrahimi
344*22dc650dSSadaf Ebrahimi #endif /* SLJIT_UTIL_STACK */
345