Saturday, August 7, 2010

Just In Time Compiler for Managed Platform- Part 7: Native Methods

Execution of native methods are easiest of all methods :D. Since we dont need to generate anything for them - they are already native.

We can not accept any native method for execution- Those should understand the stack. For native methods we fix the stack top to point to actual data- since there is nothing we need to generate- we dont need the clever stack pointer-

The signature of each native method must match the following type signature:

typedef Variable (*NativeMethod)(Context* pContext);


Lets define our helper for native method. And here also we do not deal with machine instruction since there is nothing to parse- (well except the return type of the method)-
u4 ExecuteNativeMethod(Context* pContext, CString strClassName, CString strMethod, CString strDesc)
{
JavaClass *pClass = pContext->pClass;
LOG(_T("Execute NativeMethod %s.%s%s \n"),strClassName , strMethod, strDesc);
CString strSignature= GetNativeMethodSignature(strClassName, strMethod, strDesc);
NativeMethod nativeMethod=pContext->pVMEnv->pNativeMethodProvider->GetNativeMethod(strSignature);

if(nativeMethod == NULL)
{
ASSERT(FALSE);
return -1;
}
else
{
Variable retVal = nativeMethod(pContext);

//if returns then get on stack
if(strDesc.Find(_T(")V")) < 0)
{
if(strDesc.Find(_T(")J")) < 0 && (strDesc.Find(_T(")D")) < 0))
{
//todo validate
pContext->stack[0]=retVal;
}
else
{
pContext->stack[0].intValue=0;
pContext->stack[1]=retVal;
}
}
}
return 0;
}



OK, lets now define a simple native method that adds two numbers:

Variable Add(Context* pContext)
{
Variable returnVal;
//The stack top is right in native methods-
returnVal.intValue
= pContext->stack[pContext->stackTop].intValue + pContext->stack[pContext->stackTop-1].intValue;
return returnVal;
}


Thats all for native methods for now. We'll add some native methods to dynamically load native method-