/*
 * Save the current jitStack status to the label.
 * This is done when the label is referenced the first time.
 */
static int _ILJitLabelSaveStack(ILJITCoder *coder, ILJITLabel *label)
{
	int coderStackHeight = _ILJitStackHeight(coder);
#ifdef	_IL_JIT_ENABLE_INLINE
	int coderStackBase;

	if(coder->currentInlineContext)
	{
		coderStackBase = coder->currentInlineContext->stackBase;
		coderStackHeight -= coderStackBase;
	}
	else
	{
		coderStackBase = 0;
	}
#else	/* !_IL_JIT_ENABLE_INLINE */
	int coderStackBase = 0;
#endif	/* !_IL_JIT_ENABLE_INLINE */

	if(((label->labelType & (_IL_JIT_LABEL_NORMAL |
							 _IL_JIT_LABEL_STARTCATCH)) != 0) &&
		(coderStackHeight > 0))
	{
		int current = 0;
		ILJitValue *stack = ILMemStackAllocItem(&(coder->stackStates),
									coderStackHeight * sizeof(ILJitValue));
		if(!stack)
		{
			return 0;
		}
		/* Now save the current stack state. */
		for(current = 0; current < coderStackHeight; current++)
		{
			ILJitStackItem *stackItem = _ILJitStackItemGet(coder, coderStackBase + current);

			stack[current] = _ILJitStackItemValue(*stackItem);
			if(jit_value_is_constant(_ILJitStackItemValue(*stackItem)))
			{
				/* We have to handle this case different. */
				/* Create a local value of the type of the constant. */
				ILJitValue temp = jit_value_create(coder->jitFunction,
												   jit_value_get_type(_ILJitStackItemValue(*stackItem)));
				/* and store the value of the constant in the new temporary. */
				jit_insn_store(coder->jitFunction, temp, _ILJitStackItemValue(*stackItem));
				/* Now replace the constant with the new temporary. */
				stack[current] = temp;
				_ILJitStackItemSetValue(*stackItem, temp);
			}
			else if(_ILJitStackItemNeedsDupOnLabel(*stackItem))
			{
				ILJitValue temp = jit_insn_dup(coder->jitFunction,
											   _ILJitStackItemValue(*stackItem));
				stack[current] = temp;
				_ILJitStackItemSetValue(*stackItem, temp);
			}
		}
		label->jitStack = stack;
		label->stackSize = coderStackHeight;
	}
	return 1;
}
Beispiel #2
0
jit_value jit_function::insn_dup(const jit_value& value)
{
	value_wrap(jit_insn_dup(func, value.raw()));
}