Thursday, August 5, 2010

Just In Time Compiler for Managed Platform- Part 6: Put Field and Get Field

Now we have our object on the heap. We need mechanism to putfield and getfield. The operation is very simple indeed.

First we need a helper to get a field index (variable) in the object memory in the heap:


//And also we put the method names in HelperMethods structure


int GetFieldIndex(JavaClass *pTargetClass, Context *pContext, u2 index)
{
CONSTANT_Fieldref_info *pFieldInfo
= (CONSTANT_Fieldref_info *)pContext->pClass->constant_pool[index];

ASSERT(pFieldInfo->tag == CONSTANT_Fieldref);

u2 classIndex = getu2(&((u1 *)pFieldInfo)[1]);
u2 nameAndTypeIndex = getu2(&((u1 *)pFieldInfo)[3]);

CONSTANT_NameAndType_info *pNameTypeInfo
= (CONSTANT_NameAndType_info *) pContext->pClass->constant_pool[nameAndTypeIndex];

ASSERT(pNameTypeInfo->tag == CONSTANT_NameAndType);

u2 nameIndex = getu2(&((u1 *)pNameTypeInfo)[1]);
u2 descIndex = getu2(&((u1 *)pNameTypeInfo)[3]);
CString strFieldName, strFieldDesc;

if(!pContext->pClass->GetStringFromConstPool(nameIndex, strFieldName))
{
ASSERT(FALSE);
return -1;
}

if(!pContext->pClass->GetStringFromConstPool(descIndex, strFieldDesc))
{
ASSERT(FALSE);
return -2;
}

int superClassSize = 0;

JavaClass *pCurClass = pTargetClass;

int fieldIndex = -1;
while(true)
{
fieldIndex = pCurClass->GetFieldIndex(strFieldName, strFieldDesc);
pCurClass = pTargetClass->GetSuperClass();
if(fieldIndex >= 0)
{
fieldIndex += pCurClass ? pCurClass->GetObjectFieldCount() : 0;
break;
}
else
{
if(!pCurClass)
{
break;
}
}
}

ASSERT(fieldIndex>=0);
return fieldIndex;
}


Now we define the method to execute the two instructions. We do not generate code foe this operaions and callback from the generated code since the operation is static and no parsing or instruction execution required-


#define PUT_FIELD_HELPER_INDEX 4
#define GET_FIELD_HELPER_INDEX 5

void PutField(Context *pContext, u2 index)
{
Variable obj=pContext->stack[pContext->stackTop-2];
Variable value=pContext->stack[pContext->stackTop-1];
Variable *pVarList = pContext->pVMEnv->pObjectHeap->GetObjectPointer(obj.object);

JavaClass *pTargetClass = (JavaClass *)pVarList[0].ptrValue;
ASSERT(pTargetClass && pTargetClass->magic == 0xCAFEBABE);

int fieldIndex = GetFieldIndex(pTargetClass, pContext, index);

pVarList[fieldIndex+1]=value;

pContext->stackTop-=2;
}

void GetField(Context *pContext, u2 index)
{
Variable obj=pContext->stack[pContext->stackTop-1];
Variable *pVarList=pContext->pVMEnv->pObjectHeap->GetObjectPointer(obj.object);

JavaClass *pTargetClass = (JavaClass *)pVarList[0].ptrValue;
ASSERT(pTargetClass && pTargetClass->magic == 0xCAFEBABE);

int fieldIndex = GetFieldIndex(pTargetClass, pContext, index);

pContext->stack[pContext->stackTop-1]=pVarList[fieldIndex+1];
}


Now we generate instruction for them. Here is how we do it for putfield:

void EmitCallPutField(u1* code, int &ip, u4 index)
{
u1 c[]={
//((void (*)(Context *pContext, u2 index))pContext->pVMEnv->ppHelperMethods[PUT_FIELD_HELPER_INDEX])(pContext, 0x1234);
0x8B, 0xF4, // mov esi,esp
0x68, 0x00, 0x00, 0x00, 0x00, // push index
0x8B, 0x45, 0x08, // mov eax,dword ptr [pContext]
0x50, // push eax
0x8B, 0x4D, 0x08, // mov ecx,dword ptr [pContext]
0x8B, 0x51, 0x10, // mov edx,dword ptr [ecx+10h]
0x8B, 0x42, 0x08, // mov eax,dword ptr [edx+8]
0x8B, 0x48, 0x10, // mov ecx,dword ptr [eax+10h]
0xFF, 0xD1, // call ecx
0x83, 0xC4, 0x08, // add esp,8
};

memcpy(c+3, &index, sizeof(index));
memcpy(&code[ip], c, sizeof(c));
ip+=sizeof(c);
}

void ExecutePutField(u1* code, int& ip, u2 index)
{
EmitCallPutField(code, ip, index);
}

For getfield we just need to change the method pointer (add 4)

mov ecx,dword ptr [eax+14h] 

So we can assign value to a class field and get that value when we need it. Next we need array handling. Comes next day.

No comments:

Post a Comment