Browse Source

tweak code cache API

cache-refactoring
Aleksey Demakov 12 years ago
parent
commit
e7547a6034
  1. 9
      ChangeLog
  2. 121
      jit/jit-cache.c
  3. 71
      jit/jit-cache.h
  4. 14
      jit/jit-compile.c

9
ChangeLog

@ -1,3 +1,12 @@
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)

121
jit/jit-cache.c

@ -118,7 +118,8 @@ struct jit_cache
/*
* 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;
@ -230,8 +231,8 @@ CacheCompare(jit_cache_t cache, unsigned char *key, jit_cache_method_t node)
/*
* 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;
@ -293,7 +294,8 @@ static jit_cache_method_t CacheRotate(jit_cache_t cache, unsigned char *key,
* 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;
@ -354,27 +356,6 @@ static void AddToLookupTree(jit_cache_t cache, jit_cache_method_t method)
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)
{
@ -468,45 +449,51 @@ _jit_cache_destroy(jit_cache_t cache)
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 */
@ -519,15 +506,18 @@ _jit_cache_start_function(jit_cache_t cache, jit_function_t func, int restart_co
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;
@ -591,7 +581,8 @@ _jit_cache_set_code_break(jit_cache_t cache, void *ptr)
{
return;
}
if ((unsigned char *) ptr > cache->free_end) {
if ((unsigned char *) ptr > cache->free_end)
{
return;
}
@ -615,14 +606,22 @@ _jit_cache_get_code_limit(jit_cache_t cache)
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 *

71
jit/jit-cache.h

@ -1,5 +1,5 @@
/*
* jit-cache.h - Translated method cache implementation.
* jit-cache.h - Translated function cache implementation.
*
* Copyright (C) 2002, 2004, 2008 Southern Storm Software, Pty Ltd.
*
@ -36,7 +36,7 @@ extern "C" {
#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
@ -49,46 +49,76 @@ jit_cache_t _jit_cache_create(long limit,
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,
@ -98,8 +128,7 @@ void *_jit_cache_alloc_data(jit_cache_t cache,
* 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

14
jit/jit-compile.c

@ -463,15 +463,12 @@ cache_alloc(_jit_compile_t *state)
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)
{
@ -571,9 +568,8 @@ 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_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 */

Loading…
Cancel
Save