]> git.unchartedbackwaters.co.uk Git - francis/libjit.git/commitdiff
tweak code cache API
authorAleksey Demakov <ademakov@gmail.com>
Wed, 3 Oct 2012 23:19:12 +0000 (03:19 +0400)
committerAleksey Demakov <ademakov@gmail.com>
Wed, 3 Oct 2012 23:19:12 +0000 (03:19 +0400)
ChangeLog
jit/jit-cache.c
jit/jit-cache.h
jit/jit-compile.c

index 5f3b432b74f2d85c82a2b5a8436889bf10d6bae6..036b35d0f54214bda2d655a96f0a97972791bc31 100644 (file)
--- a/ChangeLog
+++ b/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)
index deaedd8072e99d7801a5d3c0fdf8e3a0f032a4e0..5ab3cabed5457f36366c6c00b483ff41cb5b1c7f 100644 (file)
@@ -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 *
index 13dfd380260ef934339a3a38ae64a5e3d988c688..016f004a684e82c2b2338170dc3af9b84305efd6 100644 (file)
@@ -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
index 6eb610d586227a44e484060a962caa939a555e88..3c648c9d203f7be4a8e0d14fa5375d8ecac4cbcb 100644 (file)
@@ -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 */