Alien-LibJIT

 view release on metacpan or  search on metacpan

libjit/jit/jit-function.c  view on Meta::CPAN

/*
 * jit-function.c - Functions for manipulating function blocks.
 *
 * Copyright (C) 2004, 2006-2008  Southern Storm Software, Pty Ltd.
 *
 * This file is part of the libjit library.
 *
 * The libjit library is free software: you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * as published by the Free Software Foundation, either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * The libjit library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with the libjit library.  If not, see
 * <http://www.gnu.org/licenses/>.
 */

#include "jit-internal.h"
#include "jit-apply-func.h"
#include "jit-rules.h"
#include "jit-setjmp.h"

/*@
 * @deftypefun jit_function_t jit_function_create (jit_context_t @var{context}, jit_type_t @var{signature})
 * Create a new function block and associate it with a JIT context.
 * Returns NULL if out of memory.
 *
 * A function persists for the lifetime of its containing context.
 * It initially starts life in the "building" state, where the user
 * constructs instructions that represents the function body.
 * Once the build process is complete, the user calls
 * @code{jit_function_compile} to convert it into its executable form.
 *
 * It is recommended that you call @code{jit_context_build_start} before
 * calling @code{jit_function_create}, and then call
 * @code{jit_context_build_end} after you have called
 * @code{jit_function_compile}.  This will protect the JIT's internal
 * data structures within a multi-threaded environment.
 * @end deftypefun
@*/
jit_function_t
jit_function_create(jit_context_t context, jit_type_t signature)
{
	jit_function_t func;
#if !defined(JIT_BACKEND_INTERP) && (defined(jit_redirector_size) || defined(jit_indirector_size))
	unsigned char *trampoline;
#endif

	/* Acquire the memory context */
	_jit_memory_lock(context);
	if(!_jit_memory_ensure(context))
	{
		_jit_memory_unlock(context);
		return 0;
	}

	/* Allocate memory for the function and clear it */
	func = _jit_memory_alloc_function(context);
	if(!func)
	{
		_jit_memory_unlock(context);
		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

libjit/jit/jit-function.c  view on Meta::CPAN

	return func->entry_point;
#endif
}

/*@
 * @deftypefun jit_function_t jit_function_from_vtable_pointer (jit_context_t @var{context}, void *@var{vtable_pointer})
 * Convert a vtable_pointer back into a function.  Returns NULL if the
 * vtable_pointer does not correspond to a function in the specified context.
 * @end deftypefun
@*/
jit_function_t
jit_function_from_vtable_pointer(jit_context_t context, void *vtable_pointer)
{
#ifdef JIT_BACKEND_INTERP
	/* In the interpreted version, the function pointer is used in vtables */
	jit_function_t func = (jit_function_t)vtable_pointer;

	if(func && func->context == context)
	{
		return func;
	}
	return 0;
#else
	void *func_info;

	if(!context)
	{
		return 0;
	}

	func_info = _jit_memory_find_function_info(context, vtable_pointer);
	if(!func_info)
	{
		return 0;
	}

	return _jit_memory_get_function(context, func_info);
#endif
}

/*@
 * @deftypefun void jit_function_set_on_demand_compiler (jit_function_t @var{func}, jit_on_demand_func @var{on_demand})
 * Specify the C function to be called when @var{func} needs to be
 * compiled on-demand.  This should be set just after the function
 * is created, before any build or compile processes begin.
 *
 * You won't need an on-demand compiler if you always build and compile
 * your functions before you call them.  But if you can call a function
 * before it is built, then you must supply an on-demand compiler.
 *
 * When on-demand compilation is requested, @code{libjit} takes the following
 * actions:
 *
 * @enumerate
 * @item
 * The context is locked by calling @code{jit_context_build_start}.
 *
 * @item
 * If the function has already been compiled, @code{libjit} unlocks
 * the context and returns immediately.  This can happen because of race
 * conditions between threads: some other thread may have beaten us
 * to the on-demand compiler.
 *
 * @item
 * The user's on-demand compiler is called.  It is responsible for building
 * the instructions in the function's body.  It should return one of the
 * result codes @code{JIT_RESULT_OK}, @code{JIT_RESULT_COMPILE_ERROR},
 * or @code{JIT_RESULT_OUT_OF_MEMORY}.
 *
 * @item
 * If the user's on-demand function hasn't already done so, @code{libjit}
 * will call @code{jit_function_compile} to compile the function.
 *
 * @item
 * The context is unlocked by calling @code{jit_context_build_end} and
 * @code{libjit} jumps to the newly-compiled entry point.  If an error
 * occurs, a built-in exception of type @code{JIT_RESULT_COMPILE_ERROR}
 * or @code{JIT_RESULT_OUT_OF_MEMORY} will be thrown.
 * @end enumerate
 *
 * Normally you will need some kind of context information to tell you
 * which higher-level construct is being compiled.  You can use the
 * metadata facility to add this context information to the function
 * just after you create it with @code{jit_function_create}.
 * @end deftypefun
@*/
void
jit_function_set_on_demand_compiler(jit_function_t func, jit_on_demand_func on_demand)
{
	if(func)
	{
		func->on_demand = on_demand;
	}
}

/*@
 * @deftypefun jit_on_demand_func jit_function_get_on_demand_compiler (jit_function_t @var{func})
 * Returns function's on-demand compiler.
 * @end deftypefun
@*/
jit_on_demand_func
jit_function_get_on_demand_compiler(jit_function_t func)
{
	if(func)
	{
		return func->on_demand;
	}
	return 0;
}

/*@
 * @deftypefun int jit_function_apply (jit_function_t @var{func}, void **@var{args}, void *@var{return_area})
 * Call the function @var{func} with the supplied arguments.  Each element
 * in @var{args} is a pointer to one of the arguments, and @var{return_area}
 * points to a buffer to receive the return value.  Returns zero if an
 * exception occurred.
 *
 * This is the primary means for executing a function from ordinary
 * C code without creating a closure first with @code{jit_function_to_closure}.
 * Closures may not be supported on all platforms, but function application
 * is guaranteed to be supported everywhere.



( run in 1.496 second using v1.01-cache-2.11-cpan-5735350b133 )