From: Aleksey Demakov Date: Sun, 29 Jul 2012 07:01:29 +0000 (+0400) Subject: Refactor function cache allocation API. X-Git-Url: https://git.unchartedbackwaters.co.uk/w/?a=commitdiff_plain;h=a2a60671b99b64e42dbc1e2b25a311a1c40b8a4c;p=francis%2Flibjit.git Refactor function cache allocation API. Merge branch 'master' into cache-refactoring Conflicts: ChangeLog --- a2a60671b99b64e42dbc1e2b25a311a1c40b8a4c diff --cc ChangeLog index 4a3be53,468b5a1..ff44f8a --- a/ChangeLog +++ b/ChangeLog @@@ -1,41 -1,15 +1,67 @@@ ++2012-07-29 Aleksey Demakov ++ ++ * jit/jit-cache.h, jit/jit-cache.c (_jit_cache_start_function) ++ (_jit_cache_end_function, _jit_cache_get_code_break) ++ (_jit_cache_set_code_break, _jit_cache_get_code_limit) ++ (_jit_cache_alloc_data): new API for function allocation. ++ * jit/jit-cache.h, jit/jit-cache.c (_jit_cache_is_full) ++ (_jit_cache_start_method, _jit_cache_end_method) ++ (_jit_cache_alloc, _jit_cache_check_space): remove. ++ * jit/jit-cache.h, jit/jit-rules.h: remove jit_cache_posn struct. ++ Store the cache position data in jit_gencode struct. ++ * jit/jit-rules.h, jit/jit-rules.c: (_jit_gen_check_space) ++ (_jit_gen_alloc): add. ++ +2012-02-11 Aleksey Demakov + + * jit/jit-cache.h, jit/jit-cache.c (_jit_cache_end_method): add + result argument that indicates if the code genration will need + to be restarted. + * jit/jit-cache.h, jit/jit-cache.c (jit_cache_mark_full): remove + macro and replace it with direct jit_cache_posn access where + appropriate. + * jit/jit-cache.h, jit/jit-cache.c (jit_cache_get_posn): likewise. + * jit/jit-cache.h, jit/jit-rules-interp.c (jit_cache_native): move + macro to where it only used. + * jit/jit-cache.h, jit/jit-cache.c: remove other unused stuff. + + 2012-01-22 Klaus Treichel + + * config/jit-opcodes.ops: Move declaration of obsolete opcodes to + the separate include file jit-opcode-compat.h and include this new + file instead. + + * include/jit/jit-opcode-compat.h: add new include file for + obsolete opcodes. + + * include/jit/Makefile.am: add jit-opcode-compat.h to the include + sources. + +2012-01-21 Aleksey Demakov + + * jit/jit-rules.h (struct jit_gencode): add offset_encoder field + to encode bytecode offsets with jit_varints. + + * jit/jit-internal.h (struct _jit_function): move fields cookie, + start, end here from jit_cache_method; add bytecode_offset field + to encode bytecode offsets with jit_varints. + + * jit/jit-compile.c (mark_offset, _jit_function_get_bytecode): add + functions that use jit_varints for bytecode offset compression. + + * jit/jit-cache.h, jit/jit-cache.c (_jit_cache_get_method): + remove cookie argument. + + * jit/jit-cache.h, jit/jit-cache.c (_jit_cache_mark_bytecode) + (_jit_cache_set_cookie, _jit_cache_get_start_method) + (_jit_cache_get_end_method, _jit_cache_get_native) + (_jit_cache_get_bytecode, _jit_cache_get_size): remove functions, + get rid of bytecode offset compression and method region machinary. + + * jit/jit-dump.c, jit/jit-function.c, jit/jit-rules-interp.c + * jit/jit-except.c, jit/jit-unwind.c: adjust where appropriate for + cache API change. + 2011-12-18 Aleksey Demakov * jit/Makefile.am: diff --cc jit/jit-cache.c index afda4f8,bf2ceef..e813a15 --- a/jit/jit-cache.c +++ b/jit/jit-cache.c @@@ -82,15 -99,202 +82,39 @@@ struct jit_cach unsigned long maxNumPages; /* Maximum number of pages that could be in the list */ unsigned long pageSize; /* Default size of a page for allocation */ unsigned int maxPageFactor; /* Maximum page size factor */ -- unsigned char *freeStart; /* Start of the current free region */ -- unsigned char *freeEnd; /* End of the current free region */ long pagesLeft; /* Number of pages left to allocate */ ++ unsigned char *free_start; /* Current start of the free region */ ++ unsigned char *free_end; /* Current end of the free region */ ++ unsigned char *prev_start; /* Previous start of the free region */ ++ unsigned char *prev_end; /* Previous end of the free region */ jit_cache_method_t method; /* Information for the current method */ struct jit_cache_method head; /* Head of the lookup tree */ struct jit_cache_method nil; /* Nil pointer for the lookup tree */ -- unsigned char *start; /* Start of the current method */ - unsigned char debugData[JIT_CACHE_DEBUG_SIZE]; - int debugLen; /* Length of temporary debug data */ - jit_cache_debug_t firstDebug; /* First debug block for method */ - jit_cache_debug_t lastDebug; /* Last debug block for method */ - }; + /* - * Compress a "long" value so that it takes up less bytes. - * This is used to store offsets within functions and - * debug line numbers, which are usually small integers. - */ -static int CompressInt(unsigned char *buf, long data) -{ - if(data >= 0) - { - if(data < (long)0x40) - { - buf[0] = (unsigned char)(data << 1); - return 1; - } - else if(data < (long)(1 << 13)) - { - buf[0] = (unsigned char)(((data >> 7) & 0x3F) | 0x80); - buf[1] = (unsigned char)(data << 1); - return 2; - } - else if(data < (long)(1L << 28)) - { - buf[0] = (unsigned char)((data >> 23) | 0xC0); - buf[1] = (unsigned char)(data >> 15); - buf[2] = (unsigned char)(data >> 7); - buf[3] = (unsigned char)(data << 1); - return 4; - } - else - { - buf[0] = (unsigned char)0xE0; - buf[1] = (unsigned char)(data >> 23); - buf[2] = (unsigned char)(data >> 15); - buf[3] = (unsigned char)(data >> 7); - buf[4] = (unsigned char)(data << 1); - return 5; - } - } - else - { - if(data >= ((long)-0x40)) - { - buf[0] = ((((unsigned char)(data << 1)) & 0x7E) | 0x01); - return 1; - } - else if(data >= ((long)-(1 << 13))) - { - buf[0] = (unsigned char)(((data >> 7) & 0x3F) | 0x80); - buf[1] = (unsigned char)((data << 1) | 0x01); - return 2; - } - else if(data >= ((long)-(1L << 29))) - { - buf[0] = (unsigned char)(((data >> 23) & 0x1F) | 0xC0); - buf[1] = (unsigned char)(data >> 15); - buf[2] = (unsigned char)(data >> 7); - buf[3] = (unsigned char)((data << 1) | 0x01); - return 4; - } - else - { - buf[0] = (unsigned char)0xE1; - buf[1] = (unsigned char)(data >> 23); - buf[2] = (unsigned char)(data >> 15); - buf[3] = (unsigned char)(data >> 7); - buf[4] = (unsigned char)((data << 1) | 0x01); - return 5; - } - } -} - -/* - * Control data structure that is used by "UncompressInt". ++ * Get or set the sub-trees of a node. + */ -typedef struct -{ - const unsigned char *data; /* Current data position */ - unsigned long len; /* Length remaining to read */ - int error; /* Set to non-zero if error encountered */ - -} UncompressReader; ++#define GetLeft(node) \ ++ ((jit_cache_method_t)(((jit_nuint)(node)->left) & ~((jit_nuint)1))) ++#define GetRight(node) \ ++ ((node)->right) ++#define SetLeft(node,value) \ ++ ((node)->left = (jit_cache_method_t)(((jit_nuint)value) | \ ++ (((jit_nuint)(node)->left) & ((jit_nuint)1)))) ++#define SetRight(node,value) \ ++ ((node)->right = (value)) + + /* - * Uncompress a value that was compressed by "CompressInt". ++ * Get or set the red/black state of a node. + */ -static long UncompressInt(UncompressReader *meta) -{ - unsigned char ch; - unsigned char ch2; - unsigned char ch3; - unsigned char ch4; - unsigned long value; - - if(meta->len > 0) - { - ch = *((meta->data)++); - --(meta->len); - if((ch & 0x80) == 0x00) - { - /* One-byte form of the item */ - if((ch & 0x01) == 0x00) - return (long)(ch >> 1); - else - return (long)(signed char)((ch >> 1) | 0xC0); - } - else if((ch & 0xC0) == 0x80) - { - /* Two-byte form of the item */ - if(meta->len > 0) - { - --(meta->len); - value = (((unsigned long)(ch & 0x3F)) << 8) | - ((unsigned long)(*((meta->data)++))); - if((value & 0x01) == 0x00) - return (long)(value >> 1); - else - return (long)(jit_int)((value >> 1) | 0xFFFFE000); - } - else - { - meta->error = 1; - return 0; - } - } - else if((ch & 0xE0) == 0xC0) - { - /* Four-byte form of the item */ - if(meta->len >= 3) - { - ch2 = meta->data[0]; - ch3 = meta->data[1]; - ch4 = meta->data[2]; - meta->len -= 3; - meta->data += 3; - value = (((unsigned long)(ch & 0x1F)) << 24) | - (((unsigned long)ch2) << 16) | - (((unsigned long)ch3) << 8) | - ((unsigned long)ch4); - if((value & 0x01) == 0x00) - return (long)(value >> 1); - else - return (long)(jit_int)((value >> 1) | 0xF0000000); - } - else - { - meta->len = 0; - meta->error = 1; - return 0; - } - } - else - { - /* Five-byte form of the item */ - if(meta->len >= 4) - { - ch = meta->data[0]; - ch2 = meta->data[1]; - ch3 = meta->data[2]; - ch4 = meta->data[3]; - meta->len -= 4; - meta->data += 4; - value = (((unsigned long)ch) << 24) | - (((unsigned long)ch2) << 16) | - (((unsigned long)ch3) << 8) | - ((unsigned long)ch4); - return (long)(jit_int)value; - } - else - { - meta->len = 0; - meta->error = 1; - return 0; - } - } - } - else - { - meta->error = 1; - return 0; - } -} ++#define GetRed(node) \ ++ ((((jit_nuint)((node)->left)) & ((jit_nuint)1)) != 0) ++#define SetRed(node) \ ++ ((node)->left = (jit_cache_method_t)(((jit_nuint)(node)->left) | ((jit_nuint)1))) ++#define SetBlack(node) \ ++ ((node)->left = (jit_cache_method_t)(((jit_nuint)(node)->left) & ~((jit_nuint)1))) + /* * Allocate a cache page and add it to the cache. */ @@@ -151,8 -355,8 +175,8 @@@ static void AllocCachePage(jit_cache_t { jit_free_exec(ptr, cache->pageSize * factor); failAlloc: -- cache->freeStart = 0; -- cache->freeEnd = 0; ++ cache->free_start = 0; ++ cache->free_end = 0; return; } @@@ -170,39 -374,39 +194,15 @@@ } /* Set up the working region within the new page */ -- cache->freeStart = ptr; -- cache->freeEnd = ptr + (int) cache->pageSize * factor; ++ cache->free_start = ptr; ++ cache->free_end = ptr + (int) cache->pageSize * factor; } --/* -- * Get or set the sub-trees of a node. -- */ --#define GetLeft(node) \ -- ((jit_cache_method_t)(((jit_nuint)((node)->left)) & ~((jit_nuint)1))) --#define GetRight(node) ((node)->right) --#define SetLeft(node,value) \ -- ((node)->left = (jit_cache_method_t)(((jit_nuint)(value)) | \ -- (((jit_nuint)((node)->left)) & ((jit_nuint)1)))) --#define SetRight(node,value) \ -- ((node)->right = (value)) -- --/* -- * Get or set the red/black state of a node. -- */ --#define GetRed(node) \ -- ((((jit_nuint)((node)->left)) & ((jit_nuint)1)) != 0) --#define SetRed(node) \ -- ((node)->left = (jit_cache_method_t)(((jit_nuint)((node)->left)) | \ -- ((jit_nuint)1))) --#define SetBlack(node) \ -- ((node)->left = (jit_cache_method_t)(((jit_nuint)((node)->left)) & \ -- ~((jit_nuint)1))) -- /* * Compare a key against a node, being careful of sentinel nodes. */ --static int CacheCompare(jit_cache_t cache, unsigned char *key, -- jit_cache_method_t node) ++static int ++CacheCompare(jit_cache_t cache, unsigned char *key, jit_cache_method_t node) { if(node == &(cache->nil) || node == &(cache->head)) { @@@ -212,11 -416,11 +212,11 @@@ else { /* Compare a regular node */ - if(key < node->func->start) - if(key < node->start) ++ if(key < node->func->code_start) { return -1; } - else if(key > node->func->start) - else if(key > node->start) ++ else if(key > node->func->code_start) { return 1; } @@@ -295,7 -499,7 +295,7 @@@ static jit_cache_method_t CacheRotate(j */ static void AddToLookupTree(jit_cache_t cache, jit_cache_method_t method) { - unsigned char *key = method->func->start; - unsigned char *key = method->start; ++ unsigned char *key = method->func->code_start; jit_cache_method_t temp; jit_cache_method_t greatGrandParent; jit_cache_method_t grandParent; @@@ -354,7 -558,67 +354,29 @@@ SetBlack(cache->head.right); } - jit_cache_t _jit_cache_create(long limit, long cache_page_size, int max_page_factor) -/* - * Flush the current debug buffer. - */ -static void FlushCacheDebug(jit_cache_posn *posn) ++static unsigned char * ++cache_alloc_data(jit_cache_t cache, unsigned long size, unsigned long align) + { - jit_cache_t cache = posn->cache; - jit_cache_debug_t debug; - - /* Allocate a new jit_cache_debug structure to hold the data */ - debug = _jit_cache_alloc(posn, - (unsigned long)(sizeof(struct jit_cache_debug) + cache->debugLen)); - if(!debug) - { - cache->debugLen = 0; - return; - } - - /* Copy the temporary debug data into the new structure */ - jit_memcpy(debug + 1, cache->debugData, cache->debugLen); - - /* Link the structure into the debug list */ - debug->next = 0; - if(cache->lastDebug) - { - cache->lastDebug->next = debug; - } - else - { - cache->firstDebug = debug; - } - cache->lastDebug = debug; - - /* Reset the temporary debug buffer */ - cache->debugLen = 0; -} ++ unsigned char *ptr; + -/* - * Write a debug pair to the cache. The pair (-1, -1) - * terminates the debug information for a method. - */ -static void WriteCacheDebug(jit_cache_posn *posn, long offset, long nativeOffset) -{ - jit_cache_t cache = posn->cache; - - /* Write the two values to the temporary debug buffer */ - cache->debugLen += CompressInt - (cache->debugData + cache->debugLen, offset); - cache->debugLen += CompressInt - (cache->debugData + cache->debugLen, nativeOffset); - if((cache->debugLen + 5 * 2 + 1) > (int)(sizeof(cache->debugData))) ++ /* Allocate memory from the top of the free region, so that it ++ does not overlap with the method code being written at the ++ bottom of the free region */ ++ ptr = cache->free_end - size; ++ ptr = (unsigned char *) (((jit_nuint) ptr) & ~((jit_nuint) align - 1)); ++ if(ptr < cache->free_start) + { - /* Overflow occurred: write -2 to mark the end of this buffer */ - cache->debugLen += CompressInt - (cache->debugData + cache->debugLen, -2); - - /* Flush the debug data that we have collected so far */ - FlushCacheDebug(posn); ++ /* When we aligned the block, it caused an overflow */ ++ return 0; + } ++ ++ /* Allocate the block and return it */ ++ cache->free_end = ptr; ++ return ptr; + } + -jit_cache_t _jit_cache_create(long limit, long cache_page_size, int max_page_factor) ++jit_cache_t ++_jit_cache_create(long limit, long cache_page_size, int max_page_factor) { jit_cache_t cache; unsigned long exec_page_size; @@@ -392,8 -656,8 +414,8 @@@ cache->maxNumPages = 0; cache->pageSize = cache_page_size; cache->maxPageFactor = max_page_factor; -- cache->freeStart = 0; -- cache->freeEnd = 0; ++ cache->free_start = 0; ++ cache->free_end = 0; if(limit > 0) { cache->pagesLeft = limit / cache_page_size; @@@ -407,17 -671,28 +429,16 @@@ cache->pagesLeft = -1; } cache->method = 0; - cache->nil.method = 0; - cache->nil.cookie = 0; - cache->nil.start = 0; - cache->nil.end = 0; - cache->nil.debug = 0; + cache->nil.func = 0; cache->nil.left = &(cache->nil); cache->nil.right = &(cache->nil); - cache->head.method = 0; - cache->head.cookie = 0; - cache->head.start = 0; - cache->head.end = 0; - cache->head.debug = 0; + cache->head.func = 0; cache->head.left = 0; cache->head.right = &(cache->nil); -- cache->start = 0; - cache->debugLen = 0; - cache->firstDebug = 0; - cache->lastDebug = 0; /* Allocate the initial cache page */ AllocCachePage(cache, 0); -- if(!cache->freeStart) ++ if(!cache->free_start) { _jit_cache_destroy(cache); return 0; @@@ -427,7 -702,7 +448,8 @@@ return cache; } --void _jit_cache_destroy(jit_cache_t cache) ++void ++_jit_cache_destroy(jit_cache_t cache) { unsigned long page; @@@ -446,224 -721,591 +468,238 @@@ jit_free(cache); } --int _jit_cache_is_full(jit_cache_t cache, jit_cache_posn *posn) - { - return (!cache->freeStart || (posn && posn->ptr >= posn->limit)); - } - - void - _jit_cache_check_space(jit_cache_posn *posn, int space) ++int ++_jit_cache_start_function(jit_cache_t cache, jit_function_t func, int restart_count) { - if((posn->ptr + space) >= posn->limit) - return (!cache->freeStart || (posn && posn->ptr >= posn->limit)); -} - -void -_jit_cache_check_space(jit_cache_posn *posn, int space) -{ - if(!jit_cache_check_for_n(posn, space)) ++ /* Bail out if there is a started function already */ ++ if(cache->method) { -- /* No space left on the current cache page. */ - posn->ptr = posn->limit; - jit_cache_mark_full(posn); -- jit_exception_builtin(JIT_RESULT_CACHE_FULL); ++ return JIT_CACHE_ERROR; } --} -- --int _jit_cache_start_method(jit_cache_t cache, -- jit_cache_posn *posn, -- int page_factor, -- int align, - jit_function_t func) - void *method) --{ -- unsigned char *ptr; /* Do we need to allocate a new cache page? */ -- if(page_factor > 0) ++ if(restart_count > 0) { -- AllocCachePage(cache, page_factor); ++ /* Compute the page size factor */ ++ int factor = 1 << (restart_count - 1); ++ ++ /* If we had a newly allocated page then it has to be freed ++ to let allocate another new page of appropriate size. */ ++ struct jit_cache_page *p = &cache->pages[cache->numPages - 1]; ++ if((cache->free_start == ((unsigned char *)p->page)) ++ && (cache->free_end == (cache->free_start + cache->pageSize * p->factor))) ++ { ++ jit_free_exec(p->page, cache->pageSize * p->factor); ++ ++ --(cache->numPages); ++ if(cache->pagesLeft >= 0) ++ { ++ cache->pagesLeft += p->factor; ++ } ++ cache->free_start = 0; ++ cache->free_end = 0; ++ ++ if(factor <= p->factor) ++ { ++ factor = p->factor << 1; ++ } ++ } ++ ++ /* Allocate a new page now */ ++ AllocCachePage(cache, factor); } /* Bail out if the cache is already full */ -- if(!cache->freeStart) ++ if(!cache->free_start) { return JIT_CACHE_TOO_BIG; } -- /* Set up the initial cache position */ -- posn->cache = cache; -- posn->ptr = cache->freeStart; -- posn->limit = cache->freeEnd; -- -- /* Align the method start */ -- ptr = posn->ptr; -- if(align > 1) -- { -- ptr = (unsigned char *)(((jit_nuint) (ptr + align - 1)) & ~((jit_nuint) (align - 1))); -- } -- if(ptr >= posn->limit) -- { -- /* There is insufficient space in this page */ -- posn->ptr = posn->limit; -- return JIT_CACHE_RESTART; -- } --#ifdef jit_should_pad -- if(ptr > posn->ptr) -- { -- _jit_pad_buffer(posn->ptr, ptr - posn->ptr); -- } --#endif -- posn->ptr = ptr; ++ /* Save the cache position */ ++ cache->prev_start = cache->free_start; ++ cache->prev_end = cache->free_end; /* Allocate memory for the method information block */ -- cache->method = (jit_cache_method_t) _jit_cache_alloc(posn, sizeof(struct jit_cache_method)); ++ cache->method = (jit_cache_method_t) cache_alloc_data(cache, ++ sizeof(struct jit_cache_method), ++ JIT_BEST_ALIGNMENT); if(!cache->method) { /* There is insufficient space in this page */ return JIT_CACHE_RESTART; } - cache->method->method = method; - cache->method->cookie = 0; - cache->method->start = posn->ptr; - cache->method->end = posn->ptr; - cache->method->debug = 0; + cache->method->func = func; - cache->method->func->start = posn->ptr; - cache->method->func->end = posn->ptr; ++ cache->method->func->code_start = cache->free_start; ++ cache->method->func->code_end = cache->free_start; cache->method->left = 0; cache->method->right = 0; -- /* Store the method start address */ -- cache->start = posn->ptr; - - /* Clear the debug data */ - cache->debugLen = 0; - cache->firstDebug = 0; - cache->lastDebug = 0; -- return JIT_CACHE_OK; } -int _jit_cache_end_method(jit_cache_posn *posn) +int - _jit_cache_end_method(jit_cache_posn *posn, int result) ++_jit_cache_end_function(jit_cache_t cache, int result) { -- jit_cache_t cache = posn->cache; -- jit_cache_method_t method; -- jit_cache_method_t next; -- - if (result != JIT_CACHE_OK) - /* Determine if we ran out of space while writing the method */ - if(posn->ptr >= posn->limit) - { - /* If we had a newly allocated page then it has to be freed - to let allocate another new page of appropriate size. */ - if((cache->freeStart == ((unsigned char *)(cache->pages[cache->numPages - 1].page))) - && (cache->freeEnd - == (cache->freeStart + (cache->pageSize * cache->pages[cache->numPages - 1].factor)))) - { - --(cache->numPages); - jit_free_exec(cache->pages[cache->numPages].page, - cache->pageSize * cache->pages[cache->numPages].factor); - if (cache->pagesLeft >= 0) - { - cache->pagesLeft += cache->pages[cache->numPages].factor; - } - cache->freeStart = 0; - cache->freeEnd = 0; - } - return JIT_CACHE_RESTART; - } - - /* Terminate the debug information and flush it */ - if(cache->firstDebug || cache->debugLen) ++ /* Bail out if there is no started function */ ++ if(!cache->method) { - /* mark cache page full */ - posn->ptr = posn->limit; - WriteCacheDebug(posn, -1, -1); - if(cache->debugLen) - { - FlushCacheDebug(posn); - } ++ return JIT_CACHE_ERROR; } - /* Determine if we ran out of space while writing the method */ - if(posn->ptr >= posn->limit) - /* Flush the position information back to the cache */ - cache->freeStart = posn->ptr; - cache->freeEnd = posn->limit; - - /* Update the last method region block and then - add all method regions to the lookup tree */ - method = cache->method; - if(method) ++ /* Determine if we ran out of space while writing the function */ ++ if(result != JIT_CACHE_OK || cache->free_start >= cache->free_end) { - /* If we had a newly allocated page then it has to be freed - to let allocate another new page of appropriate size. */ - if((cache->freeStart == ((unsigned char *)(cache->pages[cache->numPages - 1].page))) - && (cache->freeEnd - == (cache->freeStart + (cache->pageSize * cache->pages[cache->numPages - 1].factor)))) - method->end = posn->ptr; - do -- { - --(cache->numPages); - jit_free_exec(cache->pages[cache->numPages].page, - cache->pageSize * cache->pages[cache->numPages].factor); - if (cache->pagesLeft >= 0) - { - cache->pagesLeft += cache->pages[cache->numPages].factor; - } - cache->freeStart = 0; - cache->freeEnd = 0; - method->debug = cache->firstDebug; - next = method->right; - AddToLookupTree(cache, method); - method = next; -- } - while(method != 0); ++ /* Restore the saved cache position */ ++ cache->free_start = cache->prev_start; ++ cache->free_end = cache->prev_end; + cache->method = 0; + return JIT_CACHE_RESTART; } - /* Flush the position information back to the cache */ - cache->freeStart = posn->ptr; - cache->freeEnd = posn->limit; ++ /* Update the method region block and then add it to the lookup tree */ ++ cache->method->func->code_end = cache->free_start; ++ AddToLookupTree(cache, cache->method); ++ cache->method = 0; ++ + /* The method is ready to go */ + return JIT_CACHE_OK; + } - /* Update the last method region block and then - add all method regions to the lookup tree */ - method = cache->method; - if(method) -void *_jit_cache_alloc(jit_cache_posn *posn, unsigned long size) -{ - unsigned char *ptr; - - /* Bail out if the request is too big to ever be satisfiable */ - if(size > (unsigned long)(posn->limit - posn->ptr)) - { - posn->ptr = posn->limit; - return 0; - } - - /* Allocate memory from the top of the free region, so that it - does not overlap with the method code being written at the - bottom of the free region */ - ptr = (unsigned char *)(((jit_nuint)(posn->limit - size)) & - ~(((jit_nuint)JIT_BEST_ALIGNMENT) - 1)); - if(ptr < posn->ptr) - { - /* When we aligned the block, it caused an overflow */ - posn->ptr = posn->limit; - return 0; - } - - /* Allocate the block and return it */ - posn->limit = ptr; - return (void *)ptr; -} - -void *_jit_cache_alloc_no_method - (jit_cache_t cache, unsigned long size, unsigned long align) ++void * ++_jit_cache_get_code_break(jit_cache_t cache) + { - unsigned char *ptr; - - /* Bail out if the request is too big to ever be satisfiable */ - if(size > (unsigned long)(cache->freeEnd - cache->freeStart)) - { - AllocCachePage(cache, 0); - if(size > (unsigned long)(cache->freeEnd - cache->freeStart)) - { - return 0; - } - } - - /* Allocate memory from the top of the free region, so that it - does not overlap with the method code being written at the - bottom of the free region */ - ptr = (unsigned char *)(((jit_nuint)(cache->freeEnd - size)) & - ~(((jit_nuint)align) - 1)); - if(ptr < cache->freeStart) ++ /* Bail out if there is no started function */ ++ if(!cache->method) { - method->func->end = posn->ptr; - do - { - next = method->right; - AddToLookupTree(cache, method); - method = next; - } - while(method != 0); - cache->method = 0; - /* When we aligned the block, it caused an overflow */ + return 0; } - /* The method is ready to go */ - return JIT_CACHE_OK; - /* Allocate the block and return it */ - cache->freeEnd = ptr; - return (void *)ptr; ++ /* Return the address of the available code area */ ++ return cache->free_start; } - void *_jit_cache_alloc(jit_cache_posn *posn, unsigned long size) -void _jit_cache_align(jit_cache_posn *posn, int align, int diff, int nop) ++void ++_jit_cache_set_code_break(jit_cache_t cache, void *ptr) { - unsigned char *ptr; - jit_nuint current; - jit_nuint next; - - /* Determine the location of the next alignment boundary */ - if(align <= 1) - { - align = 1; - } - current = (jit_nuint)(posn->ptr); - next = (current + ((jit_nuint)align) - 1) & - ~(((jit_nuint)align) - 1); - if(current == next || (next - current) >= (jit_nuint)diff) ++ /* Bail out if there is no started function */ ++ if(!cache->method) + { + return; + } - - /* Detect overflow of the free memory region */ - if(next > ((jit_nuint)(posn->limit))) ++ /* Sanity checks */ ++ if ((unsigned char *) ptr < cache->free_start) + { - posn->ptr = posn->limit; + return; + } - -#ifndef jit_should_pad - /* Fill from "current" to "next" with nop bytes */ - while(current < next) - { - *((posn->ptr)++) = (unsigned char)nop; - ++current; ++ if ((unsigned char *) ptr > cache->free_end) { ++ return; + } -#else - /* Use CPU-specific padding, because it may be more efficient */ - _jit_pad_buffer((unsigned char *)current, (int)(next - current)); -#endif -} - /* Bail out if the request is too big to ever be satisfiable */ - if(size > (unsigned long)(posn->limit - posn->ptr)) -void _jit_cache_mark_bytecode(jit_cache_posn *posn, unsigned long offset) -{ - WriteCacheDebug(posn, (long)offset, - (long)(posn->ptr - posn->cache->start)); ++ /* Update the address of the available code area */ ++ cache->free_start = ptr; + } + -void _jit_cache_set_cookie(jit_cache_posn *posn, void *cookie) ++void * ++_jit_cache_get_code_limit(jit_cache_t cache) + { - if(posn->cache->method) ++ /* Bail out if there is no started function */ ++ if(!cache->method) { - posn->ptr = posn->limit; - posn->cache->method->cookie = cookie; + return 0; } -} - /* Allocate memory from the top of the free region, so that it - does not overlap with the method code being written at the - bottom of the free region */ - ptr = (unsigned char *)(((jit_nuint)(posn->limit - size)) & - ~(((jit_nuint)JIT_BEST_ALIGNMENT) - 1)); - if(ptr < posn->ptr) -void *_jit_cache_get_method(jit_cache_t cache, void *pc, void **cookie) -{ - jit_cache_method_t node = cache->head.right; - while(node != &(cache->nil)) - { - if(((unsigned char *)pc) < node->start) - { - node = GetLeft(node); - } - else if(((unsigned char *)pc) >= node->end) - { - node = GetRight(node); - } - else - { - if(cookie) - { - *cookie = node->cookie; - } - return node->method; - } - } - return 0; ++ /* Return the end address of the available code area */ ++ return cache->free_end; + } + -/* - * Add a parent pointer to a list. Returns null if out of memory. - */ -static int add_parent(jit_cache_method_t *parent_buf, - jit_cache_method_t **parents, - int *num_parents, int *max_parents, - jit_cache_method_t node) ++void * ++_jit_cache_alloc_data(jit_cache_t cache, unsigned long size, unsigned long align) + { - jit_cache_method_t *new_list; - if(*num_parents >= *max_parents) ++ /* Bail out if there is no started function */ ++ if(!cache->method) { - /* When we aligned the block, it caused an overflow */ - posn->ptr = posn->limit; - if(*parents == parent_buf) - { - new_list = (jit_cache_method_t *)jit_malloc - ((*max_parents * 2) * sizeof(jit_cache_method_t)); - if(new_list) - { - jit_memcpy(new_list, *parents, - (*num_parents) * sizeof(jit_cache_method_t)); - } - } - else - { - new_list = (jit_cache_method_t *)jit_realloc - (*parents, (*max_parents * 2) * sizeof(jit_cache_method_t)); - } - if(!new_list) - { - return 0; - } - *parents = new_list; - *max_parents *= 2; + return 0; } - (*parents)[*num_parents] = node; - ++(*num_parents); - return 1; + + /* Allocate the block and return it */ - posn->limit = ptr; - return (void *)ptr; ++ return cache_alloc_data(cache, size, align); } - void *_jit_cache_alloc_no_method - (jit_cache_t cache, unsigned long size, unsigned long align) -void *_jit_cache_get_start_method(jit_cache_t cache, void *pc) ++void * ++_jit_cache_alloc_no_method(jit_cache_t cache, unsigned long size, unsigned long align) { - /* TODO: This function is not currently aware of multiple regions. */ - jit_cache_method_t node = cache->head.right; - while(node != &(cache->nil)) + unsigned char *ptr; + ++ /* Bail out if there is a started function */ ++ if(cache->method) + { - if(((unsigned char *)pc) < node->start) - { - node = GetLeft(node); - } - else if(((unsigned char *)pc) >= node->end) - { - node = GetRight(node); - } - else - { - return node->start; - } ++ return 0; + } - return 0; -} - -void *_jit_cache_get_end_method(jit_cache_t cache, void *pc) -{ - jit_cache_method_t parent_buf[16]; - jit_cache_method_t *parents = parent_buf; - int num_parents = 0; - int max_parents = 16; - jit_cache_method_t node = cache->head.right; - jit_cache_method_t last; - jit_cache_method_t parent; - void *method; - while(node != &(cache->nil)) ++ /* Bail out if there is no cache available */ ++ if(!cache->free_start) + { - if(((unsigned char *)pc) < node->start) - { - if(!add_parent(parent_buf, &parents, &num_parents, - &max_parents, node)) - { - break; - } - node = GetLeft(node); - } - else if(((unsigned char *)pc) >= node->end) - { - if(!add_parent(parent_buf, &parents, &num_parents, - &max_parents, node)) - { - break; - } - node = GetRight(node); - } - else - { - /* This is the node that contains the starting position. - We now need to do an inorder traversal from this point - to find the last node that mentions this method */ - method = node->method; - last = node; - do - { - if(GetRight(node) != &(cache->nil)) - { - /* Move down the left-most sub-tree of the right */ - if(!add_parent(parent_buf, &parents, &num_parents, - &max_parents, node)) - { - goto failed; - } - node = GetRight(node); - while(GetLeft(node) != &(cache->nil)) - { - if(!add_parent(parent_buf, &parents, &num_parents, - &max_parents, node)) - { - goto failed; - } - node = GetLeft(node); - } - } - else - { - /* Find a parent or other ancestor that contains this - node within its left sub-tree */ - for(;;) - { - if(num_parents == 0) - { - node = 0; - break; - } - parent = parents[--num_parents]; - if(GetLeft(parent) == node) - { - /* We are on our parent's left, so next is parent */ - node = parent; - break; - } - node = parent; - } - if(!node) - { - /* We reached the root of the tree */ - break; - } - } - if(node->method == method) - { - last = node; - } - } - while(node->method == method); - if(parents != parent_buf) - { - jit_free(parents); - } - return last->end; - } ++ return 0; + } -failed: - if(parents != parent_buf) + /* Bail out if the request is too big to ever be satisfiable */ - if(size > (unsigned long)(cache->freeEnd - cache->freeStart)) ++ if ((size + align - 1) > (cache->pageSize * cache->maxPageFactor)) { - AllocCachePage(cache, 0); - if(size > (unsigned long)(cache->freeEnd - cache->freeStart)) - jit_free(parents); ++ return 0; + } - return 0; -} - -/* - * Temporary structure for iterating over a method's debug list. - */ -typedef struct -{ - jit_cache_debug_t list; - UncompressReader reader; + -} jit_cache_debug_iter; ++ /* Allocate memory from the top of the current free region, so ++ * that it does not overlap with the method code being written ++ * at the bottom of the free region */ ++ ptr = cache->free_end - size; ++ ptr = (unsigned char *) (((jit_nuint) ptr) & ~((jit_nuint) align - 1)); + -/* - * Initialize a debug information list iterator for a method. - */ -static void InitDebugIter(jit_cache_debug_iter *iter, - jit_cache_t cache, void *start) -{ - jit_cache_method_t node = cache->head.right; - while(node != &(cache->nil)) ++ /* Do we need to allocate a new cache page? */ ++ if(ptr < cache->free_start) + { - if(((unsigned char *)start) < node->start) - { - node = GetLeft(node); ++ /* Find the appropriate page size */ ++ int factor = 1; ++ while((size + align - 1) > (factor * cache->pageSize)) { ++ factor <<= 1; + } - else if(((unsigned char *)start) >= node->end) - { - node = GetRight(node); - } - else - { - iter->list = node->debug; - if(iter->list) - { - iter->reader.data = (unsigned char *)(iter->list + 1); - iter->reader.len = JIT_CACHE_DEBUG_SIZE; - iter->reader.error = 0; - } - return; - } - } - iter->list = 0; -} + -/* - * Get the next debug offset pair from a debug information list. - * Returns non-zero if OK, or zero at the end of the list. - */ -static int GetNextDebug(jit_cache_debug_iter *iter, unsigned long *offset, - unsigned long *nativeOffset) -{ - long value; - while(iter->list) - { - value = UncompressInt(&(iter->reader)); - if(value == -1) ++ /* Try to allocate it */ ++ AllocCachePage(cache, factor); ++ ++ /* Bail out if the cache is full */ ++ if(!cache->free_start) { return 0; } - } - else if(value != -2) - { - *offset = (unsigned long)value; - *nativeOffset = (unsigned long)(UncompressInt(&(iter->reader))); - return 1; - } - iter->list = iter->list->next; - if(iter->list) - { - iter->reader.data = (unsigned char *)(iter->list + 1); - iter->reader.len = JIT_CACHE_DEBUG_SIZE; - iter->reader.error = 0; - } + - /* Allocate memory from the top of the free region, so that it - does not overlap with the method code being written at the - bottom of the free region */ - ptr = (unsigned char *)(((jit_nuint)(cache->freeEnd - size)) & - ~(((jit_nuint)align) - 1)); - if(ptr < cache->freeStart) - { - /* When we aligned the block, it caused an overflow */ - return 0; ++ /* Allocate memory from the new page */ ++ ptr = cache->free_end - size; ++ ptr = (unsigned char *) (((jit_nuint) ptr) & ~((jit_nuint) align - 1)); } - - return 0; ++ + /* Allocate the block and return it */ - cache->freeEnd = ptr; ++ cache->free_end = ptr; + return (void *)ptr; } -unsigned long _jit_cache_get_native(jit_cache_t cache, void *start, - unsigned long offset, int exact) +jit_function_t +_jit_cache_get_method(jit_cache_t cache, void *pc) { - jit_cache_debug_iter iter; - unsigned long ofs, nativeOfs; - unsigned long prevNativeOfs = JIT_CACHE_NO_OFFSET; - - /* Search for the bytecode offset */ - InitDebugIter(&iter, cache, start); - while(GetNextDebug(&iter, &ofs, &nativeOfs)) + jit_cache_method_t node = cache->head.right; + while(node != &(cache->nil)) { - if(((unsigned char *)pc) < node->func->start) - if(exact) ++ if(((unsigned char *)pc) < node->func->code_start) { - if(ofs == offset) - { - return nativeOfs; - } + node = GetLeft(node); } - else if(((unsigned char *)pc) >= node->func->end) - else if(ofs > offset) ++ else if(((unsigned char *)pc) >= node->func->code_end) { - return prevNativeOfs; - } - prevNativeOfs = nativeOfs; - } - - return exact ? JIT_CACHE_NO_OFFSET : prevNativeOfs; -} - -unsigned long _jit_cache_get_bytecode(jit_cache_t cache, void *start, - unsigned long offset, int exact) -{ - jit_cache_debug_iter iter; - unsigned long ofs, nativeOfs; - unsigned long prevOfs = JIT_CACHE_NO_OFFSET; - - /* Search for the native offset */ - InitDebugIter(&iter, cache, start); - while(GetNextDebug(&iter, &ofs, &nativeOfs)) - { - if(exact) - { - if(nativeOfs == offset) - { - return ofs; - } + node = GetRight(node); } - else if(nativeOfs > offset) + else { - return prevOfs; + return node->func; } - prevOfs = ofs; } - - return exact ? JIT_CACHE_NO_OFFSET : prevOfs; -} - -unsigned long _jit_cache_get_size(jit_cache_t cache) -{ - return (cache->numPages * cache->pageSize) - - (cache->freeEnd - cache->freeStart); + return 0; } /* diff --cc jit/jit-cache.h index 3cfa557,ea04bee..8c853c2 --- a/jit/jit-cache.h +++ b/jit/jit-cache.h @@@ -28,20 -28,20 +28,12 @@@ extern "C" #endif /* -- * Opaque method cache type. ++ * Result values for "_jit_cache_start_function" and "_jit_cache_end_function". */ --typedef struct jit_cache *jit_cache_t; -- --/* -- * Writing position within a cache. -- */ --typedef struct --{ -- jit_cache_t cache; /* Cache this position is attached to */ -- unsigned char *ptr; /* Current code pointer */ -- unsigned char *limit; /* Limit of the current page */ -- --} jit_cache_posn; ++#define JIT_CACHE_OK 0 /* Function is OK */ ++#define JIT_CACHE_RESTART 1 /* Restart is required */ ++#define JIT_CACHE_TOO_BIG 2 /* Function is too big for the cache */ ++#define JIT_CACHE_ERROR 3 /* Other error */ /* * Create a method cache. Returns NULL if out of memory. @@@ -62,54 -62,54 +54,45 @@@ jit_cache_t _jit_cache_create(long limi void _jit_cache_destroy(jit_cache_t cache); /* -- * Determine if the cache is full. The "posn" value should -- * be supplied while translating a method, or be NULL otherwise. ++ * Start output of a function. The "restart_count" value should be ++ * equal to zero unless the method is being recompiled because it did ++ * not fit last time into the memory. In the later case the value ++ * should gradually increase until either the methods fits or the ++ * maximum restart_count value is exceeded. */ --int _jit_cache_is_full(jit_cache_t cache, jit_cache_posn *posn); ++int _jit_cache_start_function(jit_cache_t cache, ++ jit_function_t func, ++ int restart_count); /* -- * Determine if there is sufficient space in the code cache. -- * If not throws JIT_RESULT_CACHE_FULL exception. ++ * End output of a function. Returns zero if a restart is needed. */ --void _jit_cache_check_space(jit_cache_posn *posn, int space); ++int _jit_cache_end_function(jit_cache_t cache, int result); /* -- * Return values for "_jit_cache_start_method" and "_jit_cache_end_method". ++ * Get the boundary between used and free code space. */ --#define JIT_CACHE_OK 0 /* Function is OK */ --#define JIT_CACHE_RESTART 1 /* Restart is required */ --#define JIT_CACHE_TOO_BIG 2 /* Function is too big for the cache */ ++void *_jit_cache_get_code_break(jit_cache_t cache); /* -- * Start output of a method, returning a cache position. -- * The "page_factor" value should be equal to zero unless -- * the method is being recompiled because it did not fit -- * into the current page. In the later case the value -- * should gradually increase until either the methods fits -- * or the maximum page factor value is exceeded. -- * The "align" value indicates the default alignment for -- * the start of the method. The "cookie" value is a -- * cookie for referring to the method. Returns the -- * method entry point, or NULL if the cache is full. ++ * Set the boundary between used and free code space. */ --int _jit_cache_start_method(jit_cache_t cache, -- jit_cache_posn *posn, -- int page_factor, -- int align, - jit_function_t func); - void *cookie); ++void _jit_cache_set_code_break(jit_cache_t cache, void *ptr); /* -- * End output of a method. Returns zero if a restart. ++ * Get the end address of the free code space. */ - int _jit_cache_end_method(jit_cache_posn *posn, int result); -int _jit_cache_end_method(jit_cache_posn *posn); ++void *_jit_cache_get_code_limit(jit_cache_t cache); /* -- * Allocate "size" bytes of storage in the method cache's -- * auxillary data area. Returns NULL if insufficient space ++ * Allocate "size" bytes of storage in the function cache's ++ * auxiliary data area. Returns NULL if insufficient space * to satisfy the request. It may be possible to satisfy * the request after a restart. */ --void *_jit_cache_alloc(jit_cache_posn *posn, unsigned long size); ++void *_jit_cache_alloc_data(jit_cache_t cache, ++ unsigned long size, ++ unsigned long align); /* * Allocate "size" bytes of storage when we aren't currently diff --cc jit/jit-compile.c index 3a4d3b2,9246172..6eb610d --- a/jit/jit-compile.c +++ b/jit/jit-compile.c @@@ -37,7 -37,7 +37,6 @@@ typedef struc { jit_function_t func; -- jit_cache_t cache; int cache_locked; int cache_started; @@@ -152,23 -152,6 +151,23 @@@ jit_optimize(jit_function_t func return JIT_RESULT_OK; } +/* + * Mark the current position with a bytecode offset value. + */ +void +mark_offset(jit_gencode_t gen, jit_function_t func, unsigned long offset) +{ - unsigned long native_offset = gen->posn.ptr - func->start; ++ unsigned long native_offset = gen->ptr - func->code_start; + if(!_jit_varint_encode_uint(&gen->offset_encoder, (jit_uint) offset)) + { + jit_exception_builtin(JIT_RESULT_OUT_OF_MEMORY); + } + if(!_jit_varint_encode_uint(&gen->offset_encoder, (jit_uint) native_offset)) + { + jit_exception_builtin(JIT_RESULT_OUT_OF_MEMORY); + } +} + /* * Compile a single basic block within a function. */ @@@ -188,7 -171,7 +187,7 @@@ compile_block(jit_gencode_t gen, jit_fu { #ifdef _JIT_COMPILE_DEBUG unsigned char *p1, *p2; -- p1 = gen->posn.ptr; ++ p1 = gen->ptr; printf("Insn #%d: ", func->builder->insn_count++); jit_dump_insn(stdout, func, insn); printf("\nStart of binary code: 0x%08x\n", p1); @@@ -296,7 -281,7 +295,7 @@@ } #ifdef _JIT_COMPILE_DEBUG -- p2 = gen->posn.ptr; ++ p2 = gen->ptr; printf("Length of binary code: %d\n\n", p2 - p1); fflush(stdout); #endif @@@ -394,8 -379,8 +393,8 @@@ cache_acquire(_jit_compile_t *state state->cache_locked = 1; /* Get the method cache */ -- state->cache = _jit_context_get_cache(state->func->context); -- if(!state->cache) ++ state->gen.cache = _jit_context_get_cache(state->func->context); ++ if(!state->gen.cache) { jit_exception_builtin(JIT_RESULT_OUT_OF_MEMORY); } @@@ -415,89 -400,38 +414,82 @@@ cache_release(_jit_compile_t *state } } +/* - * Allocate some space in the code cache. ++ * Align the method code on a particular boundary if the ++ * difference between the current position and the aligned ++ * boundary is less than "diff". The "nop" value is used ++ * to pad unused bytes. + */ +static void - cache_alloc(_jit_compile_t *state) ++cache_align(_jit_compile_t *state, int align, int diff, int nop) +{ - int result; ++ jit_nuint p, n; + - /* First try with the current cache page */ - result = _jit_cache_start_method(state->cache, - &state->gen.posn, - state->page_factor++, - JIT_FUNCTION_ALIGNMENT, - state->func); - if(result == JIT_CACHE_RESTART) ++ /* Adjust the required alignment */ ++ if(align < 1) + { - /* No space left on the current cache page. Allocate a new one. */ - result = _jit_cache_start_method(state->cache, - &state->gen.posn, - state->page_factor++, - JIT_FUNCTION_ALIGNMENT, - state->func); ++ align = 1; + } - if(result != JIT_CACHE_OK) ++ ++ /* Determine the location of the next alignment boundary */ ++ p = (jit_nuint) state->gen.ptr; ++ n = (p + (jit_nuint) align - 1) & ~((jit_nuint) align - 1); ++ if(p == n || (p - n) >= (jit_nuint) diff) + { - /* Failed to allocate any cache space */ - jit_exception_builtin(JIT_RESULT_OUT_OF_MEMORY); ++ return; + } + - /* Prepare the bytecode offset encoder */ - _jit_varint_init_encoder(&state->gen.offset_encoder); ++ /* Determine the actual alignment */ ++ align = (int) (n - p); + - /* On success remember the cache state */ - state->cache_started = 1; ++ /* Detect overflow of the free memory region */ ++ _jit_gen_check_space(&state->gen, align); ++ ++#ifdef jit_should_pad ++ /* Use CPU-specific padding, because it may be more efficient */ ++ _jit_pad_buffer(state->gen.ptr, align); ++#else ++ jit_memset(state->gen.ptr, nop, align); ++ state->gen.ptr += align; ++#endif +} + - #if NOT_USED /* - * Align the method code on a particular boundary if the - * difference between the current position and the aligned - * boundary is less than "diff". The "nop" value is used - * to pad unused bytes. + * Allocate some space in the code cache. */ static void - cache_align(jit_cache_posn *posn, int align, int diff, int nop) + cache_alloc(_jit_compile_t *state) { - jit_nuint current; - jit_nuint next; + int result; - /* Determine the location of the next alignment boundary */ - if(align <= 1) + /* First try with the current cache page */ - result = _jit_cache_start_method(state->cache, - &state->gen.posn, - state->page_factor++, - JIT_FUNCTION_ALIGNMENT, - state->func); ++ result = _jit_cache_start_function(state->gen.cache, ++ state->func, ++ state->page_factor++); + if(result == JIT_CACHE_RESTART) { - align = 1; + /* No space left on the current cache page. Allocate a new one. */ - result = _jit_cache_start_method(state->cache, - &state->gen.posn, - state->page_factor++, - JIT_FUNCTION_ALIGNMENT, - state->func); ++ result = _jit_cache_start_function(state->gen.cache, ++ state->func, ++ state->page_factor++); } - current = (jit_nuint)(posn->ptr); - next = (current + ((jit_nuint)align) - 1) & - ~(((jit_nuint)align) - 1); - if(current == next || (next - current) >= (jit_nuint)diff) + if(result != JIT_CACHE_OK) { - return; + /* Failed to allocate any cache space */ + jit_exception_builtin(JIT_RESULT_OUT_OF_MEMORY); } ++ state->gen.ptr = _jit_cache_get_code_break(state->gen.cache); ++ state->gen.limit = _jit_cache_get_code_limit(state->gen.cache); + - /* Detect overflow of the free memory region */ - if(next > ((jit_nuint)(posn->limit))) - { - posn->ptr = posn->limit; - return; - } ++ /* Align the function code. */ ++ cache_align(state, JIT_FUNCTION_ALIGNMENT, JIT_FUNCTION_ALIGNMENT, 0); + - #ifndef jit_should_pad - /* Fill from "current" to "next" with nop bytes */ - while(current < next) - { - *((posn->ptr)++) = (unsigned char)nop; - ++current; - } - #else - /* Use CPU-specific padding, because it may be more efficient */ - _jit_pad_buffer((unsigned char *)current, (int)(next - current)); - #endif - } - #endif ++ /* Prepare the bytecode offset encoder */ ++ _jit_varint_init_encoder(&state->gen.offset_encoder); + /* On success remember the cache state */ + state->cache_started = 1; + } /* * End function output to the cache. @@@ -511,8 -445,8 +503,11 @@@ cache_flush(_jit_compile_t *state { state->cache_started = 0; ++ /* Let the cache know where we are */ ++ _jit_cache_set_code_break(state->gen.cache, state->gen.ptr); ++ /* End the function's output process */ - result = _jit_cache_end_method(&state->gen.posn, JIT_CACHE_OK); - result = _jit_cache_end_method(&state->gen.posn); ++ result = _jit_cache_end_function(state->gen.cache, JIT_CACHE_OK); if(result != JIT_CACHE_OK) { if(result == JIT_CACHE_RESTART) @@@ -555,11 -482,13 +550,11 @@@ cache_abort(_jit_compile_t *state { state->cache_started = 0; - /* Make sure that the _jit_cache_end_method() call below will - release the currently held cache space rather than make it - allocated permanently */ - jit_cache_mark_full(&state->gen.posn); + /* Release the cache space */ - _jit_cache_end_method(&state->gen.posn, JIT_CACHE_RESTART); ++ _jit_cache_end_function(state->gen.cache, JIT_CACHE_RESTART); - /* Actually release the cache space */ - _jit_cache_end_method(&state->gen.posn); + /* Free encoded bytecode offset data */ + _jit_varint_free_data(_jit_varint_get_data(&state->gen.offset_encoder)); } } @@@ -576,21 -505,18 +571,22 @@@ cache_realloc(_jit_compile_t *state /* Allocate a new cache page with the size that grows by factor of 2 on each reallocation */ -- result = _jit_cache_start_method(state->cache, -- &state->gen.posn, -- state->page_factor, -- JIT_FUNCTION_ALIGNMENT, -- state->func); ++ result = _jit_cache_start_function(state->gen.cache, ++ state->func, ++ state->page_factor++); if(result != JIT_CACHE_OK) { /* Failed to allocate enough cache space */ jit_exception_builtin(JIT_RESULT_OUT_OF_MEMORY); } ++ state->gen.ptr = _jit_cache_get_code_break(state->gen.cache); ++ state->gen.limit = _jit_cache_get_code_limit(state->gen.cache); + - state->page_factor *= 2; ++ /* Align the function code. */ ++ cache_align(state, JIT_FUNCTION_ALIGNMENT, JIT_FUNCTION_ALIGNMENT, 0); - state->page_factor *= 2; + /* Prepare the bytecode offset encoder */ + _jit_varint_init_encoder(&state->gen.offset_encoder); /* On success remember the cache state */ state->cache_started = 1; @@@ -631,12 -557,12 +627,12 @@@ codegen(_jit_compile_t *state struct jit_gencode *gen = &state->gen; jit_block_t block; -- state->code_start = gen->posn.ptr; ++ state->code_start = gen->ptr; #ifdef JIT_PROLOG_SIZE /* Output space for the function prolog */ -- _jit_cache_check_space(&gen->posn, JIT_PROLOG_SIZE); -- gen->posn.ptr += JIT_PROLOG_SIZE; ++ _jit_gen_check_space(gen, JIT_PROLOG_SIZE); ++ gen->ptr += JIT_PROLOG_SIZE; #endif /* Generate code for the blocks in the function */ @@@ -661,18 -587,18 +657,11 @@@ /* Notify the back end that the block is finished */ _jit_gen_end_block(gen, block); -- -- /* Stop code generation if the cache page is full */ -- if(_jit_cache_is_full(state->cache, &gen->posn)) -- { -- /* No space left on the current cache page. Restart. */ -- jit_exception_builtin(JIT_RESULT_CACHE_FULL); -- } } /* Output the function epilog. All return paths will jump to here */ _jit_gen_epilog(gen, func); -- state->code_end = gen->posn.ptr; ++ state->code_end = gen->ptr; #ifdef JIT_PROLOG_SIZE /* Back-patch the function prolog and get the real entry point */ @@@ -1024,56 -950,3 +1013,56 @@@ _jit_function_compile_on_demand(jit_fun return func->entry_point; } + +#define JIT_CACHE_NO_OFFSET (~((unsigned long)0)) + +unsigned long +_jit_function_get_bytecode(jit_function_t func, void *pc, int exact) +{ + unsigned long offset = JIT_CACHE_NO_OFFSET; + jit_cache_t cache; + void *start; + unsigned long native_offset; + jit_varint_decoder_t decoder; + jit_uint off, noff; + + cache = _jit_context_get_cache(func->context); + +#ifdef JIT_PROLOG_SIZE - start = func->start; ++ start = func->code_start; +#else + start = func->entry_point; +#endif + + native_offset = pc - start; + + _jit_varint_init_decoder(&decoder, func->bytecode_offset); + for(;;) + { + off = _jit_varint_decode_uint(&decoder); + noff = _jit_varint_decode_uint(&decoder); + if(_jit_varint_decode_end(&decoder)) + { + if(exact) + { + offset = JIT_CACHE_NO_OFFSET; + } + break; + } + if(noff >= native_offset) + { + if(noff == native_offset) + { + offset = off; + } + else if (exact) + { + offset = JIT_CACHE_NO_OFFSET; + } + break; + } + offset = off; + } + + return offset; +} diff --cc jit/jit-dump.c index 5e9cb0a,de6ac29..c3a87f1 --- a/jit/jit-dump.c +++ b/jit/jit-dump.c @@@ -895,9 -897,9 +895,9 @@@ void jit_dump_function(FILE *stream, ji (long)(jit_nint)interp, (long)(jit_nint)func, (int)(interp->args_size), (int)(interp->frame_size), (int)(interp->working_area)); - dump_interp_code(stream, (void **)(interp + 1), (void **)func->end); - dump_interp_code(stream, (void **)(interp + 1), (void **)end); ++ dump_interp_code(stream, (void **)(interp + 1), (void **)func->code_end); #else - dump_object_code(stream, func->entry_point, func->end); - dump_object_code(stream, func->entry_point, end); ++ dump_object_code(stream, func->entry_point, func->code_end); #endif } diff --cc jit/jit-internal.h index b6cb2bb,911348e..da59e4c --- a/jit/jit-internal.h +++ b/jit/jit-internal.h @@@ -108,6 -103,6 +108,11 @@@ _JIT_ALIGN_CHECK_TYPE(jit_nfloat, nfloa #define JIT_ALIGN_NFLOAT _JIT_ALIGN_FOR_TYPE(nfloat) #define JIT_ALIGN_PTR _JIT_ALIGN_FOR_TYPE(ptr) ++/* ++ * Opaque function cache type. ++ */ ++typedef struct jit_cache *jit_cache_t; ++ /* * Structure of a memory pool. */ @@@ -454,11 -443,6 +459,11 @@@ struct _jit_functio /* Flag set once the function is compiled */ int volatile is_compiled; + /* Start of the cache region */ - unsigned char *start; ++ unsigned char *code_start; + /* End of the cache region */ - unsigned char *end; ++ unsigned char *code_end; + /* The entry point for the function's compiled code */ void * volatile entry_point; diff --cc jit/jit-reg-alloc.c index b6a8cdf,b6a8cdf..41ae7dd --- a/jit/jit-reg-alloc.c +++ b/jit/jit-reg-alloc.c @@@ -3776,5 -3776,5 +3776,5 @@@ _jit_regs_begin(jit_gencode_t gen, _jit { _jit_regs_assign(gen, regs); _jit_regs_gen(gen, regs); -- _jit_cache_check_space(&gen->posn, space); ++ _jit_gen_check_space(gen, space); } diff --cc jit/jit-rules-alpha.c index 2836c4a,2836c4a..edd1e7c --- a/jit/jit-rules-alpha.c +++ b/jit/jit-rules-alpha.c @@@ -79,23 -79,23 +79,23 @@@ int _alpha_has_ieeefp() * Setup or teardown the alpha code output process. */ #define jit_cache_setup_output(needed) \ -- alpha_inst inst = (alpha_inst) gen->posn.ptr; \ -- _jit_cache_check_space(&gen->posn, (needed)) ++ alpha_inst inst = (alpha_inst) gen->ptr; \ ++ _jit_gen_check_space(gen, (needed)) #define jit_cache_end_output() \ -- gen->posn.ptr = (unsigned char*) inst ++ gen->ptr = (unsigned char*) inst /* * Load the instruction pointer from the generation context. */ #define jit_gen_load_inst_ptr(gen,inst) \ -- inst = (alpha_inst) (gen)->posn.ptr; ++ inst = (alpha_inst) (gen)->ptr; /* * Save the instruction pointer back to the generation context. */ #define jit_gen_save_inst_ptr(gen,inst) \ -- (gen)->posn.ptr = (unsigned char *) inst; ++ (gen)->ptr = (unsigned char *) inst; static _jit_regclass_t *alpha_reg; static _jit_regclass_t *alpha_freg; @@@ -401,7 -401,7 +401,7 @@@ void _jit_gen_start_block(jit_gencode_ void **fixup, **next; /* Set the address of this block */ -- block->address = (void *)(gen->posn.ptr); ++ block->address = (void *)(gen->ptr); /* If this block has pending fixups, then apply them now */ fixup = (void **)(block->fixup_list); @@@ -410,7 -410,7 +410,7 @@@ alpha_inst code = (alpha_inst) fixup; next = (void **)(fixup[0]); -- _alpha_li64(code,ALPHA_AT,(long int)(gen->posn.ptr)); ++ _alpha_li64(code,ALPHA_AT,(long int)(gen->ptr)); alpha_jmp(code,ALPHA_ZERO,ALPHA_AT,1); fixup = next; @@@ -528,12 -528,12 +528,12 @@@ void _jit_gen_load_global(jit_gencode_ */ void *_jit_gen_redirector(jit_gencode_t gen, jit_function_t func) { void *ptr, *entry; -- alpha_inst inst = (alpha_inst) gen->posn.ptr; ++ alpha_inst inst = (alpha_inst) gen->ptr; -- _jit_cache_check_space(&gen->posn, 8*6); ++ _jit_gen_check_space(gen, 8*6); ptr = (void *)&(func->entry_point); -- entry = gen->posn.ptr; ++ entry = gen->ptr; alpha_call(inst, ptr); @@@ -626,7 -626,7 +626,7 @@@ void jump_to_epilog(jit_gencode_t gen, _jit_pad_buffer((unsigned char*)inst,6); /* to be overwritten later with jmp */ -- (gen)->posn.ptr = (unsigned char*) inst; ++ (gen)->ptr = (unsigned char*) inst; } #endif /* JIT_BACKEND_ALPHA */ diff --cc jit/jit-rules-arm.c index cfe3930,cfe3930..21e12c5 --- a/jit/jit-rules-arm.c +++ b/jit/jit-rules-arm.c @@@ -130,7 -130,7 +130,7 @@@ static _jit_regclass_t *arm_lreg */ #define jit_gen_load_inst_ptr(gen,inst) \ do { \ -- arm_inst_buf_init((inst), (gen)->posn.ptr, (gen)->posn.limit); \ ++ arm_inst_buf_init((inst), (gen)->ptr, (gen)->limit); \ } while (0) /* @@@ -138,7 -138,7 +138,7 @@@ */ #define jit_gen_save_inst_ptr(gen,inst) \ do { \ -- (gen)->posn.ptr = (unsigned char *)arm_inst_get_posn(inst); \ ++ (gen)->ptr = (unsigned char *)arm_inst_get_posn(inst); \ } while (0) /* @@@ -341,7 -341,7 +341,7 @@@ static void flush_constants(jit_gencode static int flush_if_too_far(jit_gencode_t gen) { if(gen->first_constant_use && -- (((arm_inst_word *)(gen->posn.ptr)) - ++ (((arm_inst_word *)(gen->ptr)) - ((arm_inst_word *)(gen->first_constant_use))) >= 100) { flush_constants(gen, 0); @@@ -361,7 -361,7 +361,7 @@@ static void add_constant_fixu { arm_inst_word *prev; int value; -- if(((unsigned char *)fixup) >= gen->posn.limit) ++ if(((unsigned char *)fixup) >= gen->limit) { /* The instruction buffer is full, so don't record this fixup */ return; @@@ -902,7 -902,7 +902,7 @@@ void *_jit_gen_redirector(jit_gencode_ arm_inst_buf inst; jit_gen_load_inst_ptr(gen, inst); ptr = (void *)&(func->entry_point); -- entry = gen->posn.ptr; ++ entry = gen->ptr; arm_load_membase(inst, ARM_WORK, ARM_PC, 0); arm_load_membase(inst, ARM_PC, ARM_WORK, 0); arm_inst_add(inst, (unsigned int)ptr); @@@ -1455,7 -1455,7 +1455,7 @@@ void _jit_gen_start_block(jit_gencode_ arm_inst_buf inst; /* Set the address of this block */ -- block->address = (void *)(gen->posn.ptr); ++ block->address = (void *)(gen->ptr); /* If this block has pending fixups, then apply them now */ fixup = (void **)(block->fixup_list); diff --cc jit/jit-rules-arm.ins index 1590dde,1590dde..b5a866a --- a/jit/jit-rules-arm.ins +++ b/jit/jit-rules-arm.ins @@@ -1758,7 -1758,7 +1758,7 @@@ JIT_OP_STORE_RELATIVE_STRUCT: manua _jit_regs_spill_all(gen); _jit_gen_fix_value(insn->value1); jit_gen_load_inst_ptr(gen, inst); -- _jit_cache_check_space(&gen->posn, 128); ++ _jit_gen_check_space(gen, 128); reg = _jit_reg_info[reg].cpu_reg; inst = memory_copy(gen, inst, reg, (int)(insn->value2->address), ARM_FP, insn->value1->frame_offset, diff --cc jit/jit-rules-interp.c index 33d5679,7cccde3..c3714d0 --- a/jit/jit-rules-interp.c +++ b/jit/jit-rules-interp.c @@@ -184,32 -184,22 +184,32 @@@ generation is complete @*/ +/* + * Output a native word to the current method. + */ - #define jit_cache_native(posn,value) \ ++#define jit_cache_native(gen,value) \ + do { \ - _jit_cache_check_space((posn), sizeof(jit_nuint)); \ - *((jit_nuint *)((posn)->ptr)) = (jit_nuint)(value); \ - (posn)->ptr += sizeof(jit_nuint); \ ++ _jit_gen_check_space((gen), sizeof(jit_nuint)); \ ++ *((jit_nuint *)((gen)->ptr)) = (jit_nuint)(value); \ ++ (gen)->ptr += sizeof(jit_nuint); \ + } while (0) + /* * Write an interpreter opcode to the cache. */ --#define jit_cache_opcode(posn,opcode) \ -- jit_cache_native((posn), (jit_nint)(opcode)) ++#define jit_cache_opcode(gen,opcode) \ ++ jit_cache_native((gen), (jit_nint)(opcode)) /* * Write "n" bytes to the cache, rounded up to a multiple of "void *". */ --#define jit_cache_add_n(posn,buf,size) \ ++#define jit_cache_add_n(gen,buf,size) \ do { \ unsigned int __size = \ ((size) + sizeof(void *) - 1) & ~(sizeof(void *) - 1); \ -- _jit_cache_check_space((posn), __size); \ -- jit_memcpy((posn)->ptr, (buf), (size)); \ -- (posn)->ptr += __size; \ ++ _jit_gen_check_space((gen), __size); \ ++ jit_memcpy((gen)->ptr, (buf), (size)); \ ++ (gen)->ptr += __size; \ } while (0) /* @@@ -910,8 -900,8 +910,8 @@@ load_value(jit_gencode_t gen, jit_value case JIT_TYPE_USHORT: case JIT_TYPE_INT: case JIT_TYPE_UINT: -- jit_cache_opcode(&(gen->posn), JIT_INTERP_OP_LDC_0_INT + index); -- jit_cache_native(&(gen->posn), (jit_nint)(value->address)); ++ jit_cache_opcode(gen, JIT_INTERP_OP_LDC_0_INT + index); ++ jit_cache_native(gen, (jit_nint)(value->address)); break; case JIT_TYPE_LONG: @@@ -919,11 -909,11 +919,11 @@@ { jit_long long_value; long_value = jit_value_get_long_constant(value); -- jit_cache_opcode(&(gen->posn), JIT_INTERP_OP_LDC_0_LONG + index); ++ jit_cache_opcode(gen, JIT_INTERP_OP_LDC_0_LONG + index); #ifdef JIT_NATIVE_INT64 -- jit_cache_native(&(gen->posn), long_value); ++ jit_cache_native(gen, long_value); #else -- jit_cache_add_n(&(gen->posn), &long_value, sizeof(long_value)); ++ jit_cache_add_n(gen, &long_value, sizeof(long_value)); #endif break; } @@@ -932,8 -922,8 +932,8 @@@ { jit_float32 float32_value; float32_value = jit_value_get_float32_constant(value); -- jit_cache_opcode(&(gen->posn), JIT_INTERP_OP_LDC_0_FLOAT32 + index); -- jit_cache_add_n(&(gen->posn), &float32_value, sizeof(float32_value)); ++ jit_cache_opcode(gen, JIT_INTERP_OP_LDC_0_FLOAT32 + index); ++ jit_cache_add_n(gen, &float32_value, sizeof(float32_value)); break; } @@@ -941,8 -931,8 +941,8 @@@ { jit_float64 float64_value; float64_value = jit_value_get_float64_constant(value); -- jit_cache_opcode(&(gen->posn), JIT_INTERP_OP_LDC_0_FLOAT64 + index); -- jit_cache_add_n (&(gen->posn), &float64_value, sizeof(float64_value)); ++ jit_cache_opcode(gen, JIT_INTERP_OP_LDC_0_FLOAT64 + index); ++ jit_cache_add_n (gen, &float64_value, sizeof(float64_value)); break; } @@@ -950,8 -940,8 +950,8 @@@ { jit_nfloat nfloat_value; nfloat_value = jit_value_get_nfloat_constant(value); -- jit_cache_opcode(&(gen->posn), JIT_INTERP_OP_LDC_0_NFLOAT + index); -- jit_cache_add_n (&(gen->posn), &nfloat_value, sizeof(nfloat_value)); ++ jit_cache_opcode(gen, JIT_INTERP_OP_LDC_0_NFLOAT + index); ++ jit_cache_add_n (gen, &nfloat_value, sizeof(nfloat_value)); break; } } @@@ -1003,8 -993,8 +1003,8 @@@ offset = -(value->frame_offset + 1); } -- jit_cache_opcode(&(gen->posn), opcode); -- jit_cache_native(&(gen->posn), offset); ++ jit_cache_opcode(gen, opcode); ++ jit_cache_native(gen, offset); } } @@@ -1028,8 -1018,8 +1028,8 @@@ store_value(jit_gencode_t gen, jit_valu opcode = _jit_store_opcode(JIT_INTERP_OP_STA_0_BYTE, 0, value->type); offset = -(offset + 1); } -- jit_cache_opcode(&(gen->posn), opcode); -- jit_cache_native(&(gen->posn), offset); ++ jit_cache_opcode(gen, opcode); ++ jit_cache_native(gen, offset); } /*@ @@@ -1117,8 -1107,8 +1117,8 @@@ void _jit_gen_insn(jit_gencode_t gen, j /* Unconditional branch */ branch: label = (jit_label_t)(insn->dest); -- pc = (void **)(gen->posn.ptr); -- jit_cache_opcode(&(gen->posn), insn->opcode); ++ pc = (void **)(gen->ptr); ++ jit_cache_opcode(gen, insn->opcode); block = jit_block_from_label(func, label); if(!block) { @@@ -1127,12 -1117,12 +1127,12 @@@ if(block->address) { /* We already know the address of the block */ -- jit_cache_native(&(gen->posn), ((void **)(block->address)) - pc); ++ jit_cache_native(gen, ((void **)(block->address)) - pc); } else { /* Record this position on the block's fixup list */ -- jit_cache_native(&(gen->posn), block->fixup_list); ++ jit_cache_native(gen, block->fixup_list); block->fixup_list = (void *)pc; } break; @@@ -1154,8 -1144,8 +1154,8 @@@ labels = (jit_label_t *) insn->value1->address; num_labels = insn->value2->address; -- jit_cache_opcode(&(gen->posn), insn->opcode); -- jit_cache_native(&(gen->posn), num_labels); ++ jit_cache_opcode(gen, insn->opcode); ++ jit_cache_native(gen, num_labels); for(index = 0; index < num_labels; index++) { block = jit_block_from_label(func, labels[index]); @@@ -1166,13 -1156,13 +1166,13 @@@ if(block->address) { /* We already know the address of the block */ -- jit_cache_native(&(gen->posn), block->address); ++ jit_cache_native(gen, block->address); } else { /* Record this position on the block's fixup list */ -- pc = (void **)(gen->posn.ptr); -- jit_cache_native(&(gen->posn), block->fixup_absolute_list); ++ pc = (void **)(gen->ptr); ++ jit_cache_native(gen, block->fixup_absolute_list); block->fixup_absolute_list = pc; } } @@@ -1187,17 -1177,17 +1187,17 @@@ { break; } -- pc = (void **)(gen->posn.ptr); -- jit_cache_opcode(&(gen->posn), insn->opcode); ++ pc = (void **)(gen->ptr); ++ jit_cache_opcode(gen, insn->opcode); if(block->address) { /* We already know the address of the block */ -- jit_cache_native(&(gen->posn), ((void **)(block->address)) - pc); ++ jit_cache_native(gen, ((void **)(block->address)) - pc); } else { /* Record this position on the block's fixup list */ -- jit_cache_native(&(gen->posn), block->fixup_list); ++ jit_cache_native(gen, block->fixup_list); block->fixup_list = (void *)pc; } store_value(gen, insn->dest); @@@ -1206,17 -1196,17 +1206,17 @@@ case JIT_OP_CALL: case JIT_OP_CALL_TAIL: /* Call a function, whose pointer is supplied explicitly */ -- jit_cache_opcode(&(gen->posn), insn->opcode); -- jit_cache_native(&(gen->posn), (jit_nint)(insn->dest)); ++ jit_cache_opcode(gen, insn->opcode); ++ jit_cache_native(gen, (jit_nint)(insn->dest)); break; case JIT_OP_CALL_INDIRECT: case JIT_OP_CALL_INDIRECT_TAIL: /* Call a function, whose pointer is supplied in the register */ load_value(gen, insn->value1, 1); -- jit_cache_opcode(&(gen->posn), insn->opcode); -- jit_cache_native(&(gen->posn), (jit_nint)(insn->value2)); -- jit_cache_native(&(gen->posn), (jit_nint) ++ jit_cache_opcode(gen, insn->opcode); ++ jit_cache_native(gen, (jit_nint)(insn->value2)); ++ jit_cache_native(gen, (jit_nint) (jit_type_num_params((jit_type_t)(insn->value2)))); break; @@@ -1224,22 -1214,22 +1224,22 @@@ case JIT_OP_CALL_VTABLE_PTR_TAIL: /* Call a function, whose vtable pointer is supplied in the register */ load_value(gen, insn->value1, 1); -- jit_cache_opcode(&(gen->posn), insn->opcode); ++ jit_cache_opcode(gen, insn->opcode); break; case JIT_OP_CALL_EXTERNAL: case JIT_OP_CALL_EXTERNAL_TAIL: /* Call a native function, whose pointer is supplied explicitly */ -- jit_cache_opcode(&(gen->posn), insn->opcode); -- jit_cache_native(&(gen->posn), (jit_nint)(insn->value2)); -- jit_cache_native(&(gen->posn), (jit_nint)(insn->dest)); -- jit_cache_native(&(gen->posn), (jit_nint) ++ jit_cache_opcode(gen, insn->opcode); ++ jit_cache_native(gen, (jit_nint)(insn->value2)); ++ jit_cache_native(gen, (jit_nint)(insn->dest)); ++ jit_cache_native(gen, (jit_nint) (jit_type_num_params((jit_type_t)(insn->value2)))); break; case JIT_OP_RETURN: /* Return from the current function with no result */ -- jit_cache_opcode(&(gen->posn), JIT_OP_RETURN); ++ jit_cache_opcode(gen, JIT_OP_RETURN); break; case JIT_OP_RETURN_INT: @@@ -1249,29 -1239,29 +1249,28 @@@ case JIT_OP_RETURN_NFLOAT: /* Return from the current function with a specific result */ load_value(gen, insn->value1, 1); -- jit_cache_opcode(&(gen->posn), insn->opcode); ++ jit_cache_opcode(gen, insn->opcode); break; case JIT_OP_RETURN_SMALL_STRUCT: /* Return from current function with a small structure result */ load_value(gen, insn->value1, 1); -- jit_cache_opcode(&(gen->posn), insn->opcode); -- jit_cache_native(&(gen->posn), jit_value_get_nint_constant(insn->value2)); ++ jit_cache_opcode(gen, insn->opcode); ++ jit_cache_native(gen, jit_value_get_nint_constant(insn->value2)); break; case JIT_OP_SETUP_FOR_NESTED: /* TODO!!! */ /* Set up to call a nested child */ -- jit_cache_opcode(&(gen->posn), insn->opcode); ++ jit_cache_opcode(gen, insn->opcode); adjust_working(gen, 2); break; case JIT_OP_SETUP_FOR_SIBLING: /* TODO!!! */ /* Set up to call a nested sibling */ -- jit_cache_opcode(&(gen->posn), insn->opcode); -- jit_cache_native(&(gen->posn), -- jit_value_get_nint_constant(insn->value1)); ++ jit_cache_opcode(gen, insn->opcode); ++ jit_cache_native(gen, jit_value_get_nint_constant(insn->value1)); adjust_working(gen, 2); break; @@@ -1280,15 -1270,15 +1279,15 @@@ _jit_gen_fix_value(insn->value1); if(insn->value1->frame_offset >= 0) { -- jit_cache_opcode(&(gen->posn), JIT_INTERP_OP_IMPORT_LOCAL); -- jit_cache_native(&(gen->posn), insn->value1->frame_offset); -- jit_cache_native(&(gen->posn), jit_value_get_nint_constant(insn->value2)); ++ jit_cache_opcode(gen, JIT_INTERP_OP_IMPORT_LOCAL); ++ jit_cache_native(gen, insn->value1->frame_offset); ++ jit_cache_native(gen, jit_value_get_nint_constant(insn->value2)); } else { -- jit_cache_opcode(&(gen->posn), JIT_INTERP_OP_IMPORT_ARG); -- jit_cache_native(&(gen->posn), -(insn->value1->frame_offset + 1)); -- jit_cache_native(&(gen->posn), jit_value_get_nint_constant(insn->value2)); ++ jit_cache_opcode(gen, JIT_INTERP_OP_IMPORT_ARG); ++ jit_cache_native(gen, -(insn->value1->frame_offset + 1)); ++ jit_cache_native(gen, jit_value_get_nint_constant(insn->value2)); } store_value(gen, insn->dest); break; @@@ -1296,13 -1286,13 +1295,13 @@@ case JIT_OP_THROW: /* Throw an exception */ load_value(gen, insn->value1, 1); -- jit_cache_opcode(&(gen->posn), insn->opcode); ++ jit_cache_opcode(gen, insn->opcode); break; case JIT_OP_LOAD_PC: case JIT_OP_LOAD_EXCEPTION_PC: /* Load the current program counter onto the stack */ -- jit_cache_opcode(&(gen->posn), insn->opcode); ++ jit_cache_opcode(gen, insn->opcode); store_value(gen, insn->dest); break; @@@ -1318,7 -1308,7 +1317,7 @@@ case JIT_OP_LEAVE_FINALLY: /* Leave a finally clause */ -- jit_cache_opcode(&(gen->posn), insn->opcode); ++ jit_cache_opcode(gen, insn->opcode); break; case JIT_OP_ENTER_FILTER: @@@ -1331,7 -1321,7 +1330,7 @@@ case JIT_OP_LEAVE_FILTER: /* Leave a filter clause, returning a particular value */ load_value(gen, insn->value1, 0); -- jit_cache_opcode(&(gen->posn), insn->opcode); ++ jit_cache_opcode(gen, insn->opcode); break; case JIT_OP_INCOMING_REG: @@@ -1350,28 -1340,28 +1349,28 @@@ case JIT_TYPE_USHORT: case JIT_TYPE_INT: case JIT_TYPE_UINT: -- jit_cache_opcode(&(gen->posn), JIT_INTERP_OP_LDR_0_INT); ++ jit_cache_opcode(gen, JIT_INTERP_OP_LDR_0_INT); store_value(gen, insn->value1); break; case JIT_TYPE_LONG: case JIT_TYPE_ULONG: -- jit_cache_opcode(&(gen->posn), JIT_INTERP_OP_LDR_0_LONG); ++ jit_cache_opcode(gen, JIT_INTERP_OP_LDR_0_LONG); store_value(gen, insn->value1); break; case JIT_TYPE_FLOAT32: -- jit_cache_opcode(&(gen->posn), JIT_INTERP_OP_LDR_0_FLOAT32); ++ jit_cache_opcode(gen, JIT_INTERP_OP_LDR_0_FLOAT32); store_value(gen, insn->value1); break; case JIT_TYPE_FLOAT64: -- jit_cache_opcode(&(gen->posn), JIT_INTERP_OP_LDR_0_FLOAT64); ++ jit_cache_opcode(gen, JIT_INTERP_OP_LDR_0_FLOAT64); store_value(gen, insn->value1); break; case JIT_TYPE_NFLOAT: -- jit_cache_opcode(&(gen->posn), JIT_INTERP_OP_LDR_0_NFLOAT); ++ jit_cache_opcode(gen, JIT_INTERP_OP_LDR_0_NFLOAT); store_value(gen, insn->value1); break; } @@@ -1398,8 -1388,8 +1397,8 @@@ load_value(gen, insn->dest, 0); load_value(gen, insn->value1, 1); size = (jit_nint)jit_type_get_size(jit_value_get_type(insn->dest)); -- jit_cache_opcode(&(gen->posn), insn->opcode); -- jit_cache_native(&(gen->posn), size); ++ jit_cache_opcode(gen, insn->opcode); ++ jit_cache_native(gen, size); break; case JIT_OP_ADDRESS_OF: @@@ -1407,13 -1397,13 +1406,13 @@@ _jit_gen_fix_value(insn->value1); if(insn->value1->frame_offset >= 0) { -- jit_cache_opcode(&(gen->posn), JIT_INTERP_OP_LDLA_0); -- jit_cache_native(&(gen->posn), insn->value1->frame_offset); ++ jit_cache_opcode(gen, JIT_INTERP_OP_LDLA_0); ++ jit_cache_native(gen, insn->value1->frame_offset); } else { -- jit_cache_opcode(&(gen->posn), JIT_INTERP_OP_LDAA_0); -- jit_cache_native(&(gen->posn), -(insn->value1->frame_offset + 1)); ++ jit_cache_opcode(gen, JIT_INTERP_OP_LDAA_0); ++ jit_cache_native(gen, -(insn->value1->frame_offset + 1)); } store_value(gen, insn->dest); break; @@@ -1425,7 -1415,7 +1424,7 @@@ case JIT_OP_PUSH_NFLOAT: /* Push an item onto the stack, ready for a function call */ load_value(gen, insn->value1, 1); -- jit_cache_opcode(&(gen->posn), insn->opcode); ++ jit_cache_opcode(gen, insn->opcode); adjust_working(gen, 1); break; @@@ -1434,14 -1424,14 +1433,14 @@@ load_value(gen, insn->value1, 1); /* Push the structure at the designated pointer */ size = jit_value_get_nint_constant(insn->value2); -- jit_cache_opcode(&(gen->posn), insn->opcode); -- jit_cache_native(&(gen->posn), size); ++ jit_cache_opcode(gen, insn->opcode); ++ jit_cache_native(gen, size); adjust_working(gen, JIT_NUM_ITEMS_IN_STRUCT(size)); break; case JIT_OP_PUSH_RETURN_AREA_PTR: /* Push the address of the interpreter's return area */ -- jit_cache_opcode(&(gen->posn), insn->opcode); ++ jit_cache_opcode(gen, insn->opcode); adjust_working(gen, 1); break; @@@ -1450,20 -1440,20 +1449,20 @@@ size = jit_value_get_nint_constant(insn->value1); if(size == 1) { -- jit_cache_opcode(&(gen->posn), JIT_INTERP_OP_POP); ++ jit_cache_opcode(gen, JIT_INTERP_OP_POP); } else if(size == 2) { -- jit_cache_opcode(&(gen->posn), JIT_INTERP_OP_POP_2); ++ jit_cache_opcode(gen, JIT_INTERP_OP_POP_2); } else if(size == 3) { -- jit_cache_opcode(&(gen->posn), JIT_INTERP_OP_POP_3); ++ jit_cache_opcode(gen, JIT_INTERP_OP_POP_3); } else if(size != 0) { -- jit_cache_opcode(&(gen->posn), JIT_OP_POP_STACK); -- jit_cache_native(&(gen->posn), size); ++ jit_cache_opcode(gen, JIT_OP_POP_STACK); ++ jit_cache_native(gen, size); } break; @@@ -1471,8 -1461,8 +1470,8 @@@ /* Flush a small structure return value back into the frame */ load_value(gen, insn->value1, 0); size = (jit_nint)jit_type_get_size(jit_value_get_type(insn->value1)); -- jit_cache_opcode(&(gen->posn), insn->opcode); -- jit_cache_native(&(gen->posn), size); ++ jit_cache_opcode(gen, insn->opcode); ++ jit_cache_native(gen, size); break; case JIT_OP_LOAD_RELATIVE_SBYTE: @@@ -1487,8 -1477,8 +1486,8 @@@ /* Load a value from a relative pointer */ load_value(gen, insn->value1, 1); offset = jit_value_get_nint_constant(insn->value2); -- jit_cache_opcode(&(gen->posn), insn->opcode); -- jit_cache_native(&(gen->posn), offset); ++ jit_cache_opcode(gen, insn->opcode); ++ jit_cache_native(gen, offset); store_value(gen, insn->dest); break; @@@ -1498,9 -1488,9 +1497,9 @@@ load_value(gen, insn->value1, 1); offset = jit_value_get_nint_constant(insn->value2); size = (jit_nint)jit_type_get_size(jit_value_get_type(insn->dest)); -- jit_cache_opcode(&(gen->posn), insn->opcode); -- jit_cache_native(&(gen->posn), offset); -- jit_cache_native(&(gen->posn), size); ++ jit_cache_opcode(gen, insn->opcode); ++ jit_cache_native(gen, offset); ++ jit_cache_native(gen, size); break; case JIT_OP_STORE_RELATIVE_BYTE: @@@ -1514,8 -1504,8 +1513,8 @@@ load_value(gen, insn->dest, 0); load_value(gen, insn->value1, 1); offset = jit_value_get_nint_constant(insn->value2); -- jit_cache_opcode(&(gen->posn), insn->opcode); -- jit_cache_native(&(gen->posn), offset); ++ jit_cache_opcode(gen, insn->opcode); ++ jit_cache_native(gen, offset); break; case JIT_OP_STORE_RELATIVE_STRUCT: @@@ -1524,9 -1514,9 +1523,9 @@@ load_value(gen, insn->value1, 1); offset = jit_value_get_nint_constant(insn->value2); size = (jit_nint)jit_type_get_size(jit_value_get_type(insn->value1)); -- jit_cache_opcode(&(gen->posn), insn->opcode); -- jit_cache_native(&(gen->posn), offset); -- jit_cache_native(&(gen->posn), size); ++ jit_cache_opcode(gen, insn->opcode); ++ jit_cache_native(gen, offset); ++ jit_cache_native(gen, size); break; case JIT_OP_ADD_RELATIVE: @@@ -1535,8 -1525,8 +1534,8 @@@ if(offset != 0) { load_value(gen, insn->value1, 1); -- jit_cache_opcode(&(gen->posn), insn->opcode); -- jit_cache_native(&(gen->posn), offset); ++ jit_cache_opcode(gen, insn->opcode); ++ jit_cache_native(gen, offset); store_value(gen, insn->dest); } else @@@ -1548,9 -1538,9 +1547,9 @@@ case JIT_OP_MARK_BREAKPOINT: /* Mark the current location as a potential breakpoint */ -- jit_cache_opcode(&(gen->posn), insn->opcode); -- jit_cache_native(&(gen->posn), insn->value1->address); -- jit_cache_native(&(gen->posn), insn->value2->address); ++ jit_cache_opcode(gen, insn->opcode); ++ jit_cache_native(gen, insn->value1->address); ++ jit_cache_native(gen, insn->value2->address); break; default: @@@ -1566,7 -1556,7 +1565,7 @@@ { load_value(gen, insn->value2, 2); } -- jit_cache_opcode(&(gen->posn), insn->opcode); ++ jit_cache_opcode(gen, insn->opcode); if(insn->dest && (insn->flags & JIT_INSN_DEST_IS_VALUE) == 0) { store_value(gen, insn->dest); @@@ -1587,7 -1577,7 +1586,7 @@@ void _jit_gen_start_block(jit_gencode_ void **next; /* Set the address of this block */ -- block->address = (void *)(gen->posn.ptr); ++ block->address = (void *)(gen->ptr); /* If this block has pending fixups, then apply them now */ fixup = (void **)(block->fixup_list); diff --cc jit/jit-rules-x86-64.c index 155d201,155d201..235f93b --- a/jit/jit-rules-x86-64.c +++ b/jit/jit-rules-x86-64.c @@@ -122,12 -122,12 +122,12 @@@ do { /* * Setup or teardown the x86 code output process. */ --#define jit_cache_setup_output(needed) \ -- unsigned char *inst = gen->posn.ptr; \ -- _jit_cache_check_space(&gen->posn, (needed)) ++#define jit_cache_setup_output(needed) \ ++ unsigned char *inst = gen->ptr; \ ++ _jit_gen_check_space(gen, (needed)) #define jit_cache_end_output() \ -- gen->posn.ptr = inst ++ gen->ptr = inst /* * Set this to 1 for debugging fixups @@@ -293,7 -293,7 +293,7 @@@ _jit_xmm1_reg_imm_size_float32(jit_genc unsigned char *inst; inst = *inst_ptr; -- ptr = _jit_cache_alloc(&(gen->posn), sizeof(jit_float32)); ++ ptr = _jit_gen_alloc(gen, sizeof(jit_float32)); if(!ptr) { return 0; @@@ -336,7 -336,7 +336,7 @@@ _jit_xmm1_reg_imm_size_float64(jit_genc unsigned char *inst; inst = *inst_ptr; -- ptr = _jit_cache_alloc(&(gen->posn), sizeof(jit_float64)); ++ ptr = _jit_gen_alloc(gen, sizeof(jit_float64)); if(!ptr) { return 0; @@@ -378,7 -378,7 +378,7 @@@ _jit_plops_reg_imm(jit_gencode_t gen, u unsigned char *inst; inst = *inst_ptr; -- ptr = _jit_cache_alloc(&(gen->posn), 16); ++ ptr = _jit_gen_alloc(gen, 16); if(!ptr) { return 0; @@@ -420,7 -420,7 +420,7 @@@ _jit_plopd_reg_imm(jit_gencode_t gen, u unsigned char *inst; inst = *inst_ptr; -- ptr = _jit_cache_alloc(&(gen->posn), 16); ++ ptr = _jit_gen_alloc(gen, 16); if(!ptr) { return 0; @@@ -1152,8 -1152,8 +1152,8 @@@ _jit_gen_free_reg(jit_gencode_t gen, in floating-point register whose value hasn't been used yet */ if(!value_used && IS_FPU_REG(reg)) { -- _jit_cache_check_space(&gen->posn, 2); -- x86_fstp(gen->posn.ptr, reg - X86_64_REG_ST0); ++ _jit_gen_check_space(gen, 2); ++ x86_fstp(gen->ptr, reg - X86_64_REG_ST0); } } @@@ -1381,7 -1381,7 +1381,7 @@@ xmm_cmp_reg_imm(jit_gencode_t gen, unsi if(is_double) { -- ptr = _jit_cache_alloc(&(gen->posn), sizeof(jit_float64)); ++ ptr = _jit_gen_alloc(gen, sizeof(jit_float64)); if(!ptr) { return 0; @@@ -1390,7 -1390,7 +1390,7 @@@ } else { -- ptr = _jit_cache_alloc(&(gen->posn), sizeof(jit_float32)); ++ ptr = _jit_gen_alloc(gen, sizeof(jit_float32)); if(!ptr) { return 0; @@@ -1803,7 -1803,7 +1803,7 @@@ _jit_gen_load_value(jit_gencode_t gen, { jit_nint offset; -- ptr = _jit_cache_alloc(&(gen->posn), sizeof(jit_float32)); ++ ptr = _jit_gen_alloc(gen, sizeof(jit_float32)); jit_memcpy(ptr, &float32_value, sizeof(float32_value)); offset = (jit_nint)ptr - ((jit_nint)inst + 6); @@@ -1872,7 -1872,7 +1872,7 @@@ { jit_nint offset; -- ptr = _jit_cache_alloc(&(gen->posn), sizeof(jit_float64)); ++ ptr = _jit_gen_alloc(gen, sizeof(jit_float64)); jit_memcpy(ptr, &float64_value, sizeof(float64_value)); offset = (jit_nint)ptr - ((jit_nint)inst + 6); @@@ -1918,7 -1918,7 +1918,7 @@@ jit_nint offset; int xmm_reg = _jit_reg_info[reg].cpu_reg; -- ptr = _jit_cache_alloc(&(gen->posn), sizeof(jit_nfloat)); ++ ptr = _jit_gen_alloc(gen, sizeof(jit_nfloat)); jit_memcpy(ptr, &nfloat_value, sizeof(nfloat_value)); offset = (jit_nint)ptr - ((jit_nint)inst + (xmm_reg > 7 ? 9 : 8)); @@@ -1953,7 -1953,7 +1953,7 @@@ { jit_nint offset; -- ptr = _jit_cache_alloc(&(gen->posn), sizeof(jit_nfloat)); ++ ptr = _jit_gen_alloc(gen, sizeof(jit_nfloat)); jit_memcpy(ptr, &nfloat_value, sizeof(nfloat_value)); offset = (jit_nint)ptr - ((jit_nint)inst + 6); @@@ -2491,9 -2491,9 +2491,9 @@@ _jit_gen_epilog(jit_gencode_t gen, jit_ jit_int *next; /* Bail out if there is insufficient space for the epilog */ -- _jit_cache_check_space(&gen->posn, 48); ++ _jit_gen_check_space(gen, 48); -- inst = gen->posn.ptr; ++ inst = gen->ptr; /* Perform fixups on any blocks that jump to the epilog */ fixup = (jit_int *)(gen->epilog_fixup); @@@ -2594,7 -2594,7 +2594,7 @@@ /* and return */ x86_64_ret(inst); -- gen->posn.ptr = inst; ++ gen->ptr = inst; } /* @@@ -2758,7 -2758,7 +2758,7 @@@ _jit_gen_start_block(jit_gencode_t gen void **absolute_next; /* Set the address of this block */ -- block->address = (void *)(gen->posn.ptr); ++ block->address = (void *)(gen->ptr); /* If this block has pending fixups, then apply them now */ fixup = (jit_int *)(block->fixup_list); diff --cc jit/jit-rules-x86-64.ins index 34c87ff,34c87ff..faca68e --- a/jit/jit-rules-x86-64.ins +++ b/jit/jit-rules-x86-64.ins @@@ -3297,8 -3297,8 +3297,7 @@@ JIT_OP_JUMP_TABLE: ternary, branc labels = (jit_label_t *) $2; num_labels = $3; -- patch_jump_table = (unsigned char *)_jit_cache_alloc(&(gen->posn), -- sizeof(void *) * $3); ++ patch_jump_table = (unsigned char *)_jit_gen_alloc(gen, sizeof(void *) * $3); if(!patch_jump_table) { /* The cache is full */ diff --cc jit/jit-rules-x86.c index eb9739e,eb9739e..5955367 --- a/jit/jit-rules-x86.c +++ b/jit/jit-rules-x86.c @@@ -265,7 -265,7 +265,7 @@@ void _jit_gen_epilog(jit_gencode_t gen void **next; /* Check if there is sufficient space for the epilog */ -- _jit_cache_check_space(&gen->posn, 48); ++ _jit_gen_check_space(gen, 48); #if JIT_APPLY_X86_FASTCALL == 1 /* Determine the number of parameter bytes to pop when we return */ @@@ -333,7 -333,7 +333,7 @@@ #endif /* Perform fixups on any blocks that jump to the epilog */ -- inst = gen->posn.ptr; ++ inst = gen->ptr; fixup = (void **)(gen->epilog_fixup); while(fixup != 0) { @@@ -393,7 -393,7 +393,7 @@@ { x86_ret(inst); } -- gen->posn.ptr = inst; ++ gen->ptr = inst; } #if 0 @@@ -404,10 -404,10 +404,10 @@@ void *_jit_gen_redirector(jit_gencode_t gen, jit_function_t func) { void *ptr, *entry; -- _jit_cache_check_space(&gen->posn, 8); ++ _jit_gen_check_space(gen, 8); ptr = (void *)&(func->entry_point); -- entry = gen->posn.ptr; -- x86_jump_mem(gen->posn.ptr, ptr); ++ entry = gen->ptr; ++ x86_jump_mem(gen->ptr, ptr); return entry; } #endif @@@ -416,11 -416,11 +416,11 @@@ * Setup or teardown the x86 code output process. */ #define jit_cache_setup_output(needed) \ -- unsigned char *inst = gen->posn.ptr; \ -- _jit_cache_check_space(&gen->posn, (needed)) ++ unsigned char *inst = gen->ptr; \ ++ _jit_gen_check_space(gen, (needed)) #define jit_cache_end_output() \ -- gen->posn.ptr = inst ++ gen->ptr = inst /* * Get a temporary register that isn't one of the specified registers. @@@ -637,8 -637,8 +637,8 @@@ _jit_gen_free_reg(jit_gencode_t gen, in floating-point register whose value hasn't been used yet */ if(!value_used && IS_FLOAT_REG(reg)) { -- _jit_cache_check_space(&gen->posn, 2); -- x86_fstp(gen->posn.ptr, reg - X86_REG_ST0); ++ _jit_gen_check_space(gen, 2); ++ x86_fstp(gen->ptr, reg - X86_REG_ST0); } } @@@ -809,7 -809,7 +809,7 @@@ _jit_gen_load_value(jit_gencode_t gen, } else { -- ptr = _jit_cache_alloc(&(gen->posn), sizeof(jit_float32)); ++ ptr = _jit_gen_alloc(gen, sizeof(jit_float32)); jit_memcpy(ptr, &float32_value, sizeof(float32_value)); x86_fld(inst, ptr, 0); } @@@ -847,7 -847,7 +847,7 @@@ } else { -- ptr = _jit_cache_alloc(&(gen->posn), sizeof(jit_float64)); ++ ptr = _jit_gen_alloc(gen, sizeof(jit_float64)); jit_memcpy(ptr, &float64_value, sizeof(float64_value)); x86_fld(inst, ptr, 1); } @@@ -885,7 -885,7 +885,7 @@@ } else { -- ptr = _jit_cache_alloc(&(gen->posn), sizeof(jit_nfloat)); ++ ptr = _jit_gen_alloc(gen, sizeof(jit_nfloat)); jit_memcpy(ptr, &nfloat_value, sizeof(nfloat_value)); if(sizeof(jit_nfloat) == sizeof(jit_float64)) { @@@ -1430,7 -1430,7 +1430,7 @@@ void _jit_gen_start_block(jit_gencode_ void **next; /* Set the address of this block */ -- block->address = (void *)(gen->posn.ptr); ++ block->address = (void *)(gen->ptr); /* If this block has pending fixups, then apply them now */ fixup = (void **)(block->fixup_list); diff --cc jit/jit-rules-x86.ins index 326cbf9,326cbf9..363304b --- a/jit/jit-rules-x86.ins +++ b/jit/jit-rules-x86.ins @@@ -1849,8 -1849,8 +1849,8 @@@ JIT_OP_SETUP_FOR_SIBLING: branc } while(level > 0) { -- gen->posn.ptr = inst; -- _jit_cache_check_space(&gen->posn, 16); ++ gen->ptr = inst; ++ _jit_gen_check_space(gen, 16); x86_mov_reg_membase(inst, cpu_reg, cpu_reg, 0, sizeof(void *)); --level; } @@@ -1868,8 -1868,8 +1868,8 @@@ JIT_OP_IMPORT: manua _jit_gen_fix_value(insn->value1); reg = _jit_regs_load_value (gen, func->builder->parent_frame, 1, 0); -- inst = gen->posn.ptr; -- _jit_cache_check_space(&gen->posn, 32 + level * 8); ++ inst = gen->ptr; ++ _jit_gen_check_space(gen, 32 + level * 8); reg = _jit_reg_info[reg].cpu_reg; while(level > 0) { @@@ -1880,7 -1880,7 +1880,7 @@@ { x86_alu_reg_imm(inst, X86_ADD, reg, insn->value1->frame_offset); } -- gen->posn.ptr = inst; ++ gen->ptr = inst; } /* @@@ -2385,13 -2385,13 +2385,13 @@@ JIT_OP_STORE_RELATIVE_STRUCT: manua JIT_INSN_DEST_LIVE))); _jit_regs_spill_all(gen); _jit_gen_fix_value(insn->value1); -- inst = gen->posn.ptr; -- _jit_cache_check_space(&gen->posn, 128); ++ inst = gen->ptr; ++ _jit_gen_check_space(gen, 128); reg = _jit_reg_info[reg].cpu_reg; inst = memory_copy(gen, inst, reg, (int)(insn->value2->address), X86_EBP, insn->value1->frame_offset, jit_type_get_size(jit_value_get_type(insn->value1))); -- gen->posn.ptr = inst; ++ gen->ptr = inst; } JIT_OP_ADD_RELATIVE: diff --cc jit/jit-rules.c index 20e01a1,20e01a1..32f5a10 --- a/jit/jit-rules.c +++ b/jit/jit-rules.c @@@ -737,6 -737,6 +737,31 @@@ int _jit_create_call_setup_insn #endif /* JIT_CDECL_WORD_REG_PARAMS */ ++void ++_jit_gen_check_space(jit_gencode_t gen, int space) ++{ ++ if((gen->ptr + space) >= gen->limit) ++ { ++ /* No space left on the current cache page. */ ++ gen->ptr = gen->limit; ++ jit_exception_builtin(JIT_RESULT_CACHE_FULL); ++ } ++} ++ ++void * ++_jit_gen_alloc(jit_gencode_t gen, unsigned long size) ++{ ++ void *ptr; ++ _jit_cache_set_code_break(gen->cache, gen->ptr); ++ ptr = _jit_cache_alloc_data(gen->cache, size, JIT_BEST_ALIGNMENT); ++ if(!ptr) ++ { ++ jit_exception_builtin(JIT_RESULT_CACHE_FULL); ++ } ++ gen->limit = _jit_cache_get_code_limit(gen->cache); ++ return ptr; ++} ++ int _jit_int_lowest_byte(void) { union diff --cc jit/jit-rules.h index 4ff23f4,67909ff..6af7e87 --- a/jit/jit-rules.h +++ b/jit/jit-rules.h @@@ -159,10 -159,10 +159,12 @@@ struct jit_regcontent typedef struct jit_gencode *jit_gencode_t; struct jit_gencode { ++ jit_cache_t cache; /* Cache this position is attached to */ ++ unsigned char *ptr; /* Current code pointer */ ++ unsigned char *limit; /* Current code space limit */ jit_regused_t permanent; /* Permanently allocated global regs */ jit_regused_t touched; /* All registers that were touched */ jit_regused_t inhibit; /* Temporarily inhibited registers */ -- jit_cache_posn posn; /* Current cache output position */ jit_regcontents_t contents[JIT_NUM_REGS]; /* Contents of each register */ int current_age; /* Current age value for registers */ #ifdef JIT_REG_STACK @@@ -191,6 -190,6 +193,17 @@@ struct jit_elf_inf * External function defintions. */ ++/* ++ * Determine if there is sufficient space in the code cache. ++ * If not throws JIT_RESULT_CACHE_FULL exception. ++ */ ++void _jit_gen_check_space(jit_gencode_t gen, int space); ++ ++/* ++ * Allocate a memory chunk for data. ++ */ ++void *_jit_gen_alloc(jit_gencode_t gen, unsigned long size); ++ void _jit_init_backend(void); void _jit_gen_get_elf_info(jit_elf_info_t *info); int _jit_create_entry_insns(jit_function_t func); diff --cc tools/gen-rules-parser.y index 56704d7,56704d7..5202677 --- a/tools/gen-rules-parser.y +++ b/tools/gen-rules-parser.y @@@ -1445,7 -1445,7 +1445,7 @@@ static void gensel_output_clauses(gense } else { -- printf("\t\t_jit_cache_check_space(&gen->posn, "); ++ printf("\t\t_jit_gen_check_space(gen, "); } if(space && space->values && space->values->value) { @@@ -1468,7 -1468,7 +1468,7 @@@ printf(");\n"); } -- printf("\t\tinst = (%s)(gen->posn.ptr);\n", gensel_inst_type); ++ printf("\t\tinst = (%s)(gen->ptr);\n", gensel_inst_type); regs = 0; imms = 0; @@@ -1547,7 -1547,7 +1547,7 @@@ } else { -- printf("\t\tgen->posn.ptr = (unsigned char *)inst;\n"); ++ printf("\t\tgen->ptr = (unsigned char *)inst;\n"); } if(contains_registers) {