+2012-10-08 Aleksey Demakov <ademakov@gmail.com>
+
+ * jit/jit-cache.c, jit/jit-cache.c(_jit_cache_alloc_trampoline)
+ (_jit_cache_free_trampoline, _jit_cache_alloc_closure)
+ (_jit_cache_free_closure): add functions.
+ * jit/jit-function.c (jit_function_create, _jit_function_destroy):
+ use trampoline alloc/free functions.
+
+ * jit/jit-apply.c, include/jit/jit-init.h (jit_get_closure_size)
+ (jit_get_closure_alignment, jit_get_trampoline_size)
+ (jit_get_trampoline_alignment): add functions.
+ * jit/jit-apply.c (jit_closures_supported): for consistency rename
+ function to jit_supports_closures.
+
2012-10-07 Aleksey Demakov <ademakov@gmail.com>
* jit/jit-function.c (jit_function_create, _jit_function_destroy):
void *jit_closure_create(jit_context_t context, jit_type_t signature,
jit_closure_func func, void *user_data);
-int jit_closures_supported(void);
-
jit_nint jit_closure_va_get_nint(jit_closure_va_list_t va);
jit_nuint jit_closure_va_get_nuint(jit_closure_va_list_t va);
jit_long jit_closure_va_get_long(jit_closure_va_list_t va);
int jit_supports_virtual_memory(void) JIT_NOTHROW;
+int jit_supports_closures(void);
+
+unsigned int jit_get_closure_size(void);
+unsigned int jit_get_closure_alignment(void);
+unsigned int jit_get_trampoline_size(void);
+unsigned int jit_get_trampoline_alignment(void);
+
#ifdef __cplusplus
};
#endif
return 0;
}
- closure = (jit_closure_t)_jit_cache_alloc_no_method(cache, sizeof(struct jit_closure), jit_closure_align);
+ closure = (jit_closure_t)_jit_cache_alloc_closure(cache);
if(!closure)
{
jit_mutex_unlock(&context->cache_lock);
}
/*@
- * @deftypefun int jit_closures_supported (void)
+ * @deftypefun int jit_supports_closures (void)
* Determine if this platform has support for closures.
* @end deftypefun
@*/
-int jit_closures_supported(void)
+int
+jit_supports_closures(void)
{
#ifdef jit_closure_size
return 1;
#endif
}
+unsigned int
+jit_get_closure_size(void)
+{
+#ifdef jit_closure_size
+ return jit_closure_size;
+#else
+ return 0;
+#endif
+}
+
+unsigned int
+jit_get_closure_alignment(void)
+{
+#ifdef jit_closure_size
+ return jit_closure_align;
+#else
+ return 0;
+#endif
+}
+
+unsigned int
+jit_get_trampoline_size(void)
+{
+ int size = 0;
+#if defined(jit_redirector_size)
+ size += jit_redirector_size;
+#endif
+#if defined(jit_indirector_size)
+ size += jit_indirector_size;
+#endif
+ return size;
+}
+
+unsigned int
+jit_get_trampoline_alignment(void)
+{
+#if defined(jit_redirector_size) || defined(jit_indirector_size)
+ return 1;
+#else
+ return 0;
+#endif
+}
+
/*@
* @deftypefun jit_nint jit_closure_va_get_nint (jit_closure_va_list_t @var{va})
* @deftypefunx jit_nuint jit_closure_va_get_nuint (jit_closure_va_list_t @var{va})
* variable arguments, and copy it into @var{buf}.
* @end deftypefun
@*/
-void jit_closure_va_get_struct
- (jit_closure_va_list_t va, void *buf, jit_type_t type)
+void
+jit_closure_va_get_struct(jit_closure_va_list_t va, void *buf, jit_type_t type)
{
#ifdef HAVE_JIT_BUILTIN_APPLY_STRUCT
_jit_builtin_apply_get_struct(&(va->builder), buf, type);
cache->prev_start = cache->free_start;
cache->prev_end = cache->free_end;
- /* Allocate memory for the function information block */
+ /* Get the function information block */
cache->method = (jit_cache_method_t)
(((char *) func) - offsetof(struct jit_cache_method, func));
return ptr;
}
+static void *
+alloc_code(jit_cache_t cache, unsigned int size, unsigned int align)
+{
+ unsigned char *ptr;
+
+ /* Bail out if there is a started function */
+ if(cache->method)
+ {
+ return 0;
+ }
+ /* Bail out if there is no cache available */
+ if(!cache->free_start)
+ {
+ return 0;
+ }
+
+ /* Allocate aligned memory. */
+ ptr = cache->free_start;
+ if(align > 1)
+ {
+ jit_nuint p = ((jit_nuint) ptr + align - 1) & ~(align - 1);
+ ptr = (unsigned char *) p;
+ }
+
+ /* Do we need to allocate a new cache page? */
+ if((ptr + size) > cache->free_end)
+ {
+ /* Allocate a new page */
+ AllocCachePage(cache, 0);
+
+ /* Bail out if the cache is full */
+ if(!cache->free_start)
+ {
+ return 0;
+ }
+
+ /* Allocate memory from the new page */
+ ptr = cache->free_start;
+ if(align > 1)
+ {
+ jit_nuint p = ((jit_nuint) ptr + align - 1) & ~(align - 1);
+ ptr = (unsigned char *) p;
+ }
+ }
+
+ /* Allocate the block and return it */
+ cache->free_start = ptr + size;
+ return (void *) ptr;
+}
+
+void *
+_jit_cache_alloc_trampoline(jit_cache_t cache)
+{
+ return alloc_code(cache,
+ jit_get_trampoline_size(),
+ jit_get_trampoline_alignment());
+}
+
+void
+_jit_cache_free_trampoline(jit_cache_t cache, void *trampoline)
+{
+ /* not supported yet */
+}
+
+void *
+_jit_cache_alloc_closure(jit_cache_t cache)
+{
+ return alloc_code(cache,
+ jit_get_closure_size(),
+ jit_get_closure_alignment());
+}
+
+void
+_jit_cache_free_closure(jit_cache_t cache, void *closure)
+{
+ /* not supported yet */
+}
+
void *
_jit_cache_alloc_no_method(jit_cache_t cache, unsigned long size, unsigned long align)
{
ptr = cache->free_end - size;
ptr = (unsigned char *) (((jit_nuint) ptr) & ~((jit_nuint) align - 1));
}
-
+
/* Allocate the block and return it */
cache->free_end = ptr;
return (void *)ptr;
void _jit_cache_extend(jit_cache_t cache, int count);
/*
- * Allocate a function description structure.
+ * Allocate a function information structure.
*/
jit_function_t _jit_cache_alloc_function(jit_cache_t cache);
/*
- * Release a function description structure.
+ * Release a function information structure.
*/
void _jit_cache_free_function(jit_cache_t cache, jit_function_t func);
unsigned long align);
/*
- * Allocate "size" bytes of storage when we aren't currently
- * translating a method.
+ * Allocate memory for a trampoline.
+ *
+ * The required size and alignment can be determined with these functions:
+ * jit_get_trampoline_size(), jit_get_trampoline_alignment().
+ */
+void *_jit_cache_alloc_trampoline(jit_cache_t cache);
+
+/*
+ * Free memory used by a trampoline.
+ */
+void _jit_cache_free_trampoline(jit_cache_t cache, void *trampoline);
+
+/*
+ * Allocate memory for a closure.
+ *
+ * The required size and alignment can be determined with these functions:
+ * jit_get_closure_size(), jit_get_closure_alignment().
+ */
+void *_jit_cache_alloc_closure(jit_cache_t cache);
+
+/*
+ * Free memory used by a closure.
*/
-void *_jit_cache_alloc_no_method(jit_cache_t cache, unsigned long size, unsigned long align);
+void _jit_cache_free_closure(jit_cache_t cache, void *closure);
/*
* Find the method that is associated with a particular
{
jit_function_t func;
jit_cache_t cache;
+#if !defined(JIT_BACKEND_INTERP) && (defined(jit_redirector_size) || defined(jit_indirector_size))
+ unsigned char *trampoline;
+#endif
/* We need the cache lock. */
jit_mutex_lock(&context->cache_lock);
}
#if !defined(JIT_BACKEND_INTERP) && (defined(jit_redirector_size) || defined(jit_indirector_size))
- /* TODO: if the function is destroyed the redirector and indirector memory
- is leaked */
-# if defined(jit_redirector_size)
- /* Allocate redirector buffer */
- func->redirector = _jit_cache_alloc_no_method(cache, jit_redirector_size, 1);
- if(!func->redirector)
+ trampoline = (unsigned char *) _jit_cache_alloc_trampoline(cache);
+ if(!trampoline)
{
_jit_cache_free_function(cache, func);
jit_mutex_unlock(&context->cache_lock);
return 0;
}
+# if defined(jit_redirector_size)
+ func->redirector = trampoline;
+ trampoline += jit_redirector_size;
# endif
# if defined(jit_indirector_size)
- /* Allocate indirector buffer */
- func->indirector = _jit_cache_alloc_no_method(cache, jit_indirector_size, 1);
- if(!func->indirector)
- {
- _jit_cache_free_function(cache, func);
- jit_mutex_unlock(&context->cache_lock);
- return 0;
- }
+ func->indirector = trampoline;
# endif
#endif /* !defined(JIT_BACKEND_INTERP) && (defined(jit_redirector_size) || defined(jit_indirector_size)) */
jit_type_free(func->signature);
jit_mutex_lock(&context->cache_lock);
+#if !defined(JIT_BACKEND_INTERP) && (defined(jit_redirector_size) || defined(jit_indirector_size))
+# if defined(jit_redirector_size)
+ _jit_cache_free_trampoline(context->cache, func->redirector);
+# else
+ _jit_cache_free_trampoline(context->cache, func->indirector);
+# endif
+#endif
_jit_cache_free_function(context->cache, func);
jit_mutex_unlock(&context->cache_lock);
}