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

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

[dotgnu-pnet-commits] libjit ChangeLog include/jit/jit-context.h jit/...


From: Aleksey Demakov
Subject: [dotgnu-pnet-commits] libjit ChangeLog include/jit/jit-context.h jit/...
Date: Mon, 03 Mar 2008 14:49:07 +0000

CVSROOT:        /sources/dotgnu-pnet
Module name:    libjit
Changes by:     Aleksey Demakov <avd>   08/03/03 14:49:07

Modified files:
        .              : ChangeLog 
        include/jit    : jit-context.h 
        jit            : jit-cache.c jit-cache.h jit-context.c 
                         jit-function.c 

Log message:
        modify cache algorithm to allow a method to occupy more than one page

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/libjit/ChangeLog?cvsroot=dotgnu-pnet&r1=1.349&r2=1.350
http://cvs.savannah.gnu.org/viewcvs/libjit/include/jit/jit-context.h?cvsroot=dotgnu-pnet&r1=1.8&r2=1.9
http://cvs.savannah.gnu.org/viewcvs/libjit/jit/jit-cache.c?cvsroot=dotgnu-pnet&r1=1.6&r2=1.7
http://cvs.savannah.gnu.org/viewcvs/libjit/jit/jit-cache.h?cvsroot=dotgnu-pnet&r1=1.4&r2=1.5
http://cvs.savannah.gnu.org/viewcvs/libjit/jit/jit-context.c?cvsroot=dotgnu-pnet&r1=1.10&r2=1.11
http://cvs.savannah.gnu.org/viewcvs/libjit/jit/jit-function.c?cvsroot=dotgnu-pnet&r1=1.35&r2=1.36

Patches:
Index: ChangeLog
===================================================================
RCS file: /sources/dotgnu-pnet/libjit/ChangeLog,v
retrieving revision 1.349
retrieving revision 1.350
diff -u -b -r1.349 -r1.350
--- ChangeLog   2 Mar 2008 17:07:05 -0000       1.349
+++ ChangeLog   3 Mar 2008 14:49:06 -0000       1.350
@@ -1,3 +1,13 @@
+2008-03-03  Aleksey Demakov  <address@hidden>
+
+       * jit/jit-cache.h, jit/jit-cache.c, jit/jit-function.c (compile):
+       modify cache algorithm to allow a method to occupy more than one
+       cache page.
+
+       * include/jit/jit-context.h: add JIT_OPTION_CACHE_MAX_PAGE_FACTOR
+       option.
+       * jit/jit-context.c (_jit_context_get_cache): use that option.
+
 2008-03-02  Klaus Treichel  <address@hidden>
 
        * jit/jit-apply-x86-64.h: define the sizes for indirector and

Index: include/jit/jit-context.h
===================================================================
RCS file: /sources/dotgnu-pnet/libjit/include/jit/jit-context.h,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -b -r1.8 -r1.9
--- include/jit/jit-context.h   24 Jan 2008 20:12:49 -0000      1.8
+++ include/jit/jit-context.h   3 Mar 2008 14:49:06 -0000       1.9
@@ -53,6 +53,7 @@
 #define        JIT_OPTION_PRE_COMPILE          10002
 #define        JIT_OPTION_DONT_FOLD            10003
 #define JIT_OPTION_POSITION_INDEPENDENT        10004
+#define JIT_OPTION_CACHE_MAX_PAGE_FACTOR       10005
 
 #ifdef __cplusplus
 };

Index: jit/jit-cache.c
===================================================================
RCS file: /sources/dotgnu-pnet/libjit/jit/jit-cache.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -b -r1.6 -r1.7
--- jit/jit-cache.c     24 Jan 2008 20:12:51 -0000      1.6
+++ jit/jit-cache.c     3 Mar 2008 14:49:06 -0000       1.7
@@ -1,7 +1,7 @@
 /*
  * jit-cache.c - Translated function cache implementation.
  *
- * Copyright (C) 2002, 2003  Southern Storm Software, Pty Ltd.
+ * Copyright (C) 2002, 2003, 2008  Southern Storm Software, Pty Ltd.
  *
  * This file is part of the libjit library.
  *
@@ -34,11 +34,19 @@
 
 /*
  * Tune the default size of a cache page.  Memory is allocated from
- * the system in chunks of this size.  This will also determine
- * the maximum method size that can be translated.
+ * the system in chunks of this size.
  */
 #ifndef        JIT_CACHE_PAGE_SIZE
-#define        JIT_CACHE_PAGE_SIZE             (128 * 1024)
+#define        JIT_CACHE_PAGE_SIZE             (64 * 1024)
+#endif
+
+/*
+ * Tune the maximum size of a cache page.  The size of a page might be
+ * up to (JIT_CACHE_PAGE_SIZE * JIT_CACHE_MAX_PAGE_FACTOR).  This will
+ * also determine the maximum method size that can be translated.
+ */
+#ifndef JIT_CACHE_MAX_PAGE_FACTOR
+#define JIT_CACHE_MAX_PAGE_FACTOR      1024
 #endif
 
 /*
@@ -72,18 +80,27 @@
 };
 
 /*
+ * Structure of the page list entry.
+ */
+struct jit_cache_page
+{
+       void                    *page;          /* Page memory */
+       long                    factor;         /* Page size factor */
+};
+
+/*
  * Structure of the method cache.
  */
 #define        JIT_CACHE_DEBUG_SIZE            64
 struct jit_cache
 {
-       void                **pages;            /* List of pages currently in 
the cache */
+       struct jit_cache_page   *pages;         /* List of pages currently in 
the cache */
        unsigned long     numPages;             /* Number of pages currently in 
the cache */
-       unsigned long     pageSize;             /* Size of a page for 
allocation */
+       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 */
-       int                               outOfMemory;  /* True when cache is 
out of memory */
-       int                               needRestart;  /* True when page 
restart is required */
        long                      pagesLeft;    /* Number of pages left to 
allocate */
        jit_cache_method_t method;              /* Information for the current 
method */
        struct jit_cache_method head;   /* Head of the lookup tree */
@@ -281,19 +298,32 @@
 /*
  * Allocate a cache page and add it to the cache.
  */
-static void AllocCachePage(jit_cache_t cache)
+static void AllocCachePage(jit_cache_t cache, int factor)
 {
-       void *ptr;
-       void **list;
+       long num;
+       unsigned char *ptr;
+       struct jit_cache_page *list;
+
+       /* The minimum page factor is 1 */
+       if(factor <= 0)
+       {
+               factor = 1;
+       }
+
+       /* If too big a page is requested, then bail out */
+       if(((unsigned int) factor) > cache->maxPageFactor)
+       {
+               goto failAlloc;
+       }
 
-       /* If we are already out of memory, then bail out */
-       if(cache->outOfMemory || !(cache->pagesLeft))
+       /* If the page limit is hit, then bail out */
+       if(cache->pagesLeft >= 0 && cache->pagesLeft < factor)
        {
                goto failAlloc;
        }
 
        /* Try to allocate a physical page */
-       ptr = jit_malloc_exec((unsigned int)(cache->pageSize));
+       ptr = (unsigned char *) jit_malloc_exec((unsigned int) cache->pageSize 
* factor);
        if(!ptr)
        {
                goto failAlloc;
@@ -304,29 +334,48 @@
           have to "touch" the pages to free them.  Touching the pages
           may cause them to be swapped in if they are currently out.
           There's no point doing that if we are trying to free them */
-       list = (void **)jit_realloc
-               (cache->pages, sizeof(void *) * (cache->numPages + 1));
+       if(cache->numPages == cache->maxNumPages)
+       {
+               if(cache->numPages == 0)
+               {
+                       num = 16;
+               }
+               else
+               {
+                       num = cache->numPages * 2;
+               }
+               if(cache->pagesLeft > 0 && num > (cache->numPages + 
cache->pagesLeft - factor + 1))
+               {
+                       num = cache->numPages + cache->pagesLeft - factor + 1;
+               }
+
+               list = (struct jit_cache_page *) jit_realloc(cache->pages,
+                                                            sizeof(struct 
jit_cache_page) * num);
        if(!list)
        {
-               jit_free_exec(ptr, cache->pageSize);
+                       jit_free_exec(ptr, cache->pageSize * factor);
        failAlloc:
-               cache->outOfMemory = 1;
                cache->freeStart = 0;
                cache->freeEnd = 0;
                return;
        }
+
+               cache->maxNumPages = num;
        cache->pages = list;
-       list[(cache->numPages)++] = ptr;
+       }
+       cache->pages[cache->numPages].page = ptr;
+       cache->pages[cache->numPages].factor = factor;
+       ++(cache->numPages);
 
-       /* One less page before we hit the limit */
+       /* Adjust te number of pages left before we hit the limit */
        if(cache->pagesLeft > 0)
        {
-               --(cache->pagesLeft);
+               cache->pagesLeft -= factor;
        }
 
        /* Set up the working region within the new page */
        cache->freeStart = ptr;
-       cache->freeEnd = (void *)(((char *)ptr) + (int)(cache->pageSize));
+       cache->freeEnd = ptr + (int) cache->pageSize * factor;
 }
 
 /*
@@ -569,10 +618,10 @@
        }
 }
 
-jit_cache_t _jit_cache_create(long limit, long cache_page_size)
+jit_cache_t _jit_cache_create(long limit, long cache_page_size, int 
max_page_factor)
 {
        jit_cache_t cache;
-       unsigned long size;
+       unsigned long exec_page_size;
 
        /* Allocate space for the cache control structure */
        if((cache = (jit_cache_t )jit_malloc(sizeof(struct jit_cache))) == 0)
@@ -580,27 +629,38 @@
                return 0;
        }
 
-       /* Initialize the rest of the cache fields */
-       cache->pages = 0;
-       cache->numPages = 0;
-       size = jit_exec_page_size();
-       if(!cache_page_size)
+       /* determine the default cache page size */
+       exec_page_size = jit_exec_page_size();
+       if(cache_page_size <= 0)
        {
                cache_page_size = JIT_CACHE_PAGE_SIZE;
        }
-       size = (cache_page_size / size) * size;
-       if(!size)
+       if(cache_page_size < exec_page_size)
        {
-               size = jit_exec_page_size();
+               cache_page_size = exec_page_size;
        }
-       cache->pageSize = size;
+       else
+       {
+               cache_page_size = (cache_page_size / exec_page_size) * 
exec_page_size;
+       }
+
+       /* determine the maximum page size factor */
+       if(max_page_factor <= 0)
+       {
+               max_page_factor = JIT_CACHE_MAX_PAGE_FACTOR;
+       }
+
+       /* Initialize the rest of the cache fields */
+       cache->pages = 0;
+       cache->numPages = 0;
+       cache->maxNumPages = 0;
+       cache->pageSize = cache_page_size;
+       cache->maxPageFactor = max_page_factor;
        cache->freeStart = 0;
        cache->freeEnd = 0;
-       cache->outOfMemory = 0;
-       cache->needRestart = 0;
        if(limit > 0)
        {
-               cache->pagesLeft = limit / size;
+               cache->pagesLeft = limit / cache_page_size;
                if(cache->pagesLeft < 1)
                {
                        cache->pagesLeft = 1;
@@ -631,8 +691,8 @@
        cache->lastDebug = 0;
 
        /* Allocate the initial cache page */
-       AllocCachePage(cache);
-       if(cache->outOfMemory)
+       AllocCachePage(cache, 0);
+       if(!cache->freeStart)
        {
                _jit_cache_destroy(cache);
                return 0;
@@ -649,7 +709,8 @@
        /* Free all of the cache pages */
        for(page = 0; page < cache->numPages; ++page)
        {
-               jit_free_exec(cache->pages[page], cache->pageSize);
+               jit_free_exec(cache->pages[page].page,
+                             cache->pageSize * cache->pages[page].factor);
        }
        if(cache->pages)
        {
@@ -662,25 +723,27 @@
 
 int _jit_cache_is_full(jit_cache_t cache, jit_cache_posn *posn)
 {
-       return (cache->outOfMemory || (posn && posn->ptr >= posn->limit));
+       return (!cache->freeStart || (posn && posn->ptr >= posn->limit));
 }
 
-void *_jit_cache_start_method(jit_cache_t cache, jit_cache_posn *posn,
-                                                 int align, void *method)
+int _jit_cache_start_method(jit_cache_t cache,
+                           jit_cache_posn *posn,
+                           int page_factor,
+                           int align,
+                           void *method)
 {
-       jit_nuint temp;
+       unsigned char *ptr;
 
        /* Do we need to allocate a new cache page? */
-       if(cache->needRestart)
+       if(page_factor > 0)
        {
-               cache->needRestart = 0;
-               AllocCachePage(cache);
+               AllocCachePage(cache, page_factor);
        }
 
        /* Bail out if the cache is already full */
-       if(cache->outOfMemory)
+       if(!cache->freeStart)
        {
-               return 0;
+               return JIT_CACHE_TOO_BIG;
        }
 
        /* Set up the initial cache position */
@@ -689,40 +752,32 @@
        posn->limit = cache->freeEnd;
 
        /* Align the method start */
-       if(align <= 1)
+       ptr = posn->ptr;
+       if(align > 1)
        {
-               align = 1;
+               ptr = (unsigned char *)(((jit_nuint) (ptr + align - 1)) & 
~((jit_nuint) (align - 1)));
        }
-       temp = (((jit_nuint)(posn->ptr)) + ((jit_nuint)align) - 1) &
-                  ~(((jit_nuint)align) - 1);
-       if(((unsigned char *)temp) >= posn->limit)
-       {
-               /* There is insufficient space in this page, so create a new 
one */
-               AllocCachePage(cache);
-               if(cache->outOfMemory)
+       if(ptr >= posn->limit)
                {
-                       return 0;
-               }
-
-               /* Set up the cache position again and align it */
-               posn->ptr = cache->freeStart;
-               posn->limit = cache->freeEnd;
-               temp = (((jit_nuint)(posn->ptr)) + ((jit_nuint)align) - 1) &
-                          ~(((jit_nuint)align) - 1);
+               /* There is insufficient space in this page */
+               posn->ptr = posn->limit;
+               return JIT_CACHE_RESTART;
        }
 #ifdef jit_should_pad
-       if(temp > (jit_nuint)(posn->ptr))
+       if(ptr > posn->ptr)
        {
-               _jit_pad_buffer(posn->ptr, (int)(((jit_nuint)(posn->ptr)) - 
temp));
+               _jit_pad_buffer(posn->ptr, ptr - posn->ptr);
        }
 #endif
-       posn->ptr = (unsigned char *)temp;
+       posn->ptr = ptr;
 
        /* Allocate memory for the method information block */
-       cache->method = (jit_cache_method_t)
-               _jit_cache_alloc(posn, sizeof(struct jit_cache_method));
-       if(cache->method)
+       cache->method = (jit_cache_method_t) _jit_cache_alloc(posn, 
sizeof(struct jit_cache_method));
+       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;
@@ -730,7 +785,8 @@
                cache->method->debug = 0;
                cache->method->left = 0;
                cache->method->right = 0;
-       }
+
+       /* Store the method start address */
        cache->start = posn->ptr;
 
        /* Clear the debug data */
@@ -738,8 +794,7 @@
        cache->firstDebug = 0;
        cache->lastDebug = 0;
 
-       /* Return the method entry point to the caller */
-       return (void *)(posn->ptr);
+       return JIT_CACHE_OK;
 }
 
 int _jit_cache_end_method(jit_cache_posn *posn)
@@ -751,20 +806,23 @@
        /* Determine if we ran out of space while writing the method */
        if(posn->ptr >= posn->limit)
        {
-               /* Determine if the method was too big, or we need a restart.
-                  The method is judged to be too big if we had a new page and
-                  yet it was insufficent to hold the method */
-               if(cache->freeStart ==
-                               ((unsigned char *)(cache->pages[cache->numPages 
- 1])) &&
-                  cache->freeEnd == (cache->freeStart + cache->pageSize))
+               /* 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)
                {
-                       return JIT_CACHE_END_TOO_BIG;
+                               cache->pagesLeft += 
cache->pages[cache->numPages].factor;
                }
-               else
-               {
-                       cache->needRestart = 1;
-                       return JIT_CACHE_END_RESTART;
+                       cache->freeStart = 0;
+                       cache->freeEnd = 0;
                }
+               return JIT_CACHE_RESTART;
        }
 
        /* Terminate the debug information and flush it */
@@ -799,7 +857,7 @@
        }
 
        /* The method is ready to go */
-       return JIT_CACHE_END_OK;
+       return JIT_CACHE_OK;
 }
 
 void *_jit_cache_alloc(jit_cache_posn *posn, unsigned long size)
@@ -838,7 +896,7 @@
        /* Bail out if the request is too big to ever be satisfiable */
        if(size > (unsigned long)(cache->freeEnd - cache->freeStart))
        {
-               AllocCachePage(cache);
+               AllocCachePage(cache, 0);
                if(size > (unsigned long)(cache->freeEnd - cache->freeStart))
                {
                        return 0;
@@ -1371,9 +1429,17 @@
 To output the code for a method, first call _jit_cache_start_method:
 
        jit_cache_posn posn;
-       void *start;
+       int result;
+
+       result = _jit_cache_start_method(cache, &posn, factor,
+                                        METHOD_ALIGNMENT, method);
 
-       start = _jit_cache_start_method(cache, &posn, METHOD_ALIGNMENT, method);
+"factor" is used to control cache space allocation for the method.
+The cache space is allocated by pages.  The value 0 indicates that
+the method has to use the space left after the last allocation.
+The value 1 or more indicates that the method has to start on a
+newly allocated space that must contain the specified number of
+consecutive pages.
 
 "METHOD_ALIGNMENT" is used to align the start of the method on an
 appropriate boundary for the target CPU.  Use the value 1 if no
@@ -1383,9 +1449,21 @@
 "method" is a value that uniquely identifies the method that is being
 translated.  Usually this is the "jit_function_t" pointer.
 
-The function initializes the "posn" structure, and returns the starting
-address for the method.  If the function returns NULL, then it indicates
-that the cache is full and further method translation is not possible.
+The function initializes the "posn" structure to point to the start
+and end of the space available for the method output.  The function
+returns one of three result codes:
+
+       JIT_CACHE_OK       The function call was successful.
+       JIT_CACHE_RESTART  The cache does not currently have enough
+                          space to fit any method.  This code may
+                          only be returned if the "factor" value
+                          was 0.  In this case it is necessary to
+                          restart the method output process by
+                          calling _jit_cache_start_method again
+                          with a bigger "factor" value.
+       JIT_CACHE_TOO_BIG  The cache does not have any space left
+                          for allocation.  In this case a restart
+                          won't help.
 
 To write code to the method, use the following:
 
@@ -1396,7 +1474,7 @@
        jit_cache_word64(&posn, value);
 
 These macros write the value to cache and then update the current
-position.  If the macros detect the end of the current cache page,
+position.  If the macros detect the end of the avaialable space,
 they will flag overflow, but otherwise do nothing (overflow is
 flagged when posn->ptr == posn->limit).  The current position
 in the method can be obtained using "jit_cache_get_posn".
@@ -1405,14 +1483,13 @@
 This can be achieved using _jit_cache_align.
 
 Once the method code has been output, call _jit_cache_end_method to finalize
-the process.  This function returns one of three result codes:
+the process.  This function returns one of two result codes:
 
-       JIT_CACHE_END_OK       The translation process was successful.
-       JIT_CACHE_END_RESTART  The cache page overflowed.  It is necessary
-                              to restart the translation process from
-                              the beginning (_jit_cache_start_method).
-       JIT_CACHE_END_TOO_BIG  The cache page overflowed, but the method
-                              is too big to fit and a restart won't help.
+       JIT_CACHE_OK       The method output process was successful.
+       JIT_CACHE_RESTART  The cache space overflowed. It is necessary
+                          to restart the method output process by
+                          calling _jit_cache_start_method again
+                          with a bigger "factor" value.
 
 The caller should repeatedly translate the method while _jit_cache_end_method
 continues to return JIT_CACHE_END_RESTART.  Normally there will be no
@@ -1424,7 +1501,7 @@
 --------------------
 
 The cache consists of one or more "cache pages", which contain method
-code and auxillary data.  The default size for a cache page is 128k
+code and auxillary data.  The default size for a cache page is 64k
 (JIT_CACHE_PAGE_SIZE).  The size is adjusted to be a multiple
 of the system page size (usually 4k), and then stored in "pageSize".
 
@@ -1433,9 +1510,10 @@
 starting at the top of the page, and growing downwards.  When the two
 regions meet, a new cache page is allocated and the process restarts.
 
-No method, plus its auxillary data, can be greater in size than one
-cache page.  The default should be sufficient for normal applications,
-but is easy to increase should the need arise.
+To allow methods bigger than a single cache page it is possible to
+allocate a block of consecutive pages as a single unit. The method
+code and auxillary data is written to such a multiple-page block in
+the same manner as into an ordinary page.
 
 Each method has one or more jit_cache_method auxillary data blocks associated
 with it.  These blocks indicate the start and end of regions within the

Index: jit/jit-cache.h
===================================================================
RCS file: /sources/dotgnu-pnet/libjit/jit/jit-cache.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -b -r1.4 -r1.5
--- jit/jit-cache.h     24 Jan 2008 20:12:51 -0000      1.4
+++ jit/jit-cache.h     3 Mar 2008 14:49:06 -0000       1.5
@@ -1,7 +1,7 @@
 /*
  * jit-cache.h - Translated method cache implementation.
  *
- * Copyright (C) 2002, 2004  Southern Storm Software, Pty Ltd.
+ * Copyright (C) 2002, 2004, 2008  Southern Storm Software, Pty Ltd.
  *
  * This file is part of the libjit library.
  *
@@ -47,9 +47,14 @@
  * Create a method cache.  Returns NULL if out of memory.
  * If "limit" is non-zero, then it specifies the maximum
  * size of the cache in bytes.  If "cache_page_size" is
- * non-zero, then it indicates the size of each cache page.
- */
-jit_cache_t _jit_cache_create(long limit, long cache_page_size);
+ * non-zero, then it indicates the dafault/minimum cache
+ * page size.  If "max_page_factor" is not zero, then it
+ * indicates the maximum cache page size as multiple of
+ * "max_page_factor" and "cache_page_size".
+ */
+jit_cache_t _jit_cache_create(long limit,
+                             long cache_page_size,
+                             int max_page_factor);
 
 /*
  * Destroy a method cache.
@@ -63,21 +68,29 @@
 int _jit_cache_is_full(jit_cache_t cache, jit_cache_posn *posn);
 
 /*
+ * Return values for "_jit_cache_start_method" and "_jit_cache_end_method".
+ */
+#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 */
+
+/*
  * 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.
  */
-void *_jit_cache_start_method(jit_cache_t cache, jit_cache_posn *posn,
-                                                 int align, void *cookie);
-
-/*
- * Return values for "_jit_cache_end_method".
- */
-#define        JIT_CACHE_END_OK                0               /* Function is 
OK */
-#define        JIT_CACHE_END_RESTART   1               /* Restart is required 
*/
-#define        JIT_CACHE_END_TOO_BIG   2               /* Function is too big 
for the cache */
+int _jit_cache_start_method(jit_cache_t cache,
+                           jit_cache_posn *posn,
+                           int page_factor,
+                           int align,
+                           void *cookie);
 
 /*
  * End output of a method.  Returns zero if a restart.

Index: jit/jit-context.c
===================================================================
RCS file: /sources/dotgnu-pnet/libjit/jit/jit-context.c,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -b -r1.10 -r1.11
--- jit/jit-context.c   24 Jan 2008 20:12:51 -0000      1.10
+++ jit/jit-context.c   3 Mar 2008 14:49:06 -0000       1.11
@@ -330,7 +330,9 @@
                        ((long)jit_context_get_meta_numeric
                                (context, JIT_OPTION_CACHE_LIMIT),
                         (long)jit_context_get_meta_numeric
-                               (context, JIT_OPTION_CACHE_PAGE_SIZE));
+                               (context, JIT_OPTION_CACHE_PAGE_SIZE),
+                        (int)jit_context_get_meta_numeric
+                               (context, JIT_OPTION_CACHE_MAX_PAGE_FACTOR));
        }
        return context->cache;
 }

Index: jit/jit-function.c
===================================================================
RCS file: /sources/dotgnu-pnet/libjit/jit/jit-function.c,v
retrieving revision 1.35
retrieving revision 1.36
diff -u -b -r1.35 -r1.36
--- jit/jit-function.c  24 Jan 2008 20:12:51 -0000      1.35
+++ jit/jit-function.c  3 Mar 2008 14:49:07 -0000       1.36
@@ -1,7 +1,7 @@
 /*
  * jit-function.c - Functions for manipulating function blocks.
  *
- * Copyright (C) 2004  Southern Storm Software, Pty Ltd.
+ * Copyright (C) 2004, 2006-2008  Southern Storm Software, Pty Ltd.
  *
  * This file is part of the libjit library.
  *
@@ -511,16 +511,6 @@
                printf("Start of binary code: 0x%08x\n", p1);
 #endif
 
-               /* The cache is full. */
-               if(!jit_cache_check_for_n(&gen->posn, 1))
-               {
-#ifdef _JIT_COMPILE_DEBUG
-                       printf("No space left in the code cache.\n\n");
-                       fflush(stdout);
-#endif
-                       return;
-               }
-
                switch(insn->opcode)
                {
                        case JIT_OP_NOP:                break;          /* 
Ignore NOP's */
@@ -649,10 +639,6 @@
        jit_insn_iter_t iter;
        jit_insn_t insn;
 
-#ifdef _JIT_COMPILE_DEBUG
-       printf("\n*** Restart compilation ***\n\n");
-#endif
-
        block = 0;
        while((block = jit_block_next(func, block)) != 0)
        {
@@ -714,27 +700,27 @@
 {
        struct jit_gencode gen;
        jit_cache_t cache;
-       void *start;
-       void *end;
+       unsigned char *start;
+       unsigned char *end;
        jit_block_t block;
+       int page_factor;
        int result;
-#ifdef JIT_PROLOG_SIZE
-       int have_prolog;
-#endif
 
-       /* We need the cache lock while we are compiling the function */
-       jit_mutex_lock(&(func->context->cache_lock));
+       /* Initialize the code generation state */
+       jit_memzero(&gen, sizeof(gen));
+       page_factor = 0;
+       start = 0;
+       end = 0;
 
-       /* Get the method cache */
-       cache = _jit_context_get_cache(func->context);
-       if(!cache)
+       /* Intuit "nothrow" and "noreturn" flags for this function */
+       if(!(func->builder->may_throw))
        {
-               jit_mutex_unlock(&(func->context->cache_lock));
-               return 0;
+               func->no_throw = 1;
+       }
+       if(!(func->builder->ordinary_return))
+       {
+               func->no_return = 1;
        }
-
-       /* Initialize the code generation state */
-       jit_memzero(&gen, sizeof(gen));
 
        /* Compute liveness and "next use" information for this function */
        _jit_function_compute_liveness(func);
@@ -744,29 +730,45 @@
        _jit_regs_alloc_global(&gen, func);
 #endif
 
-       /* We may need to perform output twice, if the first attempt fails
-          due to a lack of space in the current method cache page */
-       do
-       {
+       /* We need the cache lock while we are compiling the function */
+       jit_mutex_lock(&(func->context->cache_lock));
+
 #ifdef _JIT_COMPILE_DEBUG
                printf("\n*** Start compilation ***\n\n");
                func->builder->block_count = 0;
                func->builder->insn_count = 0;
 #endif
 
+       /* Get the method cache */
+       cache = _jit_context_get_cache(func->context);
+       if(!cache)
+       {
+               jit_mutex_unlock(&(func->context->cache_lock));
+               return 0;
+       }
+
                /* Start function output to the cache */
-               start = _jit_cache_start_method
-                       (cache, &(gen.posn), JIT_FUNCTION_ALIGNMENT, func);
-               if(!start)
+       result = _jit_cache_start_method(cache, &(gen.posn),
+                                        page_factor++,
+                                        JIT_FUNCTION_ALIGNMENT, func);
+       if (result == JIT_CACHE_RESTART)
+       {
+               /* No space left on the current cache page.  Allocate a new 
one. */
+               result = _jit_cache_start_method(cache, &(gen.posn),
+                                                page_factor++,
+                                                JIT_FUNCTION_ALIGNMENT, func);
+       }
+       if (result != JIT_CACHE_OK)
                {
-#ifdef jit_extra_gen_cleanup
-                       /* Clean up the extra code generation state */
-                       jit_extra_gen_cleanup(gen);
-#endif
+               /* Failed to allocate any cache space */
                        jit_mutex_unlock(&(func->context->cache_lock));
                        return 0;
                }
 
+       for(;;)
+       {
+               start = gen.posn.ptr;
+
 #ifdef jit_extra_gen_init
                /* Initialize information that may need to be reset each loop */
                jit_extra_gen_init(&gen);
@@ -774,20 +776,13 @@
 
 #ifdef JIT_PROLOG_SIZE
                /* Output space for the function prolog */
-               if(jit_cache_check_for_n(&(gen.posn), JIT_PROLOG_SIZE))
+               if(!jit_cache_check_for_n(&(gen.posn), JIT_PROLOG_SIZE))
                {
-                       gen.posn.ptr += JIT_PROLOG_SIZE;
-                       have_prolog = 1;
+                       /* No space left on the current cache page.  Restart. */
+                       jit_cache_mark_full(&(gen.posn));
+                       goto restart;
                }
-               else
-               {
-                       have_prolog = 0;
-               }
-#endif
-
-               /* Clear the register assignments for the first block */
-#ifndef JIT_BACKEND_INTERP
-               _jit_regs_init_for_block(&gen);
+               gen.posn.ptr += JIT_PROLOG_SIZE;
 #endif
 
                /* Generate code for the blocks in the function */
@@ -803,21 +798,28 @@
                        /* Notify the back end that the block is starting */
                        _jit_gen_start_block(&gen, block);
        
+#ifndef JIT_BACKEND_INTERP
+                       /* Clear the local register assignments */
+                       _jit_regs_init_for_block(&gen);
+#endif
+
                        /* Generate the block's code */
                        compile_block(&gen, func, block);
 
-                       /* Spill all live register values back to their frame 
positions */
 #ifndef JIT_BACKEND_INTERP
+                       /* Spill all live register values back to their frame 
positions */
                        _jit_regs_spill_all(&gen);
 #endif
 
                        /* Notify the back end that the block is finished */
                        _jit_gen_end_block(&gen, block);
        
-                       /* Clear the local register assignments, ready for the 
next block */
-#ifndef JIT_BACKEND_INTERP
-                       _jit_regs_init_for_block(&gen);
-#endif
+                       /* Stop code generation if the cache page is full */
+                       if(_jit_cache_is_full(cache, &(gen.posn)))
+                       {
+                               /* No space left on the current cache page.  
Restart. */
+                               goto restart;
+                       }
                }
 
                /* Output the function epilog.  All return paths will jump to 
here */
@@ -826,10 +828,7 @@
 
 #ifdef JIT_PROLOG_SIZE
                /* Back-patch the function prolog and get the real entry point 
*/
-               if(have_prolog)
-               {
                        start = _jit_gen_prolog(&gen, func, start);
-               }
 #endif
 
 #if !defined(JIT_BACKEND_INTERP) && (!defined(jit_redirector_size) || 
!defined(jit_indirector_size))
@@ -843,17 +842,38 @@
                }
 #endif
 
+       restart:
                /* End the function's output process */
                result = _jit_cache_end_method(&(gen.posn));
-
-               /* If we need to restart on a different cache page, then clean 
up
-                  the compilation state  */
-               if(result == JIT_CACHE_END_RESTART)
+               if(result != JIT_CACHE_RESTART)
                {
+                       break;
+               }
+
+               /* Clean up the compilation state before restart */
                        cleanup_on_restart(&gen, func);
+
+#ifdef _JIT_COMPILE_DEBUG
+               printf("\n*** Restart compilation ***\n\n");
+               func->builder->block_count = 0;
+               func->builder->insn_count = 0;
+#endif
+
+               /* Restart function output to the cache */
+               result = _jit_cache_start_method(cache, &(gen.posn),
+                                                page_factor,
+                                                JIT_FUNCTION_ALIGNMENT, func);
+               if(result != JIT_CACHE_OK)
+               {
+#ifdef jit_extra_gen_cleanup
+                       /* Clean up the extra code generation state */
+                       jit_extra_gen_cleanup(gen);
+#endif
+                       jit_mutex_unlock(&(func->context->cache_lock));
+                       return 0;
                }
+               page_factor *= 2;
        }
-       while(result == JIT_CACHE_END_RESTART);
 
 #ifdef jit_extra_gen_cleanup
        /* Clean up the extra code generation state */
@@ -861,7 +881,7 @@
 #endif
 
        /* Bail out if we ran out of memory while translating the function */
-       if(result != JIT_CACHE_END_OK)
+       if(result != JIT_CACHE_OK)
        {
                jit_mutex_unlock(&(func->context->cache_lock));
                return 0;
@@ -869,26 +889,15 @@
 
 #ifndef JIT_BACKEND_INTERP
        /* Perform a CPU cache flush, to make the code executable */
-       jit_flush_exec(start, (unsigned int)(((unsigned char *)end) -
-                                                                               
 ((unsigned char *)start)));
+       jit_flush_exec(start, (unsigned int)(end - start));
 #endif
 
-       /* Intuit "nothrow" and "noreturn" flags for this function */
-       if(!(func->builder->may_throw))
-       {
-               func->no_throw = 1;
-       }
-       if(!(func->builder->ordinary_return))
-       {
-               func->no_return = 1;
-       }
+       /* The function has been compiled successfully */
+       jit_mutex_unlock(&(func->context->cache_lock));
 
        /* Free the builder structure, which we no longer require */
        _jit_function_free_builder(func);
 
-       /* The function has been compiled successfully */
-       jit_mutex_unlock(&(func->context->cache_lock));
-
        /* Record the entry point */
        if(entry_point)
        {




reply via email to

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