]> git.unchartedbackwaters.co.uk Git - francis/libjit.git/commitdiff
Refactor function cache allocation API.
authorAleksey Demakov <ademakov@gmail.com>
Sun, 29 Jul 2012 07:01:29 +0000 (11:01 +0400)
committerAleksey Demakov <ademakov@gmail.com>
Sun, 29 Jul 2012 07:01:29 +0000 (11:01 +0400)
Merge branch 'master' into cache-refactoring

Conflicts:
ChangeLog

18 files changed:
1  2 
ChangeLog
jit/jit-cache.c
jit/jit-cache.h
jit/jit-compile.c
jit/jit-dump.c
jit/jit-internal.h
jit/jit-reg-alloc.c
jit/jit-rules-alpha.c
jit/jit-rules-arm.c
jit/jit-rules-arm.ins
jit/jit-rules-interp.c
jit/jit-rules-x86-64.c
jit/jit-rules-x86-64.ins
jit/jit-rules-x86.c
jit/jit-rules-x86.ins
jit/jit-rules.c
jit/jit-rules.h
tools/gen-rules-parser.y

diff --cc ChangeLog
index 4a3be53a0992e3738ce760a8df5e8218ccae378d,468b5a1f701101ffd3b03c5637ce9fbe5c35f133..ff44f8ae56ae599404eedc2e17caeae852f715dc
+++ b/ChangeLog
@@@ -1,41 -1,15 +1,67 @@@
++2012-07-29  Aleksey Demakov  <ademakov@gmail.com>
++
++      * 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  <ademakov@gmail.com>
 +
 +      * 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  <ktreichel@web.de>
+       * 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  <ademakov@gmail.com>
 +
 +      * 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  <ademakov@gmail.com>
  
        * jit/Makefile.am:
diff --cc jit/jit-cache.c
index afda4f882586b8a3aef16d1efa23765211328d3a,bf2ceefea91155357a31759024973e8f4086b9b1..e813a15524fc834f75e685afedf4cf861706b4d7
@@@ -82,15 -99,202 +82,39 @@@ 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 */
--      unsigned char           *start;         /* Start of the current method */
 -      unsigned char           debugData[JIT_CACHE_DEBUG_SIZE];
 -      int                     debugLen;       /* Length of temporary debug data */
 -      jit_cache_debug_t       firstDebug;     /* First debug block for method */
 -      jit_cache_debug_t       lastDebug;      /* Last debug block for method */
 -
  };
  
 - * 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".
+ /*
 -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;
++ * Get or set the sub-trees of a node.
+  */
 - * Uncompress a value that was compressed by "CompressInt".
++#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))
+ /*
 -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;
 -      }
 -}
++ * 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)))
  /*
   * Allocate a cache page and add it to the cache.
   */
@@@ -151,8 -355,8 +175,8 @@@ static void AllocCachePage(jit_cache_t 
                {
                        jit_free_exec(ptr, cache->pageSize * factor);
                failAlloc:
--                      cache->freeStart = 0;
--                      cache->freeEnd = 0;
++                      cache->free_start = 0;
++                      cache->free_end = 0;
                        return;
                }
  
        }
  
        /* 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))
        {
        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;
        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;
        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;
                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);
--      cache->start = 0;
 -      cache->debugLen = 0;
 -      cache->firstDebug = 0;
 -      cache->lastDebug = 0;
  
        /* Allocate the initial cache page */
        AllocCachePage(cache, 0);
--      if(!cache->freeStart)
++      if(!cache->free_start)
        {
                _jit_cache_destroy(cache);
                return 0;
        return cache;
  }
  
--void _jit_cache_destroy(jit_cache_t cache)
++void
++_jit_cache_destroy(jit_cache_t cache)
  {
        unsigned long page;
  
        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_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)
 -                          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;
  
--      /* Store the method start address */
--      cache->start = posn->ptr;
 -
 -      /* Clear the debug data */
 -      cache->debugLen = 0;
 -      cache->firstDebug = 0;
 -      cache->lastDebug = 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))))
 -              method->end = posn->ptr;
 -              do
--              {
-                       --(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->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 3cfa557dbd0c6c3face764168b9962fd1d44e855,ea04bee375a49cd4c34d30ea0426aae6d68eeba2..8c853c2daea1cfa1893ae99ec415e84946557970
@@@ -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
index 3a4d3b22ef6a90dbdae9bc9348502a6b26571575,9246172931e601a96d631b64f91564dfa4e04b3b..6eb610d586227a44e484060a962caa939a555e88
@@@ -37,7 -37,7 +37,6 @@@ typedef struc
  {
        jit_function_t          func;
  
--      jit_cache_t             cache;
        int                     cache_locked;
        int                     cache_started;
  
@@@ -152,23 -152,6 +151,23 @@@ jit_optimize(jit_function_t func
        return JIT_RESULT_OK;
  }
  
-       unsigned long native_offset = gen->posn.ptr - func->start;
 +/*
 + * 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->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.
   */
@@@ -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);
                }
  
  #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);
        }
@@@ -415,89 -400,38 +414,82 @@@ cache_release(_jit_compile_t *state
        }
  }
  
-  * Allocate some space in the code cache.
 +/*
- cache_alloc(_jit_compile_t *state)
++ * 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
-       int result;
++cache_align(_jit_compile_t *state, int align, int diff, int nop)
 +{
-       /* 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)
++      jit_nuint p, n;
 +
-               /* 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);
++      /* Adjust the required alignment */
++      if(align < 1)
 +      {
-       if(result != JIT_CACHE_OK)
++              align = 1;
 +      }
-               /* Failed to allocate any cache space */
-               jit_exception_builtin(JIT_RESULT_OUT_OF_MEMORY);
++
++      /* 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)
 +      {
-       /* Prepare the bytecode offset encoder */
-       _jit_varint_init_encoder(&state->gen.offset_encoder);
++              return;
 +      }
 +
-       /* On success remember the cache state */
-       state->cache_started = 1;
++      /* Determine the actual alignment */
++      align = (int) (n - p);
 +
- #if NOT_USED
++      /* 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
 +}
 +
  /*
-  * 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);
        }
-       /* Detect overflow of the free memory region */
-       if(next > ((jit_nuint)(posn->limit)))
-       {
-               posn->ptr = posn->limit;
-               return;
-       }
++      state->gen.ptr = _jit_cache_get_code_break(state->gen.cache);
++      state->gen.limit = _jit_cache_get_code_limit(state->gen.cache); 
 +
- #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
++      /* Align the function code. */
++      cache_align(state, JIT_FUNCTION_ALIGNMENT, JIT_FUNCTION_ALIGNMENT, 0);
 +
++      /* 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->page_factor *= 2;
++      state->gen.ptr = _jit_cache_get_code_break(state->gen.cache);
++      state->gen.limit = _jit_cache_get_code_limit(state->gen.cache);
 +
++      /* 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 */
  
                /* 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;
  }
-       start = func->start;
 +
 +#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->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 5e9cb0ab4125ff2b5bf065a6882876fe6079e526,de6ac290bf5426caf0983afd644398d92e895245..c3a87f10cf5a041c014cc2b8c9e75c3d8b311f52
@@@ -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
        }
  
index b6cb2bbf8268f49aaad11ced325ce17d36db06ae,911348e9ae6f0ecc58f0a3dca1a51f623889ca20..da59e4cbae674560a85dc63a8a130c9864001cac
@@@ -108,6 -103,6 +108,11 @@@ _JIT_ALIGN_CHECK_TYPE(jit_nfloat, nfloa
  #define       JIT_ALIGN_NFLOAT                _JIT_ALIGN_FOR_TYPE(nfloat)
  #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.
   */
@@@ -454,11 -443,6 +459,11 @@@ struct _jit_functio
        /* Flag set once the function is compiled */
        int volatile            is_compiled;
  
-       unsigned char           *start;
 +      /* Start of the cache region */
-       unsigned char           *end;
++      unsigned char           *code_start;
 +      /* End of the cache region */
++      unsigned char           *code_end;
 +
        /* The entry point for the function's compiled code */
        void * volatile         entry_point;
  
index b6a8cdfc70cfa8a7a909b9e05cab21beb49e417f,b6a8cdfc70cfa8a7a909b9e05cab21beb49e417f..41ae7dd7b76fda48267adb402e43daeb4cda9956
@@@ -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);
  }
index 2836c4aa93626e808b6d2cde9e47f7f5d9dea442,2836c4aa93626e808b6d2cde9e47f7f5d9dea442..edd1e7cdc94c862c2db35ac51e0abcbcafe5353b
@@@ -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);
                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 */
index cfe3930cf2b4cda1ccae56bfa1615b97fba67ee4,cfe3930cf2b4cda1ccae56bfa1615b97fba67ee4..21e12c59a1c74d5a30aabed50ae0b5c4327c6392
@@@ -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)
  
  /*
   */
  #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);
index 1590dde0ade30bfdc89cbf133f61860651975d7a,1590dde0ade30bfdc89cbf133f61860651975d7a..b5a866a12799ee2cddd1fa4d31c14a495c60c01c
@@@ -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,
index 33d56798a2ba1165a5286ee17b1f37a6d55d3d06,7cccde30aca28add5fc15690f716f6d27c4894ac..c3714d0a78fdab2f487e8db7e58a82fda9188b80
@@@ -184,32 -184,22 +184,32 @@@ generation is complete
  
  @*/
  
- #define jit_cache_native(posn,value)                                  \
 +/*
 + * Output a native word to the current method.
 + */
-               _jit_cache_check_space((posn), sizeof(jit_nuint));      \
-               *((jit_nuint *)((posn)->ptr)) = (jit_nuint)(value);     \
-               (posn)->ptr += sizeof(jit_nuint);                       \
++#define jit_cache_native(gen,value)                                   \
 +      do {                                                            \
++              _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:
                        {
                                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;
                        }
                        {
                                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;
                        }
  
                        {
                                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;
                        }
  
                        {
                                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;
                        }
                }
                        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)
                {
                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;
                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]);
                        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;
                        }
                }
                {
                        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);
        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;
  
        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:
        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;
  
                _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;
        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;
  
  
        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:
        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:
                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;
                }
                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:
                _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;
        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;
  
                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;
  
                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;
  
                /* 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:
                /* 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;
  
                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:
                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:
                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:
                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
  
        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:
                {
                        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);
index 155d201ace419957447362758354562f9857bde7,155d201ace419957447362758354562f9857bde7..235f93b89d88c0a87c38a31671433e378b0341a9
@@@ -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;
        }
        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);
                                        {
                                                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);
                                        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));
                                        {
                                                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);
        /* 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);
index 34c87ffdafa6c84b0b853c977c8e107d487690e5,34c87ffdafa6c84b0b853c977c8e107d487690e5..faca68e637f54dbf3054bdb12618cb8bea533111
@@@ -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 */
index eb9739e0fc4dec5287855bd5fdc760cd5ff29dc0,eb9739e0fc4dec5287855bd5fdc760cd5ff29dc0..5955367cc9a95fa6cf61f5ff4192631190652cff
@@@ -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 */
  #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)
        {
        {
                x86_ret(inst);
        }
--      gen->posn.ptr = inst;
++      gen->ptr = inst;
  }
  
  #if 0
  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
   * 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);
                                        }
                                        }
                                        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);
                                        }
                                        }
                                        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);
index 326cbf9067482bdb2a3b047d51efed5e229643a8,326cbf9067482bdb2a3b047d51efed5e229643a8..363304bf144768b8355d1a4170d0fc49af4b8849
@@@ -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)
                {
                {
                        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 20e01a13c311c39fb8b92bcfcad92303273180ec,20e01a13c311c39fb8b92bcfcad92303273180ec..32f5a10c3c00bd90e2f06bc5526a2fd25f913ced
@@@ -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 4ff23f40c5742308cce4a567da9350f28c0a3979,67909ffa5d331c411dc1bbf3b37967e859372f6a..6af7e87f34da307f16716398b4647d9be8225d3c
@@@ -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);
index 56704d7607af5523ceb2377f91f87b16530f5e4e,56704d7607af5523ceb2377f91f87b16530f5e4e..5202677519fdf08ad3651bf7246382a353500d20
@@@ -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)
                        {
                        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;
                }
                else
                {
--                      printf("\t\tgen->posn.ptr = (unsigned char *)inst;\n");
++                      printf("\t\tgen->ptr = (unsigned char *)inst;\n");
                }
                if(contains_registers)
                {