Alien-LibJIT

 view release on metacpan or  search on metacpan

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

					       insn->value1);
			/* Generate code for the instruction with the back end */
			_jit_gen_insn(gen, func, block, insn);
			break;
#endif

		case JIT_OP_MARK_OFFSET:
			/* Mark the current code position as corresponding
			   to a particular bytecode offset */
			mark_offset(gen, func, (unsigned long)(long)jit_value_get_nint_constant(insn->value1));
			break;

		default:
			/* Generate code for the instruction with the back end */
			_jit_gen_insn(gen, func, block, insn);
			break;
		}

#ifdef _JIT_COMPILE_DEBUG
		p2 = gen->ptr;
		printf("Length of binary code: %d\n\n", p2 - p1);
		fflush(stdout);
#endif
	}
}

/*
 * Reset value on codegen restart.
 */
static void
reset_value(jit_value_t value)
{
	value->reg = -1;
	value->in_register = 0;
	value->in_global_register = 0;
	value->in_frame = 0;
}

/*
 * Clean up the compilation state on codegen restart.
 */
static void
cleanup_on_restart(jit_gencode_t gen, jit_function_t func)
{
	jit_block_t block;
	jit_insn_iter_t iter;
	jit_insn_t insn;

	block = 0;
	while((block = jit_block_next(func, block)) != 0)
	{
		/* Clear the block addresses and fixup lists */
		block->address = 0;
		block->fixup_list = 0;
		block->fixup_absolute_list = 0;

		/* Reset values referred to by block instructions */
		jit_insn_iter_init(&iter, block);
		while((insn = jit_insn_iter_next(&iter)) != 0)
		{
			if(insn->dest && (insn->flags & JIT_INSN_DEST_OTHER_FLAGS) == 0)
			{
				reset_value(insn->dest);
			}
			if(insn->value1 && (insn->flags & JIT_INSN_VALUE1_OTHER_FLAGS) == 0)
			{
				reset_value(insn->value1);
			}
			if(insn->value2 && (insn->flags & JIT_INSN_VALUE2_OTHER_FLAGS) == 0)
			{
				reset_value(insn->value2);
			}
		}
	}

	/* Reset values referred to by builder */
	if(func->builder->setjmp_value)
	{
		reset_value(func->builder->setjmp_value);
	}
	if(func->builder->parent_frame)
	{
		reset_value(func->builder->parent_frame);
	}

	/* Reset the "touched" registers mask. The first time compilation
	   might have followed wrong code paths and thus allocated wrong
	   registers. */
	if(func->builder->has_tail_call)
	{
		/* For functions with tail calls _jit_regs_alloc_global()
		   does not allocate any global registers. The "permanent"
		   mask has all global registers set to prevent their use. */
		gen->touched = jit_regused_init;
	}
	else
	{
		gen->touched = gen->permanent;
	}

	/* Reset the epilog fixup list */
	gen->epilog_fixup = 0;
}

/*
 * Acquire the memory context.
 */
static void
memory_acquire(_jit_compile_t *state)
{
	/* Store the function's context as codegen context */
	state->gen.context = state->func->context;

	/* Acquire the memory context lock */
	_jit_memory_lock(state->gen.context);

	/* Remember that the lock is acquired */
	state->memory_locked = 1;

	if(!_jit_memory_ensure(state->gen.context))
	{
		jit_exception_builtin(JIT_RESULT_OUT_OF_MEMORY);
	}
}

/*
 * Release the memory context.
 */
static void

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

			        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;
	}
	if(!state->func->builder->ordinary_return)
	{
		state->func->no_return = 1;
	}

	/* Compute liveness and "next use" information for this function */
	_jit_function_compute_liveness(state->func);

	/* Allocate global registers to variables within the function */
#ifndef JIT_BACKEND_INTERP
	_jit_regs_alloc_global(&state->gen, state->func);
#endif
}

/*
 * Run codegen.
 */
static void
codegen(_jit_compile_t *state)
{
	jit_function_t func = state->func;
	struct jit_gencode *gen = &state->gen;
	jit_block_t block;

	/* Remember the start code address (due to alignment it may differ from
	   the available space start - gen->start) */
	gen->code_start = gen->ptr;

#ifdef JIT_PROLOG_SIZE
	/* Output space for the function prolog */
	_jit_gen_check_space(gen, JIT_PROLOG_SIZE);
	gen->ptr += JIT_PROLOG_SIZE;
#endif

	/* Generate code for the blocks in the function */
	block = 0;
	while((block = jit_block_next(func, block)) != 0)
	{
		/* Notify the back end that the block is starting */
		_jit_gen_start_block(gen, block);

#ifndef JIT_BACKEND_INTERP
		/* Clear the local register assignments */
		_jit_regs_init_for_block(gen);
#endif

		/* Generate the block's code */
		compile_block(gen, func, block);

#ifndef JIT_BACKEND_INTERP
		/* Spill all live register values back to their frame positions */
		_jit_regs_spill_all(gen);
#endif

		/* Notify the back end that the block is finished */
		_jit_gen_end_block(gen, block);



( run in 2.440 seconds using v1.01-cache-2.11-cpan-796a6f069b2 )