dotgnu-pnet-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[dotgnu-pnet-commits] [SCM] DotGNU Portable.NET Just In Time compiler (l


From: Aleksey Demakov
Subject: [dotgnu-pnet-commits] [SCM] DotGNU Portable.NET Just In Time compiler (libjit) branch, cache-refactoring, updated. a2a60671b99b64e42dbc1e2b25a311a1c40b8a4c
Date: Sun, 29 Jul 2012 07:02:57 +0000

This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "DotGNU Portable.NET Just In Time compiler (libjit)".

The branch, cache-refactoring has been updated
       via  a2a60671b99b64e42dbc1e2b25a311a1c40b8a4c (commit)
       via  57f61f53ca17b46754e5370b308807bbf2791b98 (commit)
      from  e332897e9b53e3796185f21df6b9e1c0a73fe996 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
http://git.savannah.gnu.org/cgit/libjit.git/commit/?id=a2a60671b99b64e42dbc1e2b25a311a1c40b8a4c

commit a2a60671b99b64e42dbc1e2b25a311a1c40b8a4c
Merge: e332897 57f61f5
Author: Aleksey Demakov <address@hidden>
Date:   Sun Jul 29 11:01:29 2012 +0400

    Refactor function cache allocation API.
    
    Merge branch 'master' into cache-refactoring
    
    Conflicts:
        ChangeLog

diff --cc ChangeLog
index 4a3be53,468b5a1..ff44f8a
--- a/ChangeLog
+++ b/ChangeLog
@@@ -1,41 -1,15 +1,67 @@@
++2012-07-29  Aleksey Demakov  <address@hidden>
++
++      * 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  <address@hidden>
 +
 +      * 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  <address@hidden>
+ 
+       * 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  <address@hidden>
 +
 +      * 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  <address@hidden>
  
        * jit/Makefile.am:
diff --cc jit/jit-cache.c
index afda4f8,bf2ceef..e813a15
--- a/jit/jit-cache.c
+++ b/jit/jit-cache.c
@@@ -82,16 -99,203 +82,40 @@@ 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 */
  };
  
  /*
 - * 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.
   */
  static void AllocCachePage(jit_cache_t cache, int factor)
@@@ -151,8 -355,8 +175,8 @@@
                {
                        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);
  
        /* 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_exception_builtin(JIT_RESULT_CACHE_FULL);
 -              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)
- {
-       unsigned char *ptr;
 -                          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;
  
        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))))
-               {
-                       --(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->end = posn->ptr;
 -              do
 -              {
 -                      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;
  
@@@ -153,23 -153,6 +152,23 @@@ jit_optimize(jit_function_t func
  }
  
  /*
 + * 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.
   */
  static void
@@@ -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);
        }
@@@ -416,88 -401,37 +415,81 @@@ 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
@@@ -109,6 -104,6 +109,11 @@@ _JIT_ALIGN_CHECK_TYPE(jit_nfloat, nfloa
  #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.
   */
  typedef struct jit_pool_block *jit_pool_block_t;
@@@ -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
@@@ -185,31 -185,21 +185,31 @@@ 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)
                {

-----------------------------------------------------------------------

Summary of changes:
 ChangeLog                                       |   26 ++
 config/jit-opcodes.ops                          |   17 +-
 include/jit/Makefile.am                         |    1 +
 include/jit/{jit-vmem.h => jit-opcode-compat.h} |   48 ++--
 jit/jit-cache.c                                 |  382 +++++++++++++----------
 jit/jit-cache.h                                 |   69 ++---
 jit/jit-compile.c                               |  157 +++++-----
 jit/jit-dump.c                                  |    4 +-
 jit/jit-internal.h                              |    9 +-
 jit/jit-reg-alloc.c                             |    2 +-
 jit/jit-rules-alpha.c                           |   22 +-
 jit/jit-rules-arm.c                             |   12 +-
 jit/jit-rules-arm.ins                           |    2 +-
 jit/jit-rules-interp.c                          |  209 ++++++-------
 jit/jit-rules-x86-64.c                          |   40 ++--
 jit/jit-rules-x86-64.ins                        |    3 +-
 jit/jit-rules-x86.c                             |   30 +-
 jit/jit-rules-x86.ins                           |   16 +-
 jit/jit-rules.c                                 |   25 ++
 jit/jit-rules.h                                 |   15 +-
 tools/gen-rules-parser.y                        |    6 +-
 21 files changed, 574 insertions(+), 521 deletions(-)
 copy include/jit/{jit-vmem.h => jit-opcode-compat.h} (53%)


hooks/post-receive
-- 
DotGNU Portable.NET Just In Time compiler (libjit)



reply via email to

[Prev in Thread] Current Thread [Next in Thread]