+2012-10-07 Aleksey Demakov <ademakov@gmail.com>
+
+ * jit/jit-function.c (jit_function_create, _jit_function_destroy):
+ * jit/jit-cache.h, jit/jit-cache.c (_jit_cache_alloc_function)
+ (_jit_cache_free_function): allocate and free jit_function structs
+ within cache.
+
2012-10-04 Aleksey Demakov <ademakov@gmail.com>
* jit/jit-cache.h, jit/jit-cache.c (_jit_cache_start_function):
#include "jit-cache.h"
#include "jit-apply-func.h"
+#include <stddef.h> /* for offsetof */
+
#ifdef __cplusplus
extern "C" {
#endif
typedef struct jit_cache_method *jit_cache_method_t;
struct jit_cache_method
{
- jit_function_t func; /* Function */
jit_cache_method_t left; /* Left sub-tree and red/black bit */
jit_cache_method_t right; /* Right sub-tree */
+ struct _jit_function func; /* Function */
};
/*
else
{
/* Compare a regular node */
- if(key < node->func->code_start)
+ if(key < node->func.code_start)
{
return -1;
}
- else if(key > node->func->code_start)
+ else if(key > node->func.code_start)
{
return 1;
}
static void
AddToLookupTree(jit_cache_t cache, jit_cache_method_t method)
{
- unsigned char *key = method->func->code_start;
+ unsigned char *key = method->func.code_start;
jit_cache_method_t temp;
jit_cache_method_t greatGrandParent;
jit_cache_method_t grandParent;
cache->pagesLeft = -1;
}
cache->method = 0;
- cache->nil.func = 0;
cache->nil.left = &(cache->nil);
cache->nil.right = &(cache->nil);
- cache->head.func = 0;
cache->head.left = 0;
cache->head.right = &(cache->nil);
AllocCachePage(cache, factor);
}
+jit_function_t
+_jit_cache_alloc_function(jit_cache_t cache)
+{
+ jit_cache_method_t method = jit_cnew(struct jit_cache_method);
+ return &method->func;
+}
+
+void
+_jit_cache_free_function(jit_cache_t cache, jit_function_t func)
+{
+ jit_cache_method_t method = (jit_cache_method_t)
+ (((char *) func) - offsetof(struct jit_cache_method, func));
+ jit_free(method);
+}
+
int
_jit_cache_start_function(jit_cache_t cache, jit_function_t func)
{
/* 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;
- }
+ (((char *) func) - offsetof(struct jit_cache_method, func));
/* Initialize the function information */
- cache->method->func = func;
- cache->method->func->code_start = cache->free_start;
- cache->method->func->code_end = cache->free_start;
+ cache->method->func.code_start = cache->free_start;
+ cache->method->func.code_end = cache->free_start;
cache->method->left = 0;
cache->method->right = 0;
}
/* Update the method region block and then add it to the lookup tree */
- cache->method->func->code_end = cache->free_start;
+ cache->method->func.code_end = cache->free_start;
AddToLookupTree(cache, cache->method);
cache->method = 0;
jit_cache_method_t node = cache->head.right;
while(node != &(cache->nil))
{
- if(((unsigned char *)pc) < node->func->code_start)
+ if(((unsigned char *)pc) < node->func.code_start)
{
node = GetLeft(node);
}
- else if(((unsigned char *)pc) >= node->func->code_end)
+ else if(((unsigned char *)pc) >= node->func.code_end)
{
node = GetRight(node);
}
else
{
- return node->func;
+ return &node->func;
}
}
return 0;
*/
void _jit_cache_extend(jit_cache_t cache, int count);
+/*
+ * Allocate a function description structure.
+ */
+jit_function_t _jit_cache_alloc_function(jit_cache_t cache);
+
+/*
+ * Release a function description structure.
+ */
+void _jit_cache_free_function(jit_cache_t cache, jit_function_t func);
+
/*
* Start output of a function.
*/
* data structures within a multi-threaded environment.
* @end deftypefun
@*/
-jit_function_t jit_function_create(jit_context_t context, jit_type_t signature)
+jit_function_t
+jit_function_create(jit_context_t context, jit_type_t signature)
{
jit_function_t func;
-#if !defined(JIT_BACKEND_INTERP) && (defined(jit_redirector_size) || defined(jit_indirector_size))
jit_cache_t cache;
-#endif
+
+ /* We need the cache lock. */
+ jit_mutex_lock(&context->cache_lock);
+
+ /* Get the method cache */
+ cache = _jit_context_get_cache(context);
+ if(!cache)
+ {
+ jit_mutex_unlock(&context->cache_lock);
+ return 0;
+ }
/* Allocate memory for the function and clear it */
- func = jit_cnew(struct _jit_function);
+ func = _jit_cache_alloc_function(cache);
if(!func)
{
+ jit_mutex_unlock(&context->cache_lock);
return 0;
}
#if !defined(JIT_BACKEND_INTERP) && (defined(jit_redirector_size) || defined(jit_indirector_size))
/* TODO: if the function is destroyed the redirector and indirector memory
is leaked */
-
- /* We need the cache lock while we are allocating redirector and indirector */
- jit_mutex_lock(&(context->cache_lock));
-
- /* Get the method cache */
- cache = _jit_context_get_cache(context);
- if(!cache)
- {
- jit_mutex_unlock(&(context->cache_lock));
- jit_free(func);
- return 0;
- }
-
# if defined(jit_redirector_size)
/* Allocate redirector buffer */
func->redirector = _jit_cache_alloc_no_method(cache, jit_redirector_size, 1);
if(!func->redirector)
{
- jit_mutex_unlock(&(context->cache_lock));
- jit_free(func);
+ _jit_cache_free_function(cache, func);
+ jit_mutex_unlock(&context->cache_lock);
return 0;
}
# endif
func->indirector = _jit_cache_alloc_no_method(cache, jit_indirector_size, 1);
if(!func->indirector)
{
- jit_mutex_unlock(&(context->cache_lock));
- jit_free(func);
+ _jit_cache_free_function(cache, func);
+ jit_mutex_unlock(&context->cache_lock);
return 0;
}
# endif
-
- jit_mutex_unlock(&(context->cache_lock));
#endif /* !defined(JIT_BACKEND_INTERP) && (defined(jit_redirector_size) || defined(jit_indirector_size)) */
+ jit_mutex_unlock(&context->cache_lock);
+
/* Initialize the function block */
func->context = context;
func->signature = jit_type_copy(signature);
}
}
-void _jit_function_destroy(jit_function_t func)
+void
+_jit_function_destroy(jit_function_t func)
{
+ jit_context_t context;
+
if(!func)
{
return;
}
+
+ context = func->context;
if(func->next)
{
func->next->prev = func->prev;
}
else
{
- func->context->last_function = func->prev;
+ context->last_function = func->prev;
}
if(func->prev)
{
}
else
{
- func->context->functions = func->next;
+ context->functions = func->next;
}
+
_jit_function_free_builder(func);
_jit_varint_free_data(func->bytecode_offset);
- jit_meta_destroy(&(func->meta));
+ jit_meta_destroy(&func->meta);
jit_type_free(func->signature);
- jit_free(func);
+
+ jit_mutex_lock(&context->cache_lock);
+ _jit_cache_free_function(context->cache, func);
+ jit_mutex_unlock(&context->cache_lock);
}
/*@