diff options
author | zherczeg <zherczeg@2f5784b3-3f2a-0410-8824-cb99058d5e15> | 2017-03-27 13:40:53 +0000 |
---|---|---|
committer | zherczeg <zherczeg@2f5784b3-3f2a-0410-8824-cb99058d5e15> | 2017-03-27 13:40:53 +0000 |
commit | f6f0dd9cdc9e4df83c6d1686dfc962ff82c2ee2b (patch) | |
tree | 262ad88e5b3db921a690a30ce6446292dc3bc917 /sljit | |
parent | 881b9580da401953f2a94b42cb9cc275b4719341 (diff) | |
download | pcre-f6f0dd9cdc9e4df83c6d1686dfc962ff82c2ee2b.tar.gz |
Reverse the jit-stack to top-down.
git-svn-id: svn://vcs.exim.org/pcre/code/trunk@1690 2f5784b3-3f2a-0410-8824-cb99058d5e15
Diffstat (limited to 'sljit')
-rw-r--r-- | sljit/sljitLir.h | 43 | ||||
-rw-r--r-- | sljit/sljitUtils.c | 67 |
2 files changed, 56 insertions, 54 deletions
diff --git a/sljit/sljitLir.h b/sljit/sljitLir.h index 833038f..8ecd22a 100644 --- a/sljit/sljitLir.h +++ b/sljit/sljitLir.h @@ -1228,19 +1228,23 @@ SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_release_lock(void); #if (defined SLJIT_UTIL_STACK && SLJIT_UTIL_STACK) -/* The sljit_stack is a utiliy feature of sljit, which allocates a - writable memory region between base (inclusive) and limit (exclusive). - Both base and limit is a pointer, and base is always <= than limit. - This feature uses the "address space reserve" feature - of modern operating systems. Basically we don't need to allocate a - huge memory block in one step for the worst case, we can start with - a smaller chunk and extend it later. Since the address space is - reserved, the data never copied to other regions, thus it is safe - to store pointers here. */ - -/* Note: The base field is aligned to PAGE_SIZE bytes (usually 4k or more). - Note: stack growing should not happen in small steps: 4k, 16k or even - bigger growth is better. +/* The sljit_stack is a utility extension of sljit, which provides + a top-down stack. The stack starts at base and goes down to + max_limit, so the memory region for this stack is between + max_limit (inclusive) and base (exclusive). However the + application can only use the region between limit (inclusive) + and base (exclusive). The sljit_stack_resize can be used to + extend this region up to max_limit. + + This feature uses the "address space reserve" feature of modern + operating systems, so instead of allocating a huge memory block + applications can allocate a small region and extend it later + without moving the memory area. Hence pointers can be stored + in this area. */ + +/* Note: base and max_limit fields are aligned to PAGE_SIZE bytes + (usually 4 Kbyte or more). + Note: stack should grow in larger steps, e.g. 4Kbyte, 16Kbyte or more. Note: this structure may not be supported by all operating systems. Some kind of fallback mechanism is suggested when SLJIT_UTIL_STACK is not defined. */ @@ -1248,15 +1252,16 @@ SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_release_lock(void); struct sljit_stack { /* User data, anything can be stored here. Starting with the same value as base. */ - sljit_uw top; + sljit_u8 *top; /* These members are read only. */ - sljit_uw base; - sljit_uw limit; - sljit_uw max_limit; + sljit_u8 *base; + sljit_u8 *limit; + sljit_u8 *max_limit; }; /* Returns NULL if unsuccessful. - Note: limit and max_limit contains the size for stack allocation. + Note: max_limit contains the maximum stack size in bytes. + Note: limit contains the starting stack size in bytes. Note: the top field is initialized to base. Note: see sljit_create_compiler for the explanation of allocator_data. */ SLJIT_API_FUNC_ATTRIBUTE struct sljit_stack* SLJIT_CALL sljit_allocate_stack(sljit_uw limit, sljit_uw max_limit, void *allocator_data); @@ -1268,7 +1273,7 @@ SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_free_stack(struct sljit_stack *st since the growth ratio can be added to the current limit, and sljit_stack_resize will do all the necessary checks. The fields of the stack are not changed if sljit_stack_resize fails. */ -SLJIT_API_FUNC_ATTRIBUTE sljit_sw SLJIT_CALL sljit_stack_resize(struct sljit_stack *stack, sljit_uw new_limit); +SLJIT_API_FUNC_ATTRIBUTE sljit_sw SLJIT_CALL sljit_stack_resize(struct sljit_stack *stack, sljit_u8 *new_limit); #endif /* (defined SLJIT_UTIL_STACK && SLJIT_UTIL_STACK) */ diff --git a/sljit/sljitUtils.c b/sljit/sljitUtils.c index 7db09c3..9029db2 100644 --- a/sljit/sljitUtils.c +++ b/sljit/sljitUtils.c @@ -206,10 +206,7 @@ static sljit_sw sljit_page_align = 0; SLJIT_API_FUNC_ATTRIBUTE struct sljit_stack* SLJIT_CALL sljit_allocate_stack(sljit_uw limit, sljit_uw max_limit, void *allocator_data) { struct sljit_stack *stack; - union { - void *ptr; - sljit_uw uw; - } base; + void *ptr; #ifdef _WIN32 SYSTEM_INFO si; #endif @@ -233,29 +230,29 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_stack* SLJIT_CALL sljit_allocate_stack(slj } #endif - /* Align limit and max_limit. */ - max_limit = (max_limit + sljit_page_align) & ~sljit_page_align; - stack = (struct sljit_stack*)SLJIT_MALLOC(sizeof(struct sljit_stack), allocator_data); if (!stack) return NULL; + /* Align max_limit. */ + max_limit = (max_limit + sljit_page_align) & ~sljit_page_align; + #ifdef _WIN32 - base.ptr = VirtualAlloc(NULL, max_limit, MEM_RESERVE, PAGE_READWRITE); - if (!base.ptr) { + ptr = VirtualAlloc(NULL, max_limit, MEM_RESERVE, PAGE_READWRITE); + if (!ptr) { SLJIT_FREE(stack, allocator_data); return NULL; } - stack->base = base.uw; + stack->max_limit = (sljit_u8 *)ptr; + stack->base = stack->max_limit + max_limit; stack->limit = stack->base; - stack->max_limit = stack->base + max_limit; - if (sljit_stack_resize(stack, stack->base + limit)) { + if (sljit_stack_resize(stack, stack->base - limit)) { sljit_free_stack(stack, allocator_data); return NULL; } #else #ifdef MAP_ANON - base.ptr = mmap(NULL, max_limit, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); + ptr = mmap(NULL, max_limit, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); #else if (dev_zero < 0) { if (open_dev_zero()) { @@ -263,15 +260,15 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_stack* SLJIT_CALL sljit_allocate_stack(slj return NULL; } } - base.ptr = mmap(NULL, max_limit, PROT_READ | PROT_WRITE, MAP_PRIVATE, dev_zero, 0); + ptr = mmap(NULL, max_limit, PROT_READ | PROT_WRITE, MAP_PRIVATE, dev_zero, 0); #endif - if (base.ptr == MAP_FAILED) { + if (ptr == MAP_FAILED) { SLJIT_FREE(stack, allocator_data); return NULL; } - stack->base = base.uw; - stack->limit = stack->base + limit; - stack->max_limit = stack->base + max_limit; + stack->max_limit = (sljit_u8 *)ptr; + stack->base = stack->max_limit + max_limit; + stack->limit = stack->base - limit; #endif stack->top = stack->base; return stack; @@ -279,53 +276,53 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_stack* SLJIT_CALL sljit_allocate_stack(slj #undef PAGE_ALIGN -SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_free_stack(struct sljit_stack* stack, void *allocator_data) +SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_free_stack(struct sljit_stack *stack, void *allocator_data) { SLJIT_UNUSED_ARG(allocator_data); #ifdef _WIN32 - VirtualFree((void*)stack->base, 0, MEM_RELEASE); + VirtualFree((void*)stack->max_limit, 0, MEM_RELEASE); #else - munmap((void*)stack->base, stack->max_limit - stack->base); + munmap((void*)stack->max_limit, stack->base - stack->max_limit); #endif SLJIT_FREE(stack, allocator_data); } -SLJIT_API_FUNC_ATTRIBUTE sljit_sw SLJIT_CALL sljit_stack_resize(struct sljit_stack* stack, sljit_uw new_limit) +SLJIT_API_FUNC_ATTRIBUTE sljit_sw SLJIT_CALL sljit_stack_resize(struct sljit_stack *stack, sljit_u8 *new_limit) { sljit_uw aligned_old_limit; sljit_uw aligned_new_limit; - if ((new_limit > stack->max_limit) || (new_limit < stack->base)) + if ((new_limit < stack->max_limit) || (new_limit >= stack->base)) return -1; #ifdef _WIN32 - aligned_new_limit = (new_limit + sljit_page_align) & ~sljit_page_align; - aligned_old_limit = (stack->limit + sljit_page_align) & ~sljit_page_align; + aligned_new_limit = (sljit_uw)new_limit & ~sljit_page_align; + aligned_old_limit = ((sljit_uw)stack->limit) & ~sljit_page_align; if (aligned_new_limit != aligned_old_limit) { - if (aligned_new_limit > aligned_old_limit) { - if (!VirtualAlloc((void*)aligned_old_limit, aligned_new_limit - aligned_old_limit, MEM_COMMIT, PAGE_READWRITE)) + if (aligned_new_limit < aligned_old_limit) { + if (!VirtualAlloc((void*)aligned_new_limit, aligned_old_limit - aligned_new_limit, MEM_COMMIT, PAGE_READWRITE)) return -1; } else { - if (!VirtualFree((void*)aligned_new_limit, aligned_old_limit - aligned_new_limit, MEM_DECOMMIT)) + if (!VirtualFree((void*)aligned_old_limit, aligned_new_limit - aligned_old_limit, MEM_DECOMMIT)) return -1; } } stack->limit = new_limit; return 0; #else - if (new_limit >= stack->limit) { + if (new_limit <= stack->limit) { stack->limit = new_limit; return 0; } - aligned_new_limit = (new_limit + sljit_page_align) & ~sljit_page_align; - aligned_old_limit = (stack->limit + sljit_page_align) & ~sljit_page_align; + aligned_new_limit = (sljit_uw)new_limit & ~sljit_page_align; + aligned_old_limit = ((sljit_uw)stack->limit) & ~sljit_page_align; /* If madvise is available, we release the unnecessary space. */ #if defined(MADV_DONTNEED) - if (aligned_new_limit < aligned_old_limit) - madvise((void*)aligned_new_limit, aligned_old_limit - aligned_new_limit, MADV_DONTNEED); + if (aligned_new_limit > aligned_old_limit) + madvise((void*)aligned_old_limit, aligned_new_limit - aligned_old_limit, MADV_DONTNEED); #elif defined(POSIX_MADV_DONTNEED) - if (aligned_new_limit < aligned_old_limit) - posix_madvise((void*)aligned_new_limit, aligned_old_limit - aligned_new_limit, POSIX_MADV_DONTNEED); + if (aligned_new_limit > aligned_old_limit) + posix_madvise((void*)aligned_old_limit, aligned_new_limit - aligned_old_limit, POSIX_MADV_DONTNEED); #endif stack->limit = new_limit; return 0; |