/*
 * Handle a unary opcode.
 */
static void JITCoder_Unary(ILCoder *coder, int opcode, ILEngineType type)
{
	ILJITCoder *jitCoder = _ILCoderToILJITCoder(coder);
	_ILJitStackItemNew(value);
	ILJitValue result = 0;

	_ILJitStackPop(jitCoder, value);
	switch(opcode)
	{
		case IL_OP_NEG:
		{
			result = jit_insn_neg(jitCoder->jitFunction,
								  _ILJitStackItemValue(value));
		}
		break;

		case IL_OP_NOT:
		{
			result = jit_insn_not(jitCoder->jitFunction,
								  _ILJitStackItemValue(value));
		}
		break;

		case IL_OP_CKFINITE:
		{
			/* Check the stack Top-most F value to see if it is finite */
			result = jit_insn_is_finite(jitCoder->jitFunction,
										_ILJitStackItemValue(value));
		}
		break;
	}
	_ILJitStackPushValue(jitCoder, result);
}
Exemple #2
0
/*
 * Inline function to get the character at the specified indexe in a
 * string.
 */
static int _ILJitSystemStringChars(ILJITCoder *jitCoder,
								   ILMethod *method,
								   ILCoderMethodInfo *methodInfo,
								   ILJitStackItem *args,
								   ILInt32 numArgs)
{
	ILJitFunction jitFunction = ILJitFunctionFromILMethod(method);
	ILClass *stringClass = ILMethod_Owner(method);
	ILJitValue length;
	ILJitValue stringBase;
	ILJitValue returnValue;

	if(!jitFunction)
	{
		/* We need to layout the class first. */
		if(!_LayoutClass(ILExecThreadCurrent(), stringClass))
		{
			return 0;
		}
		if(!(jitFunction = ILJitFunctionFromILMethod(method)))
		{
			return 0;
		}
	}

#if !defined(IL_CONFIG_REDUCE_CODE) && !defined(IL_WITHOUT_TOOLS) && defined(_IL_JIT_ENABLE_DEBUG)
	if(jitCoder->flags & IL_CODER_FLAG_STATS)
	{
		ILMutexLock(globalTraceMutex);
		fprintf(stdout, "Inline System.String::get_Chars\n");
		ILMutexUnlock(globalTraceMutex);
	}
#endif

	_ILJitStackItemCheckNull(jitCoder, args[0]);
	length = _ILJitStringGetLength(jitCoder->jitFunction,
								   _ILJitStackItemValue(args[0]));
	JITC_START_CHECK_STRING_INDEX(jitCoder, length, _ILJitStackItemValue(args[1]))
	stringBase = _ILJitStringGetStart(jitCoder->jitFunction,
									  _ILJitStackItemValue(args[0]));
	returnValue = jit_insn_load_elem(jitCoder->jitFunction,
									 stringBase,
									 _ILJitStackItemValue(args[1]),
									 _IL_JIT_TYPE_CHAR);
	JITC_END_CHECK_STRING_INDEX(jitCoder)

	_ILJitStackPushValue(jitCoder, returnValue);
	return 1;
}
/*
 * Merge the current jitStack status with the one saved in the label.
 */
static int _ILJitLabelMergeStack(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))
	{
		/* Verify that the stack sizes match. */
		if(coderStackHeight != label->stackSize)
		{
			fprintf(stdout, "Stack sizes don't match!\n");
			/* return 0; */
		}
		if(coderStackHeight > 0)
		{
			int current = 0;

			/* Now save the current stack state. */
			for(current = 0; current < coderStackHeight; current++)
			{
				ILJitStackItem *stackItem = _ILJitStackItemGet(coder, coderStackBase + current);

				if(_ILJitStackItemValue(*stackItem) != label->jitStack[current])
				{
					/* store the changed value to the saved stack. */
					jit_insn_store(coder->jitFunction,
								   label->jitStack[current],
								   _ILJitStackItemValue(*stackItem));
				}
			}
		}
	}
	return 1;
}
/*
 * Output the start of a table-based switch statement.
 */
static void JITCoder_SwitchStart(ILCoder *coder, ILUInt32 numEntries)
{
	ILJITCoder *jitCoder = _ILCoderToILJITCoder(coder);
	_ILJitStackItemNew(value);

	_ILJitStackPop(jitCoder, value);
	jitCoder->numSwitch = 0;
	jitCoder->maxSwitch = numEntries;
	jitCoder->switchValue = _ILJitStackItemValue(value);
}
/*
 * Output a comparison instruction.
 */
static void JITCoder_Compare(ILCoder *coder, int opcode,
				   		     ILEngineType type1, ILEngineType type2,
							 int invertTest)
{
	ILJITCoder *jitCoder = _ILCoderToILJITCoder(coder);
	_ILJitStackItemNew(value2);
	_ILJitStackItemNew(value1);
	ILJitValue temp;

	_ILJitStackPop(jitCoder, value2);
	_ILJitStackPop(jitCoder, value1);
	temp = OutputCompare(jitCoder, opcode,
						 &(_ILJitStackItemValue(value1)),
						 &(_ILJitStackItemValue(value2)));
	if(invertTest)
	{
		temp = jit_insn_to_not_bool(jitCoder->jitFunction, temp);
	}
	else
	{
		temp = jit_insn_to_bool(jitCoder->jitFunction, temp);
	}
	_ILJitStackPushValue(jitCoder, temp);
}
/*
 * 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;
}
/*
 * Handle a binary opcode.
 */
static void JITCoder_Binary(ILCoder *coder, int opcode,
							ILEngineType type1, ILEngineType type2)
{
	ILJITCoder *jitCoder = _ILCoderToILJITCoder(coder);
	_ILJitStackItemNew(value2);
	_ILJitStackItemNew(value1);
	ILJitValue result = 0;

	_ILJitStackPop(jitCoder, value2);
	_ILJitStackPop(jitCoder, value1);
	switch(opcode)
	{
		case IL_OP_ADD:
		{
			AdjustMixedBinary(jitCoder, 0,
							  &(_ILJitStackItemValue(value1)),
							  &(_ILJitStackItemValue(value2)));
			result = jit_insn_add(jitCoder->jitFunction,
								  _ILJitStackItemValue(value1),
								  _ILJitStackItemValue(value2));
		}
		break;

		case IL_OP_ADD_OVF:
		{
			AdjustMixedBinary(jitCoder, 0,
							  &(_ILJitStackItemValue(value1)),
							  &(_ILJitStackItemValue(value2)));
			result = jit_insn_add_ovf(jitCoder->jitFunction,
									  _ILJitStackItemValue(value1),
									  _ILJitStackItemValue(value2));
		}
		break;

		case IL_OP_ADD_OVF_UN:
		{
			AdjustMixedBinary(jitCoder, 1,
							  &(_ILJitStackItemValue(value1)),
							  &(_ILJitStackItemValue(value2)));
			result = jit_insn_add_ovf(jitCoder->jitFunction,
									 _ILJitStackItemValue(value1),
									 _ILJitStackItemValue(value2));
		}
		break;

		case IL_OP_SUB:
		{
			AdjustMixedBinary(jitCoder, 0,
							  &(_ILJitStackItemValue(value1)),
							  &(_ILJitStackItemValue(value2)));
			result = jit_insn_sub(jitCoder->jitFunction,
								  _ILJitStackItemValue(value1),
								  _ILJitStackItemValue(value2));
		}
		break;

		case IL_OP_SUB_OVF:
		{
			AdjustMixedBinary(jitCoder, 0,
							  &(_ILJitStackItemValue(value1)),
							  &(_ILJitStackItemValue(value2)));
			result = jit_insn_sub_ovf(jitCoder->jitFunction,
									  _ILJitStackItemValue(value1),
									  _ILJitStackItemValue(value2));
		}
		break;

		case IL_OP_SUB_OVF_UN:
		{
			AdjustMixedBinary(jitCoder, 1,
							  &(_ILJitStackItemValue(value1)),
							  &(_ILJitStackItemValue(value2)));
			result = jit_insn_sub_ovf(jitCoder->jitFunction,
									  _ILJitStackItemValue(value1),
									  _ILJitStackItemValue(value2));
		}
		break;

		case IL_OP_MUL:
		{
			AdjustMixedBinary(jitCoder, 0,
							  &(_ILJitStackItemValue(value1)),
							  &(_ILJitStackItemValue(value2)));
			result = jit_insn_mul(jitCoder->jitFunction,
								  _ILJitStackItemValue(value1),
								  _ILJitStackItemValue(value2));
		}
		break;

		case IL_OP_MUL_OVF:
		{
			AdjustMixedBinary(jitCoder, 0,
							  &(_ILJitStackItemValue(value1)),
							  &(_ILJitStackItemValue(value2)));
			result = jit_insn_mul_ovf(jitCoder->jitFunction,
									  _ILJitStackItemValue(value1),
									  _ILJitStackItemValue(value2));
		}
		break;

		case IL_OP_MUL_OVF_UN:
		{
			AdjustMixedBinary(jitCoder, 1,
							  &(_ILJitStackItemValue(value1)),
							  &(_ILJitStackItemValue(value2)));
			result = jit_insn_mul_ovf(jitCoder->jitFunction,
									  _ILJitStackItemValue(value1),
									  _ILJitStackItemValue(value2));
		}
		break;

		case IL_OP_DIV:
		{
			AdjustMixedBinary(jitCoder, 0,
							  &(_ILJitStackItemValue(value1)),
							  &(_ILJitStackItemValue(value2)));
			result = jit_insn_div(jitCoder->jitFunction,
								  _ILJitStackItemValue(value1),
								  _ILJitStackItemValue(value2));
		}
		break;

		case IL_OP_DIV_UN:
		{
			AdjustMixedBinary(jitCoder, 1,
							  &(_ILJitStackItemValue(value1)),
							  &(_ILJitStackItemValue(value2)));
			result = jit_insn_div(jitCoder->jitFunction,
								  _ILJitStackItemValue(value1),
								  _ILJitStackItemValue(value2));
		}
		break;

		case IL_OP_REM:
		{
			AdjustMixedBinary(jitCoder, 0,
							  &(_ILJitStackItemValue(value1)),
							  &(_ILJitStackItemValue(value2)));
			result = jit_insn_rem(jitCoder->jitFunction,
								  _ILJitStackItemValue(value1),
								  _ILJitStackItemValue(value2));
		}
		break;

		case IL_OP_REM_UN:
		{
			AdjustMixedBinary(jitCoder, 1,
							  &(_ILJitStackItemValue(value1)),
							  &(_ILJitStackItemValue(value2)));
			result = jit_insn_rem(jitCoder->jitFunction,
								  _ILJitStackItemValue(value1),
								  _ILJitStackItemValue(value2));
		}
		break;

		case IL_OP_AND:
		{
			result = jit_insn_and(jitCoder->jitFunction,
								  _ILJitStackItemValue(value1),
								  _ILJitStackItemValue(value2));
		}
		break;

		case IL_OP_OR:
		{
			result = jit_insn_or(jitCoder->jitFunction,
								 _ILJitStackItemValue(value1),
								 _ILJitStackItemValue(value2));
		}
		break;

		case IL_OP_XOR:
		{
			result = jit_insn_xor(jitCoder->jitFunction,
								  _ILJitStackItemValue(value1),
								  _ILJitStackItemValue(value2));
		}
		break;
		
		default:
		{
			return;
		}
	}
	_ILJitStackPushValue(jitCoder, result);
}
/*
 * Handle a shift opcode.
 */
static void JITCoder_Shift(ILCoder *coder, int opcode,
						   ILEngineType type1, ILEngineType type2)
{
	ILJITCoder *jitCoder = _ILCoderToILJITCoder(coder);
	_ILJitStackItemNew(value2);
	_ILJitStackItemNew(value1);
	ILJitValue result = 0;

	_ILJitStackPop(jitCoder, value2);
	_ILJitStackPop(jitCoder, value1);
	/* Determine how to perform the operation */
	switch(opcode)
	{
		case IL_OP_SHL:
		{
			AdjustMixedBinary(jitCoder,
							  0,
							  &(_ILJitStackItemValue(value1)),
							  &(_ILJitStackItemValue(value2)));
			result = jit_insn_shl(jitCoder->jitFunction,
								  _ILJitStackItemValue(value1),
								  _ILJitStackItemValue(value2));
		}
		break;

		case IL_OP_SHR:
		{
			AdjustMixedBinary(jitCoder,
							  0,
							  &(_ILJitStackItemValue(value1)),
							  &(_ILJitStackItemValue(value2)));
			result= jit_insn_shr(jitCoder->jitFunction,
								 _ILJitStackItemValue(value1),
								 _ILJitStackItemValue(value2));
		}
		break;

		case IL_OP_SHR_UN:
		{
			AdjustMixedBinary(jitCoder,
							  1,
							  &(_ILJitStackItemValue(value1)),
							  &(_ILJitStackItemValue(value2)));
			result = jit_insn_shr(jitCoder->jitFunction,
								  _ILJitStackItemValue(value1),
								  _ILJitStackItemValue(value2));
		}
		break;
	}
	_ILJitStackPushValue(jitCoder, result);
}
/*
 * Handle a binary opcode when pointer arithmetic is involved.
 */
static void JITCoder_BinaryPtr(ILCoder *coder, int opcode,
							   ILEngineType type1, ILEngineType type2)
{
	ILJITCoder *jitCoder = _ILCoderToILJITCoder(coder);
	int value1IsPointer = _IL_JIT_ENGINE_TYPE_IS_POINTER(type1);
	int value2IsPointer = _IL_JIT_ENGINE_TYPE_IS_POINTER(type2);
	_ILJitStackItemNew(value2);
	_ILJitStackItemNew(value1);
	ILJitValue result = 0;

	_ILJitStackPop(jitCoder, value2);
	_ILJitStackPop(jitCoder, value1);
	switch(opcode)
	{
		case IL_OP_ADD:
		{
			result = jit_insn_add(jitCoder->jitFunction,
								  _ILJitStackItemValue(value1),
								  _ILJitStackItemValue(value2));
		}
		case IL_OP_ADD_OVF_UN:
		{
			result = jit_insn_add_ovf(jitCoder->jitFunction,
									  _ILJitStackItemValue(value1),
									  _ILJitStackItemValue(value2));
		}
		break;

		case IL_OP_SUB:
		{
			result = jit_insn_sub(jitCoder->jitFunction,
								  _ILJitStackItemValue(value1),
								  _ILJitStackItemValue(value2));
		}
		case IL_OP_SUB_OVF_UN:
		{
			result = jit_insn_sub_ovf(jitCoder->jitFunction,
									  _ILJitStackItemValue(value1),
									  _ILJitStackItemValue(value2));
		}
		break;
	}
	if(value1IsPointer && value2IsPointer)
	{
		/* We can't keep the reference information for this case. */
		_ILJitStackPushValue(jitCoder, result);
	}
	else if(value1IsPointer)
	{
		/* Keep the reference information for value1. */
		_ILJitStackItemSetValue(value1, result);
		_ILJitStackPush(jitCoder, value1);
	}
	else if(value2IsPointer)
	{
		/* Keep the reference information for value2. */
		_ILJitStackItemSetValue(value2, result);
		_ILJitStackPush(jitCoder, value2);
	}
	else
	{
		/* There is no pointer involved in this operation. */
		_ILJitStackPushValue(jitCoder, result);
	}
}
/*
 * Output a branch instruction using a JIT coder.
 */
static void JITCoder_Branch(ILCoder *coder, int opcode, ILUInt32 dest,
				   		    ILEngineType type1, ILEngineType type2)
{
	ILJITCoder *jitCoder = _ILCoderToILJITCoder(coder);
	ILJITLabel *label = 0;
	ILJitValue temp = 0;
	_ILJitStackItemNew(value2);
	_ILJitStackItemNew(value1);

#if !defined(IL_CONFIG_REDUCE_CODE) && !defined(IL_WITHOUT_TOOLS)
	if (jitCoder->flags & IL_CODER_FLAG_STATS)
	{
		ILMutexLock(globalTraceMutex);
		fprintf(stdout,
			"Branch: %i\n", 
			dest);
		ILMutexUnlock(globalTraceMutex);
	}
#endif
	/* Determine what form of branch to use */
	switch(opcode)
	{
		case IL_OP_BR:
		case IL_OP_BR_S:
		case IL_OP_LEAVE:
		case IL_OP_LEAVE_S:
		{
			/* Unconditional branch */
			label = _ILJitLabelGet(jitCoder, dest, _IL_JIT_LABEL_NORMAL);

			jit_insn_branch(jitCoder->jitFunction, &(label->label));
		}
		break;

		case IL_OP_BRTRUE_S:
		case IL_OP_BRTRUE:
		{
			/* Branch if the top-most stack item is true */
			_ILJitStackPop(jitCoder, value1);
			label = _ILJitLabelGet(jitCoder, dest, _IL_JIT_LABEL_NORMAL);

			jit_insn_branch_if(jitCoder->jitFunction,
							   _ILJitStackItemValue(value1),
							   &(label->label));
		}
		break;

		case IL_OP_BRFALSE_S:
		case IL_OP_BRFALSE:
		{
			/* Branch if the top-most stack item is false */
			_ILJitStackPop(jitCoder, value1);
			label = _ILJitLabelGet(jitCoder, dest, _IL_JIT_LABEL_NORMAL);

			jit_insn_branch_if_not(jitCoder->jitFunction,
								   _ILJitStackItemValue(value1),
								   &(label->label));
		}
		break;

		default:
		{
			_ILJitStackPop(jitCoder, value2);
			_ILJitStackPop(jitCoder, value1);
			label = _ILJitLabelGet(jitCoder, dest, _IL_JIT_LABEL_NORMAL);

			switch(opcode)
			{
				case IL_OP_BEQ:
				case IL_OP_BEQ_S:
				{
					/* Equality testing branch */
					temp = OutputCompare(jitCoder, IL_OP_BEQ,
										 &(_ILJitStackItemValue(value1)),
										 &(_ILJitStackItemValue(value2)));
					jit_insn_branch_if(jitCoder->jitFunction, temp, 
									   &(label->label));
				}
				break;

				case IL_OP_BNE_UN:
				case IL_OP_BNE_UN_S:
				{
					/* Unsigned inequality testing branch */
					temp = OutputCompare(jitCoder, IL_OP_BNE_UN,
										 &(_ILJitStackItemValue(value1)),
										 &(_ILJitStackItemValue(value2)));
					jit_insn_branch_if(jitCoder->jitFunction, temp, 
									   &(label->label));
				}
				break;

				case IL_OP_BGT:
				case IL_OP_BGT_S:
				{
					/* Signed greater than testing branch */
					temp = OutputCompare(jitCoder, IL_OP_BGT,
										 &(_ILJitStackItemValue(value1)),
										 &(_ILJitStackItemValue(value2)));
					jit_insn_branch_if(jitCoder->jitFunction, temp,
									   &(label->label));
				}
				break;

				case IL_OP_BGT_UN:
				case IL_OP_BGT_UN_S:
				{
					/* Unsigned greater than testing branch */
					temp = OutputCompare(jitCoder, IL_OP_BGT_UN,
										 &(_ILJitStackItemValue(value1)),
										 &(_ILJitStackItemValue(value2)));
					jit_insn_branch_if(jitCoder->jitFunction, temp,
									   &(label->label));
				}
				break;

				case IL_OP_BGE:
				case IL_OP_BGE_S:
				{
					/* Signed greater than or equal testing branch */
					temp = OutputCompare(jitCoder, IL_OP_BGE,
										 &(_ILJitStackItemValue(value1)),
										 &(_ILJitStackItemValue(value2)));
					jit_insn_branch_if(jitCoder->jitFunction, temp,
									   &(label->label));
				}
				break;

				case IL_OP_BGE_UN:
				case IL_OP_BGE_UN_S:
				{
					/* Unsigned greater than or equal testing branch */
					temp = OutputCompare(jitCoder, IL_OP_BGE_UN,
										 &(_ILJitStackItemValue(value1)),
										 &(_ILJitStackItemValue(value2)));
					jit_insn_branch_if(jitCoder->jitFunction, temp,
									   &(label->label));
				}
				break;

				case IL_OP_BLT:
				case IL_OP_BLT_S:
				{
					/* Signed less than testing branch */
					temp = OutputCompare(jitCoder, IL_OP_BLT,
										 &(_ILJitStackItemValue(value1)),
										 &(_ILJitStackItemValue(value2)));
					jit_insn_branch_if(jitCoder->jitFunction, temp,
									   &(label->label));
				}
				break;

				case IL_OP_BLT_UN:
				case IL_OP_BLT_UN_S:
				{
					/* Unsigned less than testing branch */
					temp = OutputCompare(jitCoder, IL_OP_BLT_UN,
										 &(_ILJitStackItemValue(value1)),
										 &(_ILJitStackItemValue(value2)));
					jit_insn_branch_if(jitCoder->jitFunction, temp,
									   &(label->label));
				}
				break;

				case IL_OP_BLE:
				case IL_OP_BLE_S:
				{
					/* Signed less than or equal testing branch */
					temp = OutputCompare(jitCoder, IL_OP_BLE,
										 &(_ILJitStackItemValue(value1)),
										 &(_ILJitStackItemValue(value2)));
					jit_insn_branch_if(jitCoder->jitFunction, temp,
									   &(label->label));
				}
				break;

				case IL_OP_BLE_UN:
				case IL_OP_BLE_UN_S:
				{
					/* Unsigned less than or equal testing branch */
					temp = OutputCompare(jitCoder, IL_OP_BLE_UN,
										 &(_ILJitStackItemValue(value1)),
										 &(_ILJitStackItemValue(value2)));
					jit_insn_branch_if(jitCoder->jitFunction, temp,
									   &(label->label));
				}
				break;
			}
		}
		break;
	}

}
Exemple #11
0
/*
 * Inline function to create a new string with the given length 
 */
static int _ILJitSystemStringNew(ILJITCoder *jitCoder,
								 ILMethod *method,
								 ILCoderMethodInfo *methodInfo,
								 ILJitStackItem *args,
								 ILInt32 numArgs)
{
	ILJitFunction jitFunction = ILJitFunctionFromILMethod(method);
	ILClass *stringClass = ILMethod_Owner(method);
	ILJitValue newString;
	ILJitValue callArgs[2];

	if(!jitFunction)
	{
		/* We need to layout the class first. */
		if(!_LayoutClass(ILExecThreadCurrent(), stringClass))
		{
			return 0;
		}
		if(!(jitFunction = ILJitFunctionFromILMethod(method)))
		{
			return 0;
		}
	}

#if !defined(IL_CONFIG_REDUCE_CODE) && !defined(IL_WITHOUT_TOOLS) && defined(_IL_JIT_ENABLE_DEBUG)
	if(jitCoder->flags & IL_CODER_FLAG_STATS)
	{
		ILMutexLock(globalTraceMutex);
		fprintf(stdout, "Inline System.String::NewString\n");
		ILMutexUnlock(globalTraceMutex);
	}
#endif

	/* We call the alloc functions. */
	/* They thow an out of memory exception so we don't need to care. */
	callArgs[0] = jit_value_create_nint_constant(jitCoder->jitFunction,
												 _IL_JIT_TYPE_VPTR,
												 (jit_nint)stringClass);
	if(!callArgs[0])
	{
		return 0;
	}
	callArgs[1] = _ILJitValueConvertImplicit(jitCoder->jitFunction,
						 					 _ILJitStackItemValue(args[0]),
											 _IL_JIT_TYPE_UINT32);
	if(!callArgs[1])
	{
		return 0;
	}
	newString = jit_insn_call_native(jitCoder->jitFunction,
									 "_ILJitStringAlloc",
									 _ILJitStringAlloc,
									 _ILJitSignature_ILJitStringAlloc,
				 					 callArgs, 2, 0);
	if(!newString)
	{
		return 0;
	}

	_ILJitStackPushValue(jitCoder, newString);
	return 1;
}