Alien-LibJIT
view release on metacpan or search on metacpan
libjit/jit/jit-function.c view on Meta::CPAN
return 0;
}
#if !defined(JIT_BACKEND_INTERP) && (defined(jit_redirector_size) || defined(jit_indirector_size))
trampoline = (unsigned char *) _jit_memory_alloc_trampoline(context);
if(!trampoline)
{
_jit_memory_free_function(context, func);
_jit_memory_unlock(context);
return 0;
}
# if defined(jit_redirector_size)
func->redirector = trampoline;
trampoline += jit_redirector_size;
# endif
# if defined(jit_indirector_size)
func->indirector = trampoline;
# endif
#endif /* !defined(JIT_BACKEND_INTERP) && (defined(jit_redirector_size) || defined(jit_indirector_size)) */
/* Release the memory context */
_jit_memory_unlock(context);
/* Initialize the function block */
func->context = context;
func->signature = jit_type_copy(signature);
func->optimization_level = JIT_OPTLEVEL_NORMAL;
#if !defined(JIT_BACKEND_INTERP) && defined(jit_redirector_size)
/* If we aren't using interpretation, then point the function's
initial entry point at the redirector, which in turn will
invoke the on-demand compiler */
func->entry_point = _jit_create_redirector
(func->redirector, (void *) context->on_demand_driver,
func, jit_type_get_abi(signature));
_jit_flush_exec(func->redirector, jit_redirector_size);
#endif
#if !defined(JIT_BACKEND_INTERP) && defined(jit_indirector_size)
_jit_create_indirector(func->indirector, (void**) &(func->entry_point));
_jit_flush_exec(func->indirector, jit_indirector_size);
#endif
/* Add the function to the context list */
func->next = 0;
func->prev = context->last_function;
if(context->last_function)
{
context->last_function->next = func;
}
else
{
context->functions = func;
}
context->last_function = func;
/* Return the function to the caller */
return func;
}
/*@
* @deftypefun jit_function_t jit_function_create_nested (jit_context_t @var{context}, jit_type_t @var{signature}, jit_function_t @var{parent})
* Create a new function block and associate it with a JIT context.
* In addition, this function is nested inside the specified
* @var{parent} function and is able to access its parent's
* (and grandparent's) local variables.
*
* The front end is responsible for ensuring that the nested function can
* never be called by anyone except its parent and sibling functions.
* The front end is also responsible for ensuring that the nested function
* is compiled before its parent.
* @end deftypefun
@*/
jit_function_t jit_function_create_nested
(jit_context_t context, jit_type_t signature, jit_function_t parent)
{
jit_function_t func;
func = jit_function_create(context, signature);
if(!func)
{
return 0;
}
func->nested_parent = parent;
return func;
}
int _jit_function_ensure_builder(jit_function_t func)
{
/* Handle the easy cases first */
if(!func)
{
return 0;
}
if(func->builder)
{
return 1;
}
/* Allocate memory for the builder and clear it */
func->builder = jit_cnew(struct _jit_builder);
if(!(func->builder))
{
return 0;
}
/* Cache the value of the JIT_OPTION_POSITION_INDEPENDENT option */
func->builder->position_independent
= jit_context_get_meta_numeric(
func->context, JIT_OPTION_POSITION_INDEPENDENT);
/* Initialize the function builder */
jit_memory_pool_init(&(func->builder->value_pool), struct _jit_value);
jit_memory_pool_init(&(func->builder->edge_pool), struct _jit_edge);
jit_memory_pool_init(&(func->builder->meta_pool), struct _jit_meta);
/* Create the entry block */
if(!_jit_block_init(func))
{
_jit_function_free_builder(func);
return 0;
}
/* Create instructions to initialize the incoming arguments */
func->builder->current_block = func->builder->entry_block;
if(!_jit_create_entry_insns(func))
{
_jit_function_free_builder(func);
return 0;
}
/* The current position is where initialization code will be
inserted by "jit_insn_move_blocks_to_start" */
func->builder->init_block = func->builder->current_block;
/* Start first block for function body */
if(!jit_insn_new_block(func))
{
_jit_function_free_builder(func);
return 0;
}
/* The builder is ready to go */
return 1;
libjit/jit/jit-function.c view on Meta::CPAN
}
/*@
* @deftypefun jit_function_t jit_function_previous (jit_context_t @var{context}, jit_function_t @var{prev})
* Iterate over the defined functions in reverse creation order.
* @end deftypefun
@*/
jit_function_t jit_function_previous(jit_context_t context, jit_function_t prev)
{
if(prev)
{
return prev->prev;
}
else if(context)
{
return context->last_function;
}
else
{
return 0;
}
}
/*@
* @deftypefun jit_block_t jit_function_get_entry (jit_function_t @var{func})
* Get the entry block for a function. This is always the first block
* created by @code{jit_function_create}.
* @end deftypefun
@*/
jit_block_t jit_function_get_entry(jit_function_t func)
{
if(func && func->builder)
{
return func->builder->entry_block;
}
else
{
return 0;
}
}
/*@
* @deftypefun jit_block_t jit_function_get_current (jit_function_t @var{func})
* Get the current block for a function. New blocks are created by
* certain @code{jit_insn_xxx} calls.
* @end deftypefun
@*/
jit_block_t jit_function_get_current(jit_function_t func)
{
if(func && func->builder)
{
return func->builder->current_block;
}
else
{
return 0;
}
}
/*@
* @deftypefun jit_function_t jit_function_get_nested_parent (jit_function_t @var{func})
* Get the nested parent for a function, or NULL if @var{func}
* does not have a nested parent.
* @end deftypefun
@*/
jit_function_t jit_function_get_nested_parent(jit_function_t func)
{
if(func)
{
return func->nested_parent;
}
else
{
return 0;
}
}
/*
* Information that is stored for an exception region in the cache.
*/
typedef struct jit_cache_eh *jit_cache_eh_t;
struct jit_cache_eh
{
jit_label_t handler_label;
unsigned char *handler;
jit_cache_eh_t previous;
};
/*@
* @deftypefun int jit_function_is_compiled (jit_function_t @var{func})
* Determine if a function has already been compiled.
* @end deftypefun
@*/
int jit_function_is_compiled(jit_function_t func)
{
if(func)
{
return func->is_compiled;
}
else
{
return 0;
}
}
/*@
* @deftypefun int jit_function_set_recompilable (jit_function_t @var{func})
* Mark this function as a candidate for recompilation. That is,
* it is possible that we may call @code{jit_function_compile}
* more than once, to re-optimize an existing function.
*
* It is very important that this be called before the first time that
* you call @code{jit_function_compile}. Functions that are recompilable
* are invoked in a slightly different way to non-recompilable functions.
* If you don't set this flag, then existing invocations of the function
* may continue to be sent to the original compiled version, not the new
* version.
* @end deftypefun
@*/
void jit_function_set_recompilable(jit_function_t func)
{
if(func)
{
func->is_recompilable = 1;
}
}
/*@
* @deftypefun void jit_function_clear_recompilable (jit_function_t @var{func})
* Clear the recompilable flag on this function. Normally you would use
libjit/jit/jit-function.c view on Meta::CPAN
* is guaranteed to be supported everywhere.
*
* Function applications acts as an exception blocker. If any exceptions
* occur during the execution of @var{func}, they won't travel up the
* stack any further than this point. This prevents ordinary C code
* from being accidentally presented with a situation that it cannot handle.
* This blocking protection is not present when a function is invoked
* via its closure.
* @end deftypefun
*
* @deftypefun int jit_function_apply_vararg (jit_function_t @var{func}, jit_type_t @var{signature}, void **@var{args}, void *@var{return_area})
* Call the function @var{func} with the supplied arguments. There may
* be more arguments than are specified in the function's original signature,
* in which case the additional values are passed as variable arguments.
* This function is otherwise identical to @code{jit_function_apply}.
* @end deftypefun
@*/
#if !defined(JIT_BACKEND_INTERP)
/* The interpreter version is in "jit-interp.cpp" */
int jit_function_apply(jit_function_t func, void **args, void *return_area)
{
if(func)
{
return jit_function_apply_vararg
(func, func->signature, args, return_area);
}
else
{
return jit_function_apply_vararg(func, 0, args, return_area);
}
}
int jit_function_apply_vararg
(jit_function_t func, jit_type_t signature, void **args, void *return_area)
{
struct jit_backtrace call_trace;
void *entry;
jit_jmp_buf jbuf;
/* Establish a "setjmp" point here so that we can unwind the
stack to this point when an exception occurs and then prevent
the exception from propagating further up the stack */
_jit_unwind_push_setjmp(&jbuf);
if(setjmp(jbuf.buf))
{
_jit_unwind_pop_setjmp();
return 0;
}
/* Create a backtrace entry that blocks exceptions from
flowing further than this up the stack */
_jit_backtrace_push(&call_trace, 0);
/* Get the function's entry point */
if(!func)
{
jit_exception_builtin(JIT_RESULT_NULL_FUNCTION);
return 0;
}
if(func->nested_parent)
{
jit_exception_builtin(JIT_RESULT_CALLED_NESTED);
return 0;
}
if(func->is_compiled)
{
entry = func->entry_point;
}
else
{
entry = (*func->context->on_demand_driver)(func);
}
/* Get the default signature if necessary */
if(!signature)
{
signature = func->signature;
}
/* Clear the exception state */
jit_exception_clear_last();
/* Apply the function. If it returns, then there is no exception */
jit_apply(signature, func->entry_point, args,
jit_type_num_params(func->signature), return_area);
/* Restore the backtrace and "setjmp" contexts and exit */
_jit_unwind_pop_setjmp();
return 1;
}
#endif /* !JIT_BACKEND_INTERP */
/*@
* @deftypefun void jit_function_set_optimization_level (jit_function_t @var{func}, unsigned int @var{level})
* Set the optimization level for @var{func}. Increasing values indicate
* that the @code{libjit} dynamic compiler should expend more effort to
* generate better code for this function. Usually you would increase
* this value just before forcing @var{func} to recompile.
*
* When the optimization level reaches the value returned by
* @code{jit_function_get_max_optimization_level()}, there is usually
* little point in continuing to recompile the function because
* @code{libjit} may not be able to do any better.
*
* The front end is usually responsible for choosing candidates for
* function inlining. If it has identified more such candidates, then
* it may still want to recompile @var{func} again even once it has
* reached the maximum optimization level.
* @end deftypefun
@*/
void
jit_function_set_optimization_level(jit_function_t func, unsigned int level)
{
unsigned int max_level = jit_function_get_max_optimization_level();
if(level > max_level)
{
level = max_level;
}
if(func)
( run in 0.357 second using v1.01-cache-2.11-cpan-4991d5b9bd9 )