Alien-LibJIT

 view release on metacpan or  search on metacpan

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


	/* Clear the original "catch_pc" value within "setjmp_value" */
	if(!jit_insn_store_relative
		(func, jit_insn_address_of(func, func->builder->setjmp_value),
		 jit_jmp_catch_pc_offset, jit_value_create_nint_constant
		 	(func, jit_type_void_ptr, 0)))
	{
		return 0;
	}

	/* Jump to this function's exception catcher */
	if(!jit_insn_branch(func, &(func->builder->catcher_label)))
	{
		return 0;
	}

	/* Mark the position of the rethrow label */
	if(!jit_insn_label(func, &rethrow_label))
	{
		return 0;
	}

	/* Call "_jit_unwind_pop_and_rethrow" to pop the current
	   "setjmp" context and then rethrow the current exception */
	type = jit_type_create_signature
		(jit_abi_cdecl, jit_type_void, 0, 0, 1);
	if(!type)
	{
		return 0;
	}
	jit_insn_call_native
		(func, "_jit_unwind_pop_and_rethrow",
		 (void *)_jit_unwind_pop_and_rethrow, type, 0, 0,
		 JIT_CALL_NOTHROW | JIT_CALL_NORETURN);
	jit_type_free(type);

	/* Insert the target to jump to the normal code. */
	if(!jit_insn_label(func, &code_label))
	{
		return 0;
	}

	/* Force the start of a new block to mark the end of the init code */
	if(!jit_insn_label(func, &end_label))
	{
		return 0;
	}

	/* Move the initialization code to the head of the function so that
	   it is performed once upon entry to the function */
	return jit_insn_move_blocks_to_start(func, start_label, end_label);
#else
	/* The interpreter doesn't need the "setjmp" setup block */
	func->builder->catcher_label = jit_label_undefined;
	return 1;
#endif
}

/*@
 * @deftypefun int jit_insn_uses_catcher (jit_function_t @var{func})
 * Notify the function building process that @var{func} contains
 * some form of @code{catch} clause for catching exceptions.  This must
 * be called before any instruction that is covered by a @code{try},
 * ideally at the start of the function output process.
 * @end deftypefun
@*/
int jit_insn_uses_catcher(jit_function_t func)
{
	if(!_jit_function_ensure_builder(func))
	{
		return 0;
	}
	if(func->has_try)
	{
		return 1;
	}
	func->has_try = 1;
	func->builder->may_throw = 1;
	func->builder->non_leaf = 1;
	return initialize_setjmp_block(func);
}

/*@
 * @deftypefun jit_value_t jit_insn_start_catcher (jit_function_t @var{func})
 * Start the catcher block for @var{func}.  There should be exactly one
 * catcher block for any function that involves a @code{try}.  All
 * exceptions that are thrown within the function will cause control
 * to jump to this point.  Returns a value that holds the exception
 * that was thrown.
 * @end deftypefun
@*/
jit_value_t jit_insn_start_catcher(jit_function_t func)
{
	jit_value_t value;
#if !defined(JIT_BACKEND_INTERP)
	jit_value_t last_exception;
	jit_type_t type;
#endif
	if(!_jit_function_ensure_builder(func))
	{
		return 0;
	}
	if(!jit_insn_label(func, &(func->builder->catcher_label)))
	{
		return 0;
	}
	value = jit_insn_thrown_exception(func);
	if(!value)
	{
		return 0;
	}
#if defined(JIT_BACKEND_INTERP)
	/* In the interpreter, the exception object will be on the top of
	   the operand stack when control reaches the catcher */
	if(!jit_insn_incoming_reg(func, value, 0))
	{
		return 0;
	}
#else
	type = jit_type_create_signature(jit_abi_cdecl, jit_type_void_ptr, 0, 0, 1);
	if(!type)
	{
		return 0;
	}

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

	/* The current block ends in a dead instruction */
	func->builder->current_block->ends_in_dead = 1;

	/* Create a new block for the following code */
	return jit_insn_new_block(func);
}

/*@
 * @deftypefun int jit_insn_call_finally (jit_function_t @var{func}, jit_label_t *@var{finally_label})
 * Call a @code{finally} clause.
 * @end deftypefun
@*/
int jit_insn_call_finally(jit_function_t func, jit_label_t *finally_label)
{
	jit_insn_t insn;

	/* Ensure that we have a function builder */
	if(!_jit_function_ensure_builder(func))
	{
		return 0;
	}

	/* Flush any stack pops that were deferred previously */
	if(!jit_insn_flush_defer_pop(func, 0))
	{
		return 0;
	}

	/* Allocate the label number if necessary */
	if(*finally_label == jit_label_undefined)
	{
		*finally_label = (func->builder->next_label)++;
	}

	/* Calling a finally handler makes the function not a leaf because
	   we may need to do a native "call" to invoke the handler */
	func->builder->non_leaf = 1;

	/* Add a new branch instruction to branch to the finally handler */
	insn = _jit_block_add_insn(func->builder->current_block);
	if(!insn)
	{
		return 0;
	}
	insn->opcode = (short)JIT_OP_CALL_FINALLY;
	insn->flags = JIT_INSN_DEST_IS_LABEL;
	insn->dest = (jit_value_t)(*finally_label);

	/* Create a new block for the following code */
	return jit_insn_new_block(func);
}

/*@
 * @deftypefun jit_value_t jit_insn_start_filter (jit_function_t @var{func}, jit_label_t *@var{label}, jit_type_t @var{type})
 * Define the start of a filter.  Filters are embedded subroutines within
 * functions that are used to filter exceptions in @code{catch} blocks.
 *
 * A filter subroutine takes a single argument (usually a pointer) and
 * returns a single result (usually a boolean).  The filter has complete
 * access to the local variables of the function, and can use any of
 * them in the filtering process.
 *
 * This function returns a temporary value of the specified @var{type},
 * indicating the parameter that is supplied to the filter.
 * @end deftypefun
@*/
jit_value_t jit_insn_start_filter
	(jit_function_t func, jit_label_t *label, jit_type_t type)
{
	/* Set a label at this point to start a new block */
	if(!jit_insn_label(func, label))
	{
		return 0;
	}

	/* Create a note to load the filter's parameter at runtime */
	return create_dest_note(func, JIT_OP_ENTER_FILTER, type);
}

/*@
 * @deftypefun int jit_insn_return_from_filter (jit_function_t @var{func}, jit_value_t @var{value})
 * Return from a filter subroutine with the specified @code{value} as
 * its result.
 * @end deftypefun
@*/
int jit_insn_return_from_filter(jit_function_t func, jit_value_t value)
{
	/* Flush any deferred stack pops before we return */
	if(!jit_insn_flush_defer_pop(func, 0))
	{
		return 0;
	}

	/* Mark the end of the "filter" clause */
	if(!create_unary_note(func, JIT_OP_LEAVE_FILTER, value))
	{
		return 0;
	}

	/* The current block ends in a dead instruction */
	func->builder->current_block->ends_in_dead = 1;

	/* Create a new block for the following code */
	return jit_insn_new_block(func);
}

/*@
 * @deftypefun jit_value_t jit_insn_call_filter (jit_function_t @var{func}, jit_label_t *@var{label}, jit_value_t @var{value}, jit_type_t @var{type})
 * Call the filter subroutine at @var{label}, passing it @var{value} as
 * its argument.  This function returns a value of the specified
 * @var{type}, indicating the filter's result.
 * @end deftypefun
@*/
jit_value_t jit_insn_call_filter
	(jit_function_t func, jit_label_t *label,
	 jit_value_t value, jit_type_t type)
{
	jit_insn_t insn;

	/* Ensure that we have a function builder */
	if(!_jit_function_ensure_builder(func))



( run in 1.267 second using v1.01-cache-2.11-cpan-5b529ec07f3 )