+2012-10-04 Aleksey Demakov <ademakov@gmail.com>
+
+ * jit/jit-cache.h, jit/jit-cache.c (_jit_cache_start_function):
+ remove the restart_count argument.
+ * jit/jit-cache.h, jit/jit-cache.c (_jit_cache_extend): add
+ function to allocate more cache space.
+ * jit/jit-cache.c (_jit_cache_alloc_data): let be called outside
+ function generation context.
+
2012-07-29 Aleksey Demakov <ademakov@gmail.com>
* jit/jit-cache.h, jit/jit-cache.c (_jit_cache_start_function)
/*
* Allocate a cache page and add it to the cache.
*/
-static void AllocCachePage(jit_cache_t cache, int factor)
+static void
+AllocCachePage(jit_cache_t cache, int factor)
{
long num;
unsigned char *ptr;
/*
* Rotate a sub-tree around a specific node.
*/
-static jit_cache_method_t CacheRotate(jit_cache_t cache, unsigned char *key,
- jit_cache_method_t around)
+static jit_cache_method_t
+CacheRotate(jit_cache_t cache, unsigned char *key, jit_cache_method_t around)
{
jit_cache_method_t child, grandChild;
int setOnLeft;
* Add a method region block to the red-black lookup tree
* that is associated with a method cache.
*/
-static void AddToLookupTree(jit_cache_t cache, jit_cache_method_t method)
+static void
+AddToLookupTree(jit_cache_t cache, jit_cache_method_t method)
{
unsigned char *key = method->func->code_start;
jit_cache_method_t temp;
SetBlack(cache->head.right);
}
-static unsigned char *
-cache_alloc_data(jit_cache_t cache, unsigned long size, unsigned long align)
-{
- unsigned char *ptr;
-
- /* 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)
- {
- /* 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_free(cache);
}
-int
-_jit_cache_start_function(jit_cache_t cache, jit_function_t func, int restart_count)
+void
+_jit_cache_extend(jit_cache_t cache, int count)
{
- /* Bail out if there is a started function already */
+ /* Compute the page size factor */
+ int factor = 1 << count;
+
+ /* Bail out if there is a started function */
if(cache->method)
{
- return JIT_CACHE_ERROR;
+ return;
}
- /* Do we need to allocate a new cache page? */
- if(restart_count > 0)
+ /* 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)))
{
- /* Compute the page size factor */
- int factor = 1 << (restart_count - 1);
+ jit_free_exec(p->page, cache->pageSize * p->factor);
- /* 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)))
+ --(cache->numPages);
+ if(cache->pagesLeft >= 0)
{
- 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;
+ cache->pagesLeft += p->factor;
+ }
+ cache->free_start = 0;
+ cache->free_end = 0;
- if(factor <= p->factor)
- {
- factor = p->factor << 1;
- }
+ if(factor <= p->factor)
+ {
+ factor = p->factor << 1;
}
+ }
- /* Allocate a new page now */
- AllocCachePage(cache, factor);
+ /* Allocate a new page now */
+ AllocCachePage(cache, factor);
+}
+
+int
+_jit_cache_start_function(jit_cache_t cache, jit_function_t func)
+{
+ /* Bail out if there is a started function already */
+ if(cache->method)
+ {
+ return JIT_CACHE_ERROR;
}
/* Bail out if the cache is already full */
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) cache_alloc_data(cache,
- sizeof(struct jit_cache_method),
- JIT_BEST_ALIGNMENT);
+ /* Allocate memory for the function information block */
+ cache->method = (jit_cache_method_t)
+ _jit_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;
}
+
+ /* Initialize the function information */
cache->method->func = func;
cache->method->func->code_start = cache->free_start;
cache->method->func->code_end = cache->free_start;
{
return;
}
- if ((unsigned char *) ptr > cache->free_end) {
+ if ((unsigned char *) ptr > cache->free_end)
+ {
return;
}
void *
_jit_cache_alloc_data(jit_cache_t cache, unsigned long size, unsigned long align)
{
- /* Bail out if there is no started function */
- if(!cache->method)
+ unsigned char *ptr;
+
+ /* Get memory from the top of the free region, so that it does not
+ overlap with the function code possibly being written at the bottom
+ of the free region */
+ ptr = cache->free_end - size;
+ ptr = (unsigned char *) (((jit_nuint) ptr) & ~(align - 1));
+ if(ptr < cache->free_start)
{
+ /* When we aligned the block, it caused an overflow */
return 0;
}
/* Allocate the block and return it */
- return cache_alloc_data(cache, size, align);
+ cache->free_end = ptr;
+ return ptr;
}
void *
/*
- * jit-cache.h - Translated method cache implementation.
+ * jit-cache.h - Translated function cache implementation.
*
* Copyright (C) 2002, 2004, 2008 Southern Storm Software, Pty Ltd.
*
#define JIT_CACHE_ERROR 3 /* Other error */
/*
- * Create a method cache. Returns NULL if out of memory.
+ * Create a code cache. Returns NULL if out of memory.
* If "limit" is non-zero, then it specifies the maximum
* size of the cache in bytes. If "cache_page_size" is
* non-zero, then it indicates the dafault/minimum cache
int max_page_factor);
/*
- * Destroy a method cache.
+ * Destroy a code cache.
*/
void _jit_cache_destroy(jit_cache_t cache);
/*
- * 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.
+ * Request to allocate more code cache space.
+ *
+ * The "count" value should normally be zero except if just after the last
+ * call a function is being recompiled again because it is still too big
+ * to fit into the available cache space. In this case the "count" value
+ * should gradually increase.
+ */
+void _jit_cache_extend(jit_cache_t cache, int count);
+
+/*
+ * Start output of a function.
*/
-int _jit_cache_start_function(jit_cache_t cache,
- jit_function_t func,
- int restart_count);
+int _jit_cache_start_function(jit_cache_t cache, jit_function_t func);
/*
- * End output of a function. Returns zero if a restart is needed.
+ * End output of a function.
*/
int _jit_cache_end_function(jit_cache_t cache, int result);
/*
- * Get the boundary between used and free code space.
+ * Get the start address of memory available for function code generation.
+ *
+ * This function is only called betweed _jit_cache_start_function() and
+ * corresponding _jit_cache_end_function() calls.
+ *
+ * Initially it should return the start address of the allocated memory.
+ * Then the address may be moved forward with _jit_cache_set_code_break()
+ * calls.
*/
void *_jit_cache_get_code_break(jit_cache_t cache);
/*
- * Set the boundary between used and free code space.
+ * Set the address of memory yet available for function code generation.
+ *
+ * This function is only called betweed _jit_cache_start_function() and
+ * corresponding _jit_cache_end_function() calls.
+ *
+ * The given address must be greater than or equal to its last value as
+ * returned by the _jit_cache_get_code_break() call and also less than or
+ * equal to the memory the address returned by _jit_cache_get_code_limit()
+ * call.
+ *
+ * This function is to be used in two cases. First, on the end of code
+ * generation just before the _jit_cache_end_function() call. Second,
+ * before allocating data with _jit_cache_alloc_data() calls. This lets
+ * the cache know how much space was actually used and how much is still
+ * free.
*/
void _jit_cache_set_code_break(jit_cache_t cache, void *ptr);
/*
- * Get the end address of the free code space.
+ * Get the end address of memory available for function code generation.
+ *
+ * This function is only called betweed _jit_cache_start_function() and
+ * corresponding _jit_cache_end_function() calls.
+ *
+ * The available memory may change if during code generation there were
+ * _jit_cache_alloc_data() calls. So after such calls available memory
+ * should be rechecked.
*/
void *_jit_cache_get_code_limit(jit_cache_t cache);
/*
- * 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.
+ * Allocate "size" bytes of memory in the data area. Returns NULL if
+ * there is insufficient space to satisfy the request.
*/
void *_jit_cache_alloc_data(jit_cache_t cache,
unsigned long size,
* Allocate "size" bytes of storage when we aren't currently
* translating a method.
*/
-void *_jit_cache_alloc_no_method
- (jit_cache_t cache, unsigned long size, unsigned long align);
+void *_jit_cache_alloc_no_method(jit_cache_t cache, unsigned long size, unsigned long align);
/*
* Find the method that is associated with a particular
int result;
/* First try with the current cache page */
- result = _jit_cache_start_function(state->gen.cache,
- state->func,
- state->page_factor++);
+ result = _jit_cache_start_function(state->gen.cache, state->func);
if(result == JIT_CACHE_RESTART)
{
/* No space left on the current cache page. Allocate a new one. */
- result = _jit_cache_start_function(state->gen.cache,
- state->func,
- state->page_factor++);
+ _jit_cache_extend(state->gen.cache, state->page_factor++);
+ result = _jit_cache_start_function(state->gen.cache, state->func);
}
if(result != JIT_CACHE_OK)
{
/* Allocate a new cache page with the size that grows
by factor of 2 on each reallocation */
- result = _jit_cache_start_function(state->gen.cache,
- state->func,
- state->page_factor++);
+ _jit_cache_extend(state->gen.cache, state->page_factor++);
+ result = _jit_cache_start_function(state->gen.cache, state->func);
if(result != JIT_CACHE_OK)
{
/* Failed to allocate enough cache space */