Alien-LibJIT
view release on metacpan or search on metacpan
libjit/jit/jit-compile.c view on Meta::CPAN
typedef struct
{
jit_function_t func;
int memory_locked;
int memory_started;
int restart;
int page_factor;
struct jit_gencode gen;
} _jit_compile_t;
#define _JIT_RESULT_TO_OBJECT(x) ((void *) ((jit_nint) (x) - JIT_RESULT_OK))
#define _JIT_RESULT_FROM_OBJECT(x) ((jit_nint) ((void *) (x)) + JIT_RESULT_OK)
/*
* This exception handler overrides a user-defined handler during compilation.
*/
static void *
internal_exception_handler(int exception_type)
{
return _JIT_RESULT_TO_OBJECT(exception_type);
}
/*
* Optimize a function.
*/
static void
optimize(jit_function_t func)
{
if(func->is_optimized || func->optimization_level == JIT_OPTLEVEL_NONE)
{
/* The function is already optimized or does not need optimization */
return;
}
/* Build control flow graph */
_jit_block_build_cfg(func);
/* Eliminate useless control flow */
_jit_block_clean_cfg(func);
/* Optimization is done */
func->is_optimized = 1;
}
/*@
* @deftypefun int jit_optimize (jit_function_t @var{func})
* Optimize a function by analyzing and transforming its intermediate
* representation. If the function was already compiled or optimized,
* then do nothing.
*
* Returns @code{JIT_RESUlT_OK} on success, otherwise it might return
* @code{JIT_RESULT_OUT_OF_MEMORY}, @code{JIT_RESULT_COMPILE_ERROR} or
* possibly some other more specific @code{JIT_RESULT_} code.
*
* Normally this function should not be used because @code{jit_compile}
* performs all the optimization anyway. However it might be useful for
* debugging to verify the effect of the @code{libjit} code optimization.
* This might be done, for instance, by calling @code{jit_dump_function}
* before and after @code{jit_optimize}.
* @end deftypefun
@*/
int
jit_optimize(jit_function_t func)
{
jit_jmp_buf jbuf;
jit_exception_func handler;
/* Bail out on invalid parameter */
if(!func)
{
return JIT_RESULT_NULL_FUNCTION;
}
/* Bail out if there is nothing to do here */
if(!func->builder)
{
if(func->is_compiled)
{
/* The function is already compiled and we can't optimize it */
return JIT_RESULT_OK;
}
else
{
/* We don't have anything to optimize at all */
return JIT_RESULT_NULL_FUNCTION;
}
}
/* Override user's exception handler */
handler = jit_exception_set_handler(internal_exception_handler);
/* 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();
jit_exception_set_handler(handler);
return _JIT_RESULT_FROM_OBJECT(jit_exception_get_last_and_clear());
}
/* Perform the optimizations */
optimize(func);
/* Restore the "setjmp" contexts and exit */
_jit_unwind_pop_setjmp();
jit_exception_set_handler(handler);
return JIT_RESULT_OK;
}
/*
* Mark the current position with a bytecode offset value.
*/
void
mark_offset(jit_gencode_t gen, jit_function_t func, unsigned long offset)
{
libjit/jit/jit-compile.c view on Meta::CPAN
/* Try to allocate within the current memory limit */
result = _jit_memory_start_function(state->gen.context, state->func);
if(result == JIT_MEMORY_RESTART)
{
/* Not enough space. Request to extend the limit and retry */
_jit_memory_extend_limit(state->gen.context, state->page_factor++);
result = _jit_memory_start_function(state->gen.context, state->func);
}
if(result != JIT_MEMORY_OK)
{
/* Failed to allocate any space */
jit_exception_builtin(JIT_RESULT_OUT_OF_MEMORY);
}
/* Start with with allocated space */
memory_start(state);
}
/*
* Finish code generation.
*/
static void
memory_flush(_jit_compile_t *state)
{
int result;
if(state->memory_started)
{
/* Reset the memory state */
state->memory_started = 0;
/* Let the memory context know the address we ended at */
_jit_memory_set_break(state->gen.context, state->gen.code_end);
/* Finally end the function */
result = _jit_memory_end_function(state->gen.context, JIT_MEMORY_OK);
if(result != JIT_MEMORY_OK)
{
if(result == JIT_MEMORY_RESTART)
{
/* Throw an internal exception that causes
a larger code space to be allocated and
the code generation to restart */
jit_exception_builtin(JIT_RESULT_MEMORY_FULL);
}
else
{
/* Throw exception that indicates failure
to allocate enough code space */
jit_exception_builtin(JIT_RESULT_OUT_OF_MEMORY);
}
}
#ifndef JIT_BACKEND_INTERP
/* On success perform a CPU cache flush, to make the code executable */
_jit_flush_exec(state->gen.code_start,
state->gen.code_end - state->gen.code_start);
#endif
/* Terminate the debug information and flush it */
if(!_jit_varint_encode_end(&state->gen.offset_encoder))
{
jit_exception_builtin(JIT_RESULT_OUT_OF_MEMORY);
}
state->func->bytecode_offset = _jit_varint_get_data(&state->gen.offset_encoder);
}
}
/*
* Give back the allocated space in case of failure to generate the code.
*/
static void
memory_abort(_jit_compile_t *state)
{
if(state->memory_started)
{
state->memory_started = 0;
/* Release the code space */
_jit_memory_end_function(state->gen.context, JIT_MEMORY_RESTART);
/* Free encoded bytecode offset data */
_jit_varint_free_data(_jit_varint_get_data(&state->gen.offset_encoder));
}
}
/*
* Allocate more code space.
*/
static void
memory_realloc(_jit_compile_t *state)
{
int result;
/* Release the previously allocated code space */
memory_abort(state);
/* Request to extend memory limit and retry space allocation */
_jit_memory_extend_limit(state->gen.context, state->page_factor++);
result = _jit_memory_start_function(state->gen.context, state->func);
if(result != JIT_MEMORY_OK)
{
/* Failed to allocate enough space */
jit_exception_builtin(JIT_RESULT_OUT_OF_MEMORY);
}
/* Start with with allocated space */
memory_start(state);
}
/*
* Prepare function info needed for code generation.
*/
static void
codegen_prepare(_jit_compile_t *state)
{
/* Intuit "nothrow" and "noreturn" flags for this function */
if(!state->func->builder->may_throw)
{
state->func->no_throw = 1;
( run in 0.780 second using v1.01-cache-2.11-cpan-02777c243ea )