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 )