Alien-LibJIT

 view release on metacpan or  search on metacpan

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

 * Fetch stack items from various positions.
 */
#define	VM_STK_INT0		(stacktop[0].int_value)
#define	VM_STK_INT1		(stacktop[1].int_value)
#define	VM_STK_INTP		(stacktop[-1].int_value)
#define	VM_STK_UINT0	(stacktop[0].uint_value)
#define	VM_STK_UINT1	(stacktop[1].uint_value)
#define	VM_STK_UINTP	(stacktop[-1].uint_value)
#define	VM_STK_LONG0	(stacktop[0].long_value)
#define	VM_STK_LONG1	(stacktop[1].long_value)
#define	VM_STK_LONGP	(stacktop[-1].long_value)
#define	VM_STK_ULONG0	(stacktop[0].ulong_value)
#define	VM_STK_ULONG1	(stacktop[1].ulong_value)
#define	VM_STK_ULONGP	(stacktop[-1].ulong_value)
#define	VM_STK_FLOAT320	(stacktop[0].float32_value)
#define	VM_STK_FLOAT321	(stacktop[1].float32_value)
#define	VM_STK_FLOAT32P	(stacktop[-1].float32_value)
#define	VM_STK_FLOAT640	(stacktop[0].float64_value)
#define	VM_STK_FLOAT641	(stacktop[1].float64_value)
#define	VM_STK_FLOAT64P	(stacktop[-1].float64_value)
#define	VM_STK_NFLOAT0	(stacktop[0].nfloat_value)
#define	VM_STK_NFLOAT1	(stacktop[1].nfloat_value)
#define	VM_STK_NFLOATP	(stacktop[-1].nfloat_value)
#define	VM_STK_PTR0		(stacktop[0].ptr_value)
#define	VM_STK_PTR1		(stacktop[1].ptr_value)
#define	VM_STK_PTR2		(stacktop[2].ptr_value)
#define	VM_STK_PTRP		(stacktop[-1].ptr_value)
#define	VM_STK_PTRP2	(stacktop[-2].ptr_value)
#ifdef JIT_NATIVE_INT32
#define	VM_STK_NINT0	VM_STK_INT0
#define	VM_STK_NINT1	VM_STK_INT1
#define	VM_STK_NUINT0	VM_STK_UINT0
#define	VM_STK_NUINT1	VM_STK_UINT1
#else
#define	VM_STK_NINT0	VM_STK_LONG0
#define	VM_STK_NINT1	VM_STK_LONG1
#define	VM_STK_NUINT0	VM_STK_ULONG0
#define	VM_STK_NUINT1	VM_STK_ULONG1
#endif

/*
 * Apply a relative adjustment to a pointer and cast to a specific type.
 */
#define	VM_REL(type,ptr)	\
			((type *)(((unsigned char *)(ptr)) + VM_NINT_ARG))

/*
 * Apply an array adjustment to a pointer.
 */
#define	VM_LOAD_ELEM(type)	\
			(*(((type *)VM_R1_PTR) + VM_R2_NINT))
#define	VM_STORE_ELEM(type,value)	\
			(*(((type *)VM_R0_PTR) + VM_R1_NINT) = (type)(value))

/*
 * Get the address of an argument or local variable at a particular offset.
 */
#define	VM_ARG(type)		\
			((type *)(((jit_item *)args) + VM_NINT_ARG))
#define	VM_LOC(type)		\
			((type *)(((jit_item *)frame) + VM_NINT_ARG))

/*
 * Handle the return value from a function that reports a builtin exception.
 */
#define	VM_BUILTIN(value)	\
			do { \
				builtin_exception = (value); \
				if(builtin_exception < JIT_RESULT_OK) \
				{ \
					goto handle_builtin; \
				} \
			} while (0)

/*
 * Perform a tail call to a new function.
 */
#define	VM_PERFORM_TAIL(newfunc)	\
			{ \
				if(jbuf) \
				{ \
					_jit_unwind_pop_setjmp(); \
				} \
				func = (newfunc); \
				if(func->frame_size > current_frame_size) \
				{ \
					current_frame_size = func->frame_size; \
					frame_base = (jit_item *)alloca(current_frame_size); \
				} \
				stacktop = frame_base + func->working_area; \
				frame = stacktop; \
				goto restart_tail; \
			}

/*
 * Call "jit_apply" from the interpreter, to invoke a native function.
 */
static void apply_from_interpreter
		(jit_type_t signature, void *func,
		 jit_item *args, unsigned int num_fixed_args,
		 void *return_area)
{
	unsigned int num_params;
	unsigned int param;
	jit_type_t type;
	void **apply_args;

	/* Allocate space for the apply arguments and initialize them */
	num_params = jit_type_num_params(signature);
	apply_args = (void **)alloca(sizeof(void *) * num_params);
	for(param = 0; param < num_params; ++param)
	{
		type = jit_type_normalize(jit_type_get_param(signature, param));
		switch(type->kind)
		{
			case JIT_TYPE_SBYTE:
			case JIT_TYPE_UBYTE:
			{
				apply_args[param] =
					((unsigned char *)args) + _jit_int_lowest_byte();
				++args;
			}
			break;

			case JIT_TYPE_SHORT:
			case JIT_TYPE_USHORT:
			{
				apply_args[param] =
					((unsigned char *)args) + _jit_int_lowest_short();
				++args;
			}
			break;

			case JIT_TYPE_INT:
			case JIT_TYPE_UINT:
			case JIT_TYPE_LONG:
			case JIT_TYPE_ULONG:
			case JIT_TYPE_FLOAT32:
			case JIT_TYPE_FLOAT64:
			case JIT_TYPE_NFLOAT:
			{
				apply_args[param] = args;
				++args;
			}
			break;

			case JIT_TYPE_STRUCT:
			case JIT_TYPE_UNION:
			{
				apply_args[param] = args;
				args += JIT_NUM_ITEMS_IN_STRUCT(jit_type_get_size(type));
			}
			break;

			default:
			{
				/* Shouldn't happen, but do something sane */
				apply_args[param] = args;
			}
			break;
		}
	}

	/* Apply the function */
	jit_apply(signature, func, apply_args, num_fixed_args, return_area);
}

void _jit_run_function(jit_function_interp_t func, jit_item *args,
					   jit_item *return_area)
{
	jit_item *frame_base;
	jit_item *frame;
	jit_item *stacktop;
	jit_item r0, r1, r2;
	void **pc;
	jit_int builtin_exception;
	jit_nint temparg;
	void *tempptr;
	void *tempptr2;
	jit_function_t call_func;
	struct jit_backtrace call_trace;
	void *entry;
	void *exception_object = 0;
	void *exception_pc = 0;
	void *handler;
	jit_jmp_buf *jbuf;
	jit_nint current_frame_size;

	/* Define the label table for computed goto dispatch */
	#include "jit-interp-labels.h"

	/* Set up the stack frame for this function */
	current_frame_size = func->frame_size;
	frame_base = (jit_item *)alloca(current_frame_size);
	stacktop = frame_base + func->working_area;
	frame = stacktop;

	/* Get the initial program counter */
restart_tail:
	pc = jit_function_interp_entry_pc(func);

	/* Create a "setjmp" point if this function has a "try" block.
	   This is used to catch exceptions on their way up the stack */
	if(func->func->has_try)
	{
		jbuf = (jit_jmp_buf *)alloca(sizeof(jit_jmp_buf));
		_jit_unwind_push_setjmp(jbuf);
		if(setjmp(jbuf->buf))
		{
			/* An exception has been thrown by lower-level code */
			exception_object = jit_exception_get_last_and_clear();
			exception_pc = pc - 1;
			goto handle_exception;
		}
	}
	else
	{
		jbuf = 0;
	}

	/* Enter the instruction dispatch loop */
	VMSWITCH(pc)
	{
		/******************************************************************
		 * Simple opcodes.
		 ******************************************************************/

		VMCASE(JIT_OP_NOP):
		{
			/* Nothing to do except move on to the next instruction */
			VM_MODIFY_PC(1);
		}
		VMBREAK;

		/******************************************************************
		 * Conversion opcodes.
		 ******************************************************************/

		VMCASE(JIT_OP_TRUNC_SBYTE):
		{
			/* Truncate an integer to a signed 8-bit value */
			VM_R0_INT = (jit_int)(jit_sbyte)VM_R1_INT;
			VM_MODIFY_PC(1);
		}
		VMBREAK;

		VMCASE(JIT_OP_TRUNC_UBYTE):
		{
			/* Truncate an integer to an unsigned 8-bit value */
			VM_R0_INT = (jit_int)(jit_ubyte)VM_R1_INT;
			VM_MODIFY_PC(1);
		}
		VMBREAK;

		VMCASE(JIT_OP_TRUNC_SHORT):
		{

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

		}
		/* Not reached */

		VMCASE(JIT_OP_RETURN_FLOAT32):
		{
			/* Return from the current function, with a 32-bit float result */
			return_area->float32_value = VM_R1_FLOAT32;
			if(jbuf)
			{
				_jit_unwind_pop_setjmp();
			}
			return;
		}
		/* Not reached */

		VMCASE(JIT_OP_RETURN_FLOAT64):
		{
			/* Return from the current function, with a 64-bit float result */
			return_area->float64_value = VM_R1_FLOAT64;
			if(jbuf)
			{
				_jit_unwind_pop_setjmp();
			}
			return;
		}
		/* Not reached */

		VMCASE(JIT_OP_RETURN_NFLOAT):
		{
			/* Return from the current function, with a native float result */
			return_area->nfloat_value = VM_R1_NFLOAT;
			if(jbuf)
			{
				_jit_unwind_pop_setjmp();
			}
			return;
		}
		/* Not reached */

		VMCASE(JIT_OP_RETURN_SMALL_STRUCT):
		{
			/* Return from the current function, with a small structure */
#if JIT_APPLY_MAX_STRUCT_IN_REG != 0
			jit_memcpy(return_area->struct_value,
				   VM_R1_PTR,
				   (unsigned int)VM_NINT_ARG);
#endif
			if(jbuf)
			{
				_jit_unwind_pop_setjmp();
			}
			return;
		}
		/* Not reached */

		VMCASE(JIT_OP_SETUP_FOR_NESTED):
		{
			/* TODO!!! */
			/* Set up to call a nested function who is our child */
			stacktop[-1].ptr_value = args;
			stacktop[-2].ptr_value = frame;
			VM_MODIFY_PC_AND_STACK(1, -2);
		}
		VMBREAK;

		VMCASE(JIT_OP_SETUP_FOR_SIBLING):
		{
			/* TODO!!! */
			/* Set up to call a nested function who is our sibling, a sibling
			   of one of our ancestors, or one of our ancestors directly */
			temparg = VM_NINT_ARG;
			tempptr = &(args[0]);
			while(temparg > 0)
			{
				tempptr = (((jit_item *)tempptr)[1]).ptr_value;
				--temparg;
			}
			stacktop[-1].ptr_value = (((jit_item *)tempptr)[1]).ptr_value;
			stacktop[-2].ptr_value = (((jit_item *)tempptr)[0]).ptr_value;
			VM_MODIFY_PC_AND_STACK(1, -2);
		}
		VMBREAK;

		VMCASE(JIT_INTERP_OP_IMPORT_LOCAL):
		{
			/* TODO!!! */
			/* Import the address of a local variable from an outer scope */
			temparg = VM_NINT_ARG2;
			tempptr = args[0].ptr_value;
			tempptr2 = args[1].ptr_value;
			while(temparg > 1)
			{
				tempptr = ((jit_item *)tempptr2)[0].ptr_value;
				tempptr2 = ((jit_item *)tempptr2)[1].ptr_value;
				--temparg;
			}
			VM_R0_PTR = ((jit_item *)tempptr) + VM_NINT_ARG;
			VM_MODIFY_PC(3);
		}
		VMBREAK;

		VMCASE(JIT_INTERP_OP_IMPORT_ARG):
		{
			/* TODO!!! */
			/* Import the address of an argument from an outer scope */
			temparg = VM_NINT_ARG2;
			tempptr = args[1].ptr_value;
			while(temparg > 1)
			{
				tempptr = ((jit_item *)tempptr)[1].ptr_value;
				--temparg;
			}
			VM_R0_PTR = ((jit_item *)tempptr) + VM_NINT_ARG;
			VM_MODIFY_PC(3);
		}
		VMBREAK;

		VMCASE(JIT_OP_PUSH_INT):
		{
			VM_STK_INTP = VM_R1_INT;
			VM_MODIFY_PC_AND_STACK(1, -1);

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

			VM_STK_LONGP = VM_R1_LONG;
			VM_MODIFY_PC_AND_STACK(1, -1);
		}
		VMBREAK;

		VMCASE(JIT_OP_PUSH_FLOAT32):
		{
			VM_STK_FLOAT32P = VM_R1_FLOAT32;
			VM_MODIFY_PC_AND_STACK(1, -1);
		}
		VMBREAK;

		VMCASE(JIT_OP_PUSH_FLOAT64):
		{
			VM_STK_FLOAT64P = VM_R1_FLOAT64;
			VM_MODIFY_PC_AND_STACK(1, -1);
		}
		VMBREAK;

		VMCASE(JIT_OP_PUSH_NFLOAT):
		{
			VM_STK_NFLOATP = VM_R1_NFLOAT;
			VM_MODIFY_PC_AND_STACK(1, -1);
		}
		VMBREAK;

		VMCASE(JIT_OP_PUSH_STRUCT):
		{
			/* Push a structure value onto the stack, given a pointer to it */
			temparg = VM_NINT_ARG;
			stacktop -= JIT_NUM_ITEMS_IN_STRUCT(temparg);
			jit_memcpy(stacktop, VM_R1_PTR, (unsigned int)temparg);
			VM_MODIFY_PC(2);
		}
		VMBREAK;

		VMCASE(JIT_OP_FLUSH_SMALL_STRUCT):
		{
#if JIT_APPLY_MAX_STRUCT_IN_REG != 0
			jit_memcpy(VM_R0_PTR, return_area->struct_value, VM_NINT_ARG);
#endif
			VM_MODIFY_PC(2);
		}
		VMBREAK;

		/******************************************************************
		 * Exception handling.
		 ******************************************************************/

		VMCASE(JIT_OP_THROW):
		{
			/* Throw an exception, which may be handled in this function */
			exception_object = VM_R1_PTR;
			exception_pc = pc;
		handle_exception:
			tempptr = jit_function_from_pc(func->func->context, pc, &handler);
			if(tempptr == func->func && handler != 0)
			{
				/* We have an appropriate "catch" handler in this function */
				pc = (void **)handler;
				stacktop = frame;
				VM_R0_PTR = exception_object;
			}
			else
			{
				/* Throw the exception up to the next level */
				if(jbuf)
				{
					_jit_unwind_pop_setjmp();
				}
				jit_exception_throw(exception_object);
			}
		}
		VMBREAK;

		VMCASE(JIT_OP_RETHROW):
		{
			/* Rethrow an exception to the caller */
			if(jbuf)
			{
				_jit_unwind_pop_setjmp();
			}
			jit_exception_throw(VM_R1_PTR);
		}
		VMBREAK;

		VMCASE(JIT_OP_LOAD_PC):
		{
			/* Load the current program counter onto the stack */
			VM_R0_PTR = (void *)pc;
			VM_MODIFY_PC(1);
		}
		VMBREAK;

		VMCASE(JIT_OP_LOAD_EXCEPTION_PC):
		{
			/* Load the address where the exception occurred onto the stack */
			VM_R0_PTR = (void *)exception_pc;
			VM_MODIFY_PC(1);
		}
		VMBREAK;

		VMCASE(JIT_OP_LEAVE_FINALLY):
		{
			/* Return from a "finally" handler */
			pc = (void **)VM_STK_PTR0;
			VM_MODIFY_STACK(1);
		}
		VMBREAK;

		VMCASE(JIT_OP_LEAVE_FILTER):
		{
			/* Return from a "filter" handler: pc on stack */
			pc = (void **)(stacktop[0].ptr_value);
			VM_MODIFY_STACK(1);
		}
		VMBREAK;

		VMCASE(JIT_OP_CALL_FILTER):
		{
			/* Call a "filter" handler with pc and value on stack */

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

		}
		VMBREAK;

		VMCASE(JIT_INTERP_OP_STA_0_BYTE):
		{
			/* Store an 8-bit integer into an argument */
			*VM_ARG(jit_sbyte) = (jit_sbyte)VM_R0_INT;
			VM_MODIFY_PC(2);
		}
		VMBREAK;

		VMCASE(JIT_INTERP_OP_STA_0_SHORT):
		{
			/* Store an 16-bit integer into an argument */
			*VM_ARG(jit_short) = (jit_short)VM_R0_INT;
			VM_MODIFY_PC(2);
		}
		VMBREAK;

		VMCASE(JIT_INTERP_OP_STA_0_INT):
		{
			/* Store an 32-bit integer into an argument */
			*VM_ARG(jit_int) = (jit_int)VM_R0_INT;
			VM_MODIFY_PC(2);
		}
		VMBREAK;

		VMCASE(JIT_INTERP_OP_STA_0_LONG):
		{
			/* Store an 64-bit integer into an argument */
			*VM_ARG(jit_long) = (jit_long)VM_R0_LONG;
			VM_MODIFY_PC(2);
		}
		VMBREAK;

		VMCASE(JIT_INTERP_OP_STA_0_FLOAT32):
		{
			/* Store a 32-bit float into an argument */
			*VM_ARG(jit_float32) = VM_R0_FLOAT32;
			VM_MODIFY_PC(2);
		}
		VMBREAK;

		VMCASE(JIT_INTERP_OP_STA_0_FLOAT64):
		{
			/* Store a 64-bit float into an argument */
			*VM_ARG(jit_float64) = VM_R0_FLOAT64;
			VM_MODIFY_PC(2);
		}
		VMBREAK;

		VMCASE(JIT_INTERP_OP_STA_0_NFLOAT):
		{
			/* Store a native float into an argument */
			*VM_ARG(jit_nfloat) = VM_R0_NFLOAT;
			VM_MODIFY_PC(2);
		}
		VMBREAK;

		/******************************************************************
		 * Local variable frame access opcodes.
		 ******************************************************************/

		VMCASE(JIT_INTERP_OP_LDL_0_SBYTE):
		{
			/* Load a signed 8-bit integer local into the register 0 */
			VM_R0_INT = *VM_LOC(jit_sbyte);
			VM_MODIFY_PC(2);
		}
		VMBREAK;

		VMCASE(JIT_INTERP_OP_LDL_0_UBYTE):
		{
			/* Load an unsigned 8-bit integer local into the register 0 */
			VM_R0_INT = *VM_LOC(jit_ubyte);
			VM_MODIFY_PC(2);
		}
		VMBREAK;

		VMCASE(JIT_INTERP_OP_LDL_0_SHORT):
		{
			/* Load a signed 16-bit integer local into the register 0 */
			VM_R0_INT = *VM_LOC(jit_short);
			VM_MODIFY_PC(2);
		}
		VMBREAK;

		VMCASE(JIT_INTERP_OP_LDL_0_USHORT):
		{
			/* Load am unsigned 16-bit integer local into the register 0 */
			VM_R0_INT = *VM_LOC(jit_ushort);
			VM_MODIFY_PC(2);
		}
		VMBREAK;

		VMCASE(JIT_INTERP_OP_LDL_0_INT):
		{
			/* Load a 32-bit integer local into the register 0 */
			VM_R0_INT = *VM_LOC(jit_int);
			VM_MODIFY_PC(2);
		}
		VMBREAK;

		VMCASE(JIT_INTERP_OP_LDL_0_LONG):
		{
			/* Load a 64-bit integer local into the register 0 */
			VM_R0_LONG = *VM_LOC(jit_long);
			VM_MODIFY_PC(2);
		}
		VMBREAK;

		VMCASE(JIT_INTERP_OP_LDL_0_FLOAT32):
		{
			/* Load a 32-bit float local into the register 0 */
			VM_R0_FLOAT32 = *VM_LOC(jit_float32);
			VM_MODIFY_PC(2);
		}
		VMBREAK;

		VMCASE(JIT_INTERP_OP_LDL_0_FLOAT64):
		{



( run in 1.233 second using v1.01-cache-2.11-cpan-df04353d9ac )