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