void Type_Init() { U32 i; // Build all the types needed by the interpreter. numInitTypes = sizeof(typeInit) / sizeof(typeInit[0]); types = (tMD_TypeDef**)mallocForever(numInitTypes * sizeof(tMD_TypeDef*)); for (i=0; i<numInitTypes; i++) { if (typeInit[i].assemblyName != NULL) { // Normal type initialisation types[i] = MetaData_GetTypeDefFromFullName(typeInit[i].assemblyName, typeInit[i].nameSpace, typeInit[i].name); // For the pre-defined system types, fill in the well-known memory sizes types[i]->stackType = typeInit[i].stackType; types[i]->stackSize = typeInit[i].stackSize; types[i]->arrayElementSize = typeInit[i].arrayElementSize; types[i]->instanceMemSize = typeInit[i].instanceMemSize; } } for (i=0; i<numInitTypes; i++) { if (typeInit[i].assemblyName != NULL) { MetaData_Fill_TypeDef(types[i], NULL, NULL); } else { // Special initialisation for arrays of particular types. types[i] = Type_GetArrayTypeDef(types[(U32)(typeInit[i].name)], NULL, NULL); } } CorLibDone = 1; }
U32 Type_IsDerivedFromOrSame(tMD_TypeDef *pBaseType, tMD_TypeDef *pTestType) { while (pTestType != NULL) { if (pTestType == pBaseType) { return 1; } MetaData_Fill_TypeDef(pTestType, NULL, NULL); pTestType = pTestType->pParent; } return 0; }
tMD_MethodDef* MetaData_GetMethodDefFromDefRefOrSpec(tMetaData *pMetaData, IDX_TABLE token, tMD_TypeDef **ppClassTypeArgs, tMD_TypeDef **ppMethodTypeArgs) { void *pTableEntry; pTableEntry = MetaData_GetTableRow(pMetaData, token); if (((tMDC_ToMethodDef*)pTableEntry)->pMethodDef != NULL) { return ((tMDC_ToMethodDef*)pTableEntry)->pMethodDef; } switch (TABLE_ID(token)) { case MD_TABLE_METHODDEF: ((tMDC_ToMethodDef*)pTableEntry)->pMethodDef = (tMD_MethodDef*)pTableEntry; return (tMD_MethodDef*)pTableEntry; case MD_TABLE_MEMBERREF: { tMD_MemberRef *pMemberRef; pMemberRef = (tMD_MemberRef*)pTableEntry; switch (TABLE_ID(pMemberRef->class_)) { case MD_TABLE_TYPEREF: case MD_TABLE_TYPESPEC: { tMD_TypeDef *pTypeDef; tMD_MethodDef *pMethodDef; pTypeDef = MetaData_GetTypeDefFromDefRefOrSpec(pMetaData, pMemberRef->class_, ppClassTypeArgs, ppMethodTypeArgs); MetaData_Fill_TypeDef(pTypeDef, NULL, NULL); pMethodDef = FindMethodInType(pTypeDef, pMemberRef->name, pMetaData, pMemberRef->signature, pTypeDef->ppClassTypeArgs, ppMethodTypeArgs); //pMethodDef->pMethodDef = pMethodDef; return pMethodDef; } default: Crash("MetaData_GetMethodDefFromMethodDefOrRef(): Cannot handle pMemberRef->class_=0x%08x", pMemberRef->class_); } } case MD_TABLE_METHODSPEC: { tMD_MethodSpec *pMethodSpec; tMD_MethodDef *pMethodDef; pMethodSpec = (tMD_MethodSpec*)pTableEntry; pMethodDef = Generics_GetMethodDefFromSpec(pMethodSpec, ppClassTypeArgs, ppMethodTypeArgs); // Note: Cannot cache the MethodDef from the MethodSpec, as class generic arguments // may be different. return pMethodDef; } } Crash("MetaData_GetMethodDefFromMethodDefOrRef(): Cannot handle token: 0x%08x", token); FAKE_RETURN; }
void MetaData_Fill_FieldDef(tMD_TypeDef *pParentType, tMD_FieldDef *pFieldDef, U32 memOffset, tMD_TypeDef **ppClassTypeArgs) { U32 sigLength; PTR sig; tMetaData *pMetaData; //log_f(5,"MetaData_Fill_FieldDef %s.%s\n", pParentType->name,pFieldDef->name); pFieldDef->pParentType = pParentType; sig = MetaData_GetBlob(pFieldDef->signature, &sigLength); MetaData_DecodeSigEntry(&sig); // First entry always 0x06 pFieldDef->pType = Type_GetTypeFromSig(pFieldDef->pMetaData, &sig, ppClassTypeArgs, NULL); if (pFieldDef->pType == NULL) { // If the field is a core generic type definition, then we can't do anything more return; } MetaData_Fill_TypeDef(pFieldDef->pType, NULL, NULL); // A check for 0 is done so if a type has a field of it's own type it is handled correctly. pFieldDef->memSize = (pFieldDef->pType->stackSize>0)?pFieldDef->pType->stackSize:sizeof(void*); pFieldDef->memOffset = memOffset; pFieldDef->pFieldDef = pFieldDef; pMetaData = pFieldDef->pMetaData; if (FIELD_HASFIELDRVA(pFieldDef)) { U32 i, top; // Field has RVA, so load it from FieldRVA top = pMetaData->tables.numRows[MD_TABLE_FIELDRVA]; for (i=1; i<=top; i++) { tMD_FieldRVA *pFieldRVA; pFieldRVA = (tMD_FieldRVA*)MetaData_GetTableRow(pMetaData, MAKE_TABLE_INDEX(MD_TABLE_FIELDRVA, i)); if (pFieldRVA->field == pFieldDef->tableIndex) { pFieldDef->pMemory = (PTR)pFieldRVA->rva; break; } } } else if (FIELD_ISLITERAL(pFieldDef)) { // Field is literal, so make pMemory point to the value signature U32 i, top; top = pMetaData->tables.numRows[MD_TABLE_CONSTANT]; for (i=1; i<=top; i++) { tMD_Constant *pConst; pConst = (tMD_Constant*)MetaData_GetTableRow(pMetaData, MAKE_TABLE_INDEX(MD_TABLE_CONSTANT, i)); if (pConst->parent == pFieldDef->tableIndex) { // Found the field pFieldDef->pMemory = (PTR)pConst; break; } } } }
tMD_TypeDef* Generics_GetGenericTypeFromSig (tMetaData *pMetaData, SIG *pSig, tMD_TypeDef **ppCallingClassTypeArgs, tMD_TypeDef **ppCallingMethodTypeArgs) { tMD_TypeDef *pCoreType, *pRet; U32 numTypeArgs, i; tMD_TypeDef **ppTypeArgs; pCoreType = Type_GetTypeFromSig(pMetaData, pSig, ppCallingClassTypeArgs, ppCallingMethodTypeArgs); MetaData_Fill_TypeDef(pCoreType, ppCallingClassTypeArgs, ppCallingMethodTypeArgs); //NULL, NULL); numTypeArgs = MetaData_DecodeSigEntry(pSig); ppTypeArgs = (tMD_TypeDef**)malloc(numTypeArgs * sizeof(tMD_TypeDef*)); for (i=0; i<numTypeArgs; i++) { ppTypeArgs[i] = Type_GetTypeFromSig(pMetaData, pSig, ppCallingClassTypeArgs, ppCallingMethodTypeArgs); if (ppTypeArgs[i] != NULL) { MetaData_Fill_TypeDef(ppTypeArgs[i], NULL, NULL); } } pRet = Generics_GetGenericTypeFromCoreType(pCoreType, numTypeArgs, ppTypeArgs); free(ppTypeArgs); return pRet; }
static tMD_FieldDef* FindFieldInType(tMD_TypeDef *pTypeDef, STRING name) { U32 i; MetaData_Fill_TypeDef(pTypeDef, NULL, NULL); for (i=0; i<pTypeDef->numFields; i++) { if (strcmp(pTypeDef->ppFields[i]->name, name) == 0) { return pTypeDef->ppFields[i]; } } Crash("FindFieldInType(): Cannot find field '%s' in type %s.%s", name, pTypeDef->nameSpace, pTypeDef->name); FAKE_RETURN; }
U32 Type_IsValueType(tMD_TypeDef *pTypeDef) { // If this type is an interface, then return 0 if (TYPE_ISINTERFACE(pTypeDef)) { return 0; } // If this type is Object or ValueType then return an answer if (strcmp(pTypeDef->nameSpace, "System") == 0) { if (strcmp(pTypeDef->name, "ValueType") == 0) { return 1; } if (strcmp(pTypeDef->name, "Object") == 0) { return 0; } } // Return the isValueType determined by parent type pTypeDef = MetaData_GetTypeDefFromDefRefOrSpec(pTypeDef->pMetaData, pTypeDef->extends, NULL, NULL); MetaData_Fill_TypeDef(pTypeDef, NULL, NULL); return pTypeDef->isValueType; }
// Return pointer to the relevant Def structure. // pObjectType returns: // 0 - tMD_TypeDef // 1 - tMD_MethodDef // 2 - tMD_FieldDef // (These link up with the JIT_LOADTOKEN_* opcodes) PTR MetaData_GetTypeMethodField(tMetaData *pMetaData, IDX_TABLE token, U32 *pObjectType, tMD_TypeDef **ppClassTypeArgs, tMD_TypeDef **ppMethodTypeArgs) { switch (TABLE_ID(token)) { case MD_TABLE_TYPEDEF: case MD_TABLE_TYPEREF: case MD_TABLE_TYPESPEC: { tMD_TypeDef *pTypeDef; pTypeDef = MetaData_GetTypeDefFromDefRefOrSpec(pMetaData, token, ppClassTypeArgs, ppMethodTypeArgs); MetaData_Fill_TypeDef(pTypeDef, NULL, NULL); *pObjectType = 0; return (PTR)pTypeDef; } case MD_TABLE_METHODDEF: method: { tMD_MethodDef *pMethodDef; pMethodDef = MetaData_GetMethodDefFromDefRefOrSpec(pMetaData, token, ppClassTypeArgs, ppMethodTypeArgs); if (pMethodDef->isFilled == 0) { tMD_TypeDef *pTypeDef; pTypeDef = MetaData_GetTypeDefFromMethodDef(pMethodDef); MetaData_Fill_TypeDef(pTypeDef, NULL, NULL); } *pObjectType = 1; return (PTR)pMethodDef; } case MD_TABLE_FIELDDEF: field: { tMD_FieldDef *pFieldDef; pFieldDef = MetaData_GetFieldDefFromDefOrRef(pMetaData, token, ppClassTypeArgs, ppMethodTypeArgs); if (pFieldDef->pParentType == NULL) { tMD_TypeDef *pTypeDef; pTypeDef = MetaData_GetTypeDefFromFieldDef(pFieldDef); MetaData_Fill_TypeDef(pTypeDef, NULL, NULL); } *pObjectType = 2; return (PTR)pFieldDef; } case MD_TABLE_MEMBERREF: { tMD_MemberRef *pMemberRef; SIG sig; pMemberRef = (tMD_MemberRef*)MetaData_GetTableRow(pMetaData, token); sig = MetaData_GetBlob(pMemberRef->signature, NULL); if (*(U8*)sig == 0x06) { // Field goto field; } else { // Method goto method; } } } Crash("MetaData_GetTypeMethodField(): Cannot handle token: 0x%08x", token); FAKE_RETURN; }
void MetaData_Fill_MethodDef(tMD_TypeDef *pParentType, tMD_MethodDef *pMethodDef, tMD_TypeDef **ppClassTypeArgs, tMD_TypeDef **ppMethodTypeArgs) { SIG sig; U32 i, entry, totalSize; pMethodDef->pParentType = pParentType; pMethodDef->pMethodDef = pMethodDef; pMethodDef->isFilled = 1; if (pMethodDef->isGenericDefinition) { // Generic definition method, so can't do any more. log_f(3, "Loaded Generic Method: %s.%s.%s()\n", pParentType->nameSpace, pParentType->name, pMethodDef->name); return; } sig = MetaData_GetBlob(pMethodDef->signature, NULL); entry = MetaData_DecodeSigEntry(&sig); if (entry & SIG_METHODDEF_GENERIC) { // Has generic parameters. Read how many, but don't care about the answer MetaData_DecodeSigEntry(&sig); } pMethodDef->numberOfParameters = MetaData_DecodeSigEntry(&sig) + (METHOD_ISSTATIC(pMethodDef)?0:1); pMethodDef->pReturnType = Type_GetTypeFromSig(pMethodDef->pMetaData, &sig, ppClassTypeArgs, ppMethodTypeArgs); if (pMethodDef->pReturnType != NULL) { MetaData_Fill_TypeDef(pMethodDef->pReturnType, NULL, NULL); } pMethodDef->pParams = (tParameter*)malloc(pMethodDef->numberOfParameters * sizeof(tParameter)); totalSize = 0; if (!METHOD_ISSTATIC(pMethodDef)) { // Fill in parameter info for the 'this' pointer pMethodDef->pParams->offset = 0; if (pParentType->isValueType) { // If this is a value-type then the 'this' pointer is actually an IntPtr to the value-type's location pMethodDef->pParams->size = 4; pMethodDef->pParams->pTypeDef = types[TYPE_SYSTEM_INTPTR]; } else { pMethodDef->pParams->size = 4; pMethodDef->pParams->pTypeDef = pParentType; } totalSize = 4; } for (i=totalSize>>2; i<pMethodDef->numberOfParameters; i++) { tMD_TypeDef *pTypeDef; U32 size; pTypeDef = Type_GetTypeFromSig(pMethodDef->pMetaData, &sig, ppClassTypeArgs, ppMethodTypeArgs); //if (pTypeDef != NULL) { MetaData_Fill_TypeDef(pTypeDef, NULL, NULL); size = pTypeDef->stackSize; //} else { // // If this method has generic-type-argument arguments, then we can't do anything very sensible yet // size = 0; //} pMethodDef->pParams[i].pTypeDef = pTypeDef; pMethodDef->pParams[i].offset = totalSize; pMethodDef->pParams[i].size = size; totalSize += size; } pMethodDef->parameterStackSize = totalSize; log_f(3, "Loaded Method %s.%s::%s \n", pParentType->nameSpace, pParentType->name, pMethodDef->name); }
void MetaData_Fill_TypeDef_(tMD_TypeDef *pTypeDef, tMD_TypeDef **ppClassTypeArgs, tMD_TypeDef **ppMethodTypeArgs) { IDX_TABLE firstIdx, lastIdx, token; U32 instanceMemSize, staticMemSize, virtualOfs, i, j; tMetaData *pMetaData; tMD_TypeDef *pParent; pMetaData = pTypeDef->pMetaData; pTypeDef->isFilled = 1; pTypeDef->pTypeDef = pTypeDef; pTypeDef->pParent = MetaData_GetTypeDefFromDefRefOrSpec(pMetaData, pTypeDef->extends, ppClassTypeArgs, ppMethodTypeArgs); pParent = pTypeDef->pParent; if (pParent != NULL) { MetaData_Fill_TypeDef(pParent, NULL, NULL); virtualOfs = pParent->numVirtualMethods; } else { virtualOfs = 0; } pTypeDef->isValueType = (U8)Type_IsValueType(pTypeDef); // If not primed, then work out how many methods & fields there are. if (!pTypeDef->isPrimed) { // Methods lastIdx = (pTypeDef->isLast)? MAKE_TABLE_INDEX(MD_TABLE_METHODDEF, pTypeDef->pMetaData->tables.numRows[MD_TABLE_METHODDEF]): (pTypeDef[1].methodList - 1); pTypeDef->numMethods = lastIdx - pTypeDef->methodList + 1; // Fields lastIdx = (pTypeDef->isLast)? MAKE_TABLE_INDEX(MD_TABLE_FIELDDEF, pTypeDef->pMetaData->tables.numRows[MD_TABLE_FIELDDEF]): (pTypeDef[1].fieldList - 1); pTypeDef->numFields = lastIdx - pTypeDef->fieldList + 1; } // Must create the virtual method table BEFORE any other type resolution is done // Note that this must not do ANY filling of types or methods. // This is to ensure that the parent object(s) in any type inheritance hierachy are allocated // their virtual method offset before derived types. firstIdx = pTypeDef->methodList; lastIdx = firstIdx + pTypeDef->numMethods - 1; // This only needs to be done for non-generic types, or for generic types that are not a definition // I.e. Fully instantiated generic types if (!pTypeDef->isGenericDefinition) { for (token = firstIdx; token <= lastIdx; token++) { tMD_MethodDef *pMethodDef; pMethodDef = MetaData_GetMethodDefFromDefRefOrSpec(pMetaData, token, ppClassTypeArgs, ppMethodTypeArgs); // This is needed, so array resolution can work correctly and FindVirtualOverriddenMethod() can work. pMethodDef->pParentType = pTypeDef; if (METHOD_ISVIRTUAL(pMethodDef)) { if (METHOD_ISNEWSLOT(pMethodDef) || pTypeDef->pParent == NULL) { // Allocate a new vTable slot if method is explicitly marked as NewSlot, or // this is of type Object. pMethodDef->vTableOfs = virtualOfs++; } else { tMD_MethodDef *pVirtualOveriddenMethod; pVirtualOveriddenMethod = FindVirtualOverriddenMethod(pTypeDef->pParent, pMethodDef); Assert(pVirtualOveriddenMethod != NULL); pMethodDef->vTableOfs = pVirtualOveriddenMethod->vTableOfs; } } else { // Dummy value - make it obvious it's not valid! pMethodDef->vTableOfs = 0xffffffff; } } // Create the virtual method table pTypeDef->numVirtualMethods = virtualOfs; // Resolve fields, members, interfaces. // Only needs to be done if it's not a generic definition type // It it's not a value-type and the stack-size is not preset, then set it up now. // It needs to be done here as non-static fields in non-value types can point to the containing type if (pTypeDef->stackSize == 0 && !pTypeDef->isValueType) { pTypeDef->stackType = EVALSTACK_O; pTypeDef->stackSize = sizeof(void*); } // Resolve all fields - instance ONLY at this point, // because static fields in value-types can be of the containing type, and the size is not yet known. firstIdx = pTypeDef->fieldList; lastIdx = firstIdx + pTypeDef->numFields - 1; staticMemSize = 0; if (pTypeDef->numFields > 0) { pTypeDef->ppFields = mallocForever(pTypeDef->numFields * sizeof(tMD_FieldDef*)); } instanceMemSize = (pTypeDef->pParent == NULL)?0:pTypeDef->pParent->instanceMemSize; for (token = firstIdx, i=0; token <= lastIdx; token++, i++) { tMD_FieldDef *pFieldDef; pFieldDef = MetaData_GetFieldDefFromDefOrRef(pMetaData, token, ppClassTypeArgs, ppMethodTypeArgs); if (!FIELD_ISSTATIC(pFieldDef)) { // Only handle non-static fields at the moment if (pTypeDef->pGenericDefinition != NULL) { // If this is a generic instantiation type, then all field defs need to be copied, // as there will be lots of different instantiations. tMD_FieldDef *pFieldCopy = TMALLOCFOREVER(tMD_FieldDef); memcpy(pFieldCopy, pFieldDef, sizeof(tMD_FieldDef)); pFieldDef = pFieldCopy; } if (FIELD_ISLITERAL(pFieldDef) || FIELD_HASFIELDRVA(pFieldDef)) { // If it's a literal, then analyse the field, but don't include it in any memory allocation // If is has an RVA, then analyse the field, but don't include it in any memory allocation MetaData_Fill_FieldDef(pTypeDef, pFieldDef, 0, ppClassTypeArgs); } else { MetaData_Fill_FieldDef(pTypeDef, pFieldDef, instanceMemSize, ppClassTypeArgs); instanceMemSize += pFieldDef->memSize; } pTypeDef->ppFields[i] = pFieldDef; } } if (pTypeDef->instanceMemSize == 0) { pTypeDef->instanceMemSize = instanceMemSize; } // Sort out stack type and size. // Note that this may already be set, as some basic types have this preset; // or if it's not a value-type it'll already be set if (pTypeDef->stackSize == 0) { // if it gets here then it must be a value type pTypeDef->stackType = EVALSTACK_VALUETYPE; pTypeDef->stackSize = pTypeDef->instanceMemSize; } // Sort out array element size. Note that some basic types will have this preset. if (pTypeDef->arrayElementSize == 0) { pTypeDef->arrayElementSize = pTypeDef->stackSize; } // Handle static fields for (token = firstIdx, i=0; token <= lastIdx; token++, i++) { tMD_FieldDef *pFieldDef; pFieldDef = MetaData_GetFieldDefFromDefOrRef(pMetaData, token, ppClassTypeArgs, ppMethodTypeArgs); if (FIELD_ISSTATIC(pFieldDef)) { // Only handle static fields here if (pTypeDef->pGenericDefinition != NULL) { // If this is a generic instantiation type, then all field defs need to be copied, // as there will be lots of different instantiations. tMD_FieldDef *pFieldCopy = TMALLOCFOREVER(tMD_FieldDef); memcpy(pFieldCopy, pFieldDef, sizeof(tMD_FieldDef)); pFieldDef = pFieldCopy; } if (FIELD_ISLITERAL(pFieldDef) || FIELD_HASFIELDRVA(pFieldDef)) { // If it's a literal, then analyse the field, but don't include it in any memory allocation // If is has an RVA, then analyse the field, but don't include it in any memory allocation MetaData_Fill_FieldDef(pTypeDef, pFieldDef, 0, ppClassTypeArgs); } else { MetaData_Fill_FieldDef(pTypeDef, pFieldDef, staticMemSize, ppClassTypeArgs); staticMemSize += pFieldDef->memSize; } pTypeDef->ppFields[i] = pFieldDef; } } if (staticMemSize > 0) { pTypeDef->pStaticFields = mallocForever(staticMemSize); memset(pTypeDef->pStaticFields, 0, staticMemSize); // Set the field addresses (->pMemory) of all static fields for (i = 0; i<pTypeDef->numFields; i++) { tMD_FieldDef *pFieldDef; pFieldDef = pTypeDef->ppFields[i]; if (FIELD_ISSTATIC(pFieldDef) && pFieldDef->pMemory == NULL) { // Only set it if it isn't already set. It will be already set if this field has an RVA pFieldDef->pMemory = pTypeDef->pStaticFields + pFieldDef->memOffset; } } pTypeDef->staticFieldSize = staticMemSize; } // Resolve all members firstIdx = pTypeDef->methodList; lastIdx = firstIdx + pTypeDef->numMethods - 1; pTypeDef->ppMethods = mallocForever(pTypeDef->numMethods * sizeof(tMD_MethodDef*)); pTypeDef->pVTable = mallocForever(pTypeDef->numVirtualMethods * sizeof(tMD_MethodDef*)); // Copy initial vTable from parent if (pTypeDef->pParent != NULL) { memcpy(pTypeDef->pVTable, pTypeDef->pParent->pVTable, pTypeDef->pParent->numVirtualMethods * sizeof(tMD_MethodDef*)); } for (token = firstIdx, i = 0; token <= lastIdx; token++, i++) { tMD_MethodDef *pMethodDef; pMethodDef = MetaData_GetMethodDefFromDefRefOrSpec(pMetaData, token, ppClassTypeArgs, ppMethodTypeArgs); if (pTypeDef->pGenericDefinition != NULL) { // If this is a generic instantiation type, then all method defs need to be copied, // as there will be lots of different instantiations. tMD_MethodDef *pMethodCopy = TMALLOCFOREVER(tMD_MethodDef); memcpy(pMethodCopy, pMethodDef, sizeof(tMD_MethodDef)); pMethodDef = pMethodCopy; } if (METHOD_ISSTATIC(pMethodDef) && strcmp(pMethodDef->name, ".cctor") == 0) { // This is a static constructor pTypeDef->pStaticConstructor = pMethodDef; } if (!METHOD_ISSTATIC(pMethodDef) && pTypeDef->pParent != NULL && strcmp(pMethodDef->name, "Finalize") == 0) { // This is a Finalizer method, but not for Object. // Delibrately miss out Object's Finalizer because it's empty and will cause every object // of any type to have a Finalizer which will be terrible for performance. pTypeDef->pFinalizer = pMethodDef; } if (METHOD_ISVIRTUAL(pMethodDef)) { // This is a virtual method, so enter it in the vTable pTypeDef->pVTable[pMethodDef->vTableOfs] = pMethodDef; } pTypeDef->ppMethods[i] = pMethodDef; } // Find inherited Finalizer, if this type doesn't have an explicit Finalizer, and if there is one if (pTypeDef->pFinalizer == NULL) { tMD_TypeDef *pInheritedType = pTypeDef->pParent; while (pInheritedType != NULL) { if (pInheritedType->pFinalizer != NULL) { pTypeDef->pFinalizer = pInheritedType->pFinalizer; break; } pInheritedType = pInheritedType->pParent; } } // Fill all method definitions for this type for (i=0; i<pTypeDef->numMethods; i++) { MetaData_Fill_MethodDef(pTypeDef, pTypeDef->ppMethods[i], ppClassTypeArgs, ppMethodTypeArgs); } // Map all interface method calls. This only needs to be done for Classes, not Interfaces // And is not done for generic definitions. if (!TYPE_ISINTERFACE(pTypeDef)) { firstIdx = 0; if (pTypeDef->pParent != NULL) { j = pTypeDef->numInterfaces = pTypeDef->pParent->numInterfaces; } else { j = 0; } // TODO: Better to do this once during file load (the bit in this for loop) for (i=1; i<=pMetaData->tables.numRows[MD_TABLE_INTERFACEIMPL]; i++) { tMD_InterfaceImpl *pInterfaceImpl; pInterfaceImpl = (tMD_InterfaceImpl*)MetaData_GetTableRow(pMetaData, MAKE_TABLE_INDEX(MD_TABLE_INTERFACEIMPL, i)); if (pInterfaceImpl->class_ == pTypeDef->tableIndex) { // count how many interfaces are implemented pTypeDef->numInterfaces++; if (firstIdx == 0) { firstIdx = MAKE_TABLE_INDEX(MD_TABLE_INTERFACEIMPL, i); } lastIdx = MAKE_TABLE_INDEX(MD_TABLE_INTERFACEIMPL, i); } } if (pTypeDef->numInterfaces > 0 && !pTypeDef->isGenericDefinition) { U32 mapNum; pTypeDef->pInterfaceMaps = (tInterfaceMap*)mallocForever(pTypeDef->numInterfaces * sizeof(tInterfaceMap)); // Copy interface maps from parent type if (j > 0) { memcpy(pTypeDef->pInterfaceMaps, pTypeDef->pParent->pInterfaceMaps, j * sizeof(tInterfaceMap)); } mapNum = j; if (firstIdx > 0) { for (token=firstIdx; token<=lastIdx; token++, mapNum++) { tMD_InterfaceImpl *pInterfaceImpl; pInterfaceImpl = (tMD_InterfaceImpl*)MetaData_GetTableRow(pMetaData, token); if (pInterfaceImpl->class_ == pTypeDef->tableIndex) { tMD_TypeDef *pInterface; tInterfaceMap *pMap; // Get the interface that this type implements pInterface = MetaData_GetTypeDefFromDefRefOrSpec(pMetaData, pInterfaceImpl->interface_, ppClassTypeArgs, ppMethodTypeArgs); MetaData_Fill_TypeDef(pInterface, NULL, NULL); pMap = &pTypeDef->pInterfaceMaps[mapNum]; pMap->pInterface = pInterface; pMap->pVTableLookup = (U32*)mallocForever(pInterface->numVirtualMethods * sizeof(U32)); pMap->ppMethodVLookup = NULL; // Discover interface mapping for each interface method for (i=0; i<pInterface->numVirtualMethods; i++) { tMD_MethodDef *pInterfaceMethod, *pOverriddenMethod; pInterfaceMethod = pInterface->pVTable[i]; pOverriddenMethod = FindVirtualOverriddenMethod(pTypeDef, pInterfaceMethod); Assert(pOverriddenMethod != NULL); pMap->pVTableLookup[i] = pOverriddenMethod->vTableOfs; } } else { Crash("Problem with interface class"); } } } } } // If this is an enum type, then pretend its stack type is its underlying type if (pTypeDef->pParent == types[TYPE_SYSTEM_ENUM]) { pTypeDef->stackType = EVALSTACK_INT32; } } // If this is a nested type, then find the namespace of it if (pTypeDef->pNestedIn != NULL) { tMD_TypeDef *pRootTypeDef = pTypeDef->pNestedIn; while (pRootTypeDef->pNestedIn != NULL) { pRootTypeDef = pRootTypeDef->pNestedIn; } pTypeDef->nameSpace = pRootTypeDef->nameSpace; } log_f(2, "Type: %s.%s\n", pTypeDef->nameSpace, pTypeDef->name); }
tMethodState* MethodState_Direct(tThread *pThread, tMD_MethodDef *pMethod, tMethodState *pCaller, U32 isInternalNewObjCall) { tMethodState *pThis; if (!pMethod->isFilled) { tMD_TypeDef *pTypeDef; pTypeDef = MetaData_GetTypeDefFromMethodDef(pMethod); MetaData_Fill_TypeDef(pTypeDef, NULL, NULL); } pThis = (tMethodState*)Thread_StackAlloc(pThread, sizeof(tMethodState)); pThis->finalizerThis = NULL; pThis->pCaller = pCaller; pThis->pMetaData = pMethod->pMetaData; pThis->pMethod = pMethod; if (pMethod->pJITted == NULL) { // If method has not already been JITted JIT_Prepare(pMethod, 0); } pThis->pJIT = pMethod->pJITted; pThis->ipOffset = 0; pThis->pEvalStack = (PTR)Thread_StackAlloc(pThread, pThis->pMethod->pJITted->maxStack); pThis->stackOfs = 0; pThis->isInternalNewObjCall = isInternalNewObjCall; pThis->pNextDelegate = NULL; pThis->pDelegateParams = NULL; pThis->pParamsLocals = (PTR)Thread_StackAlloc(pThread, pMethod->parameterStackSize + pMethod->pJITted->localsStackSize); memset(pThis->pParamsLocals, 0, pMethod->parameterStackSize + pMethod->pJITted->localsStackSize); #ifdef GEN_COMBINED_OPCODES AddCall(pMethod); /*if (combinedJITSize < GEN_COMBINED_OPCODES_MAX_MEMORY) { if (pMethod->genCallCount > GEN_COMBINED_OPCODES_CALL_TRIGGER) { if (pMethod->pJITtedCombined == NULL) { JIT_Prepare(pMethod, 1); combinedJITSize += pMethod->pJITtedCombined->opsMemSize; } } }*/ if (pMethod->pJITtedCombined == NULL && pMethod->genCallCount >= GEN_COMBINED_OPCODES_CALL_TRIGGER && (pMethod->pNextHighestCalls == NULL || pMethod->pPrevHighestCalls == NULL || pMethod->pPrevHighestCalls->pJITtedCombined != NULL || (combinedJITSize < GEN_COMBINED_OPCODES_MAX_MEMORY && pMethod->pNextHighestCalls->pJITtedCombined != NULL))) { // Do a combined JIT, if there's enough room after removing combined JIT from previous if (combinedJITSize > GEN_COMBINED_OPCODES_MAX_MEMORY) { // Remove the least-called function's combined JIT tMD_MethodDef *pToRemove = pMethod; while (pToRemove->pPrevHighestCalls != NULL && pToRemove->pPrevHighestCalls->pJITtedCombined != NULL) { pToRemove = pToRemove->pPrevHighestCalls; } if (pToRemove != pMethod) { RemoveCombinedJIT(pToRemove); } } if (combinedJITSize < GEN_COMBINED_OPCODES_MAX_MEMORY) { // If there's enough room, then create new combined JIT AddCombinedJIT(pMethod); } } // See if there is a combined opcode JIT ready to use if (pMethod->pJITtedCombined != NULL) { pThis->pJIT = pMethod->pJITtedCombined; pMethod->callStackCount++; } #endif #ifdef DIAG_METHOD_CALLS // Keep track of the number of times this method is called pMethod->callCount++; pThis->startTime = microTime(); #endif return pThis; }
tMD_TypeDef* Generics_GetGenericTypeFromCoreType(tMD_TypeDef *pCoreType, U32 numTypeArgs, tMD_TypeDef **ppTypeArgs) { tGenericInstance *pInst; tMD_TypeDef *pTypeDef; U32 i; unsigned char name[2048]; tMetaData *pMetaData; pMetaData = pCoreType->pMetaData; MetaData_Fill_TypeDef(pCoreType, NULL, NULL); // See if we have already built an instantiation of this type with the given type args. pInst = pCoreType->pGenericInstances; while (pInst != NULL) { if (pInst->numTypeArgs == numTypeArgs && memcmp(pInst->pTypeArgs, ppTypeArgs, numTypeArgs * sizeof(tMD_TypeDef*)) == 0) { return pInst->pInstanceTypeDef; } pInst = pInst->pNext; } // This has not already been instantiated, so instantiate it now. pInst = (tGenericInstance*)mallocForever(sizeof(tGenericInstance) + numTypeArgs * sizeof(tMD_TypeDef*)); // Insert this into the chain of instantiations. pInst->pNext = pCoreType->pGenericInstances; pCoreType->pGenericInstances = pInst; // Copy the type args into the instantiation. pInst->numTypeArgs = numTypeArgs; memcpy(pInst->pTypeArgs, ppTypeArgs, numTypeArgs * sizeof(tMD_TypeDef*)); // Create the new instantiated type pInst->pInstanceTypeDef = pTypeDef = TMALLOCFOREVER(tMD_TypeDef); memset(pTypeDef, 0, sizeof(tMD_TypeDef)); // Make the name of the instantiation. strcpy(name, pCoreType->name); strcat(name, "["); for (i=0; i<numTypeArgs; i++) { if (i > 0) { strcat(name, ","); } if (ppTypeArgs[i] != NULL) { sprintf(strchr(name, 0), "%s.%s", ppTypeArgs[i]->nameSpace, ppTypeArgs[i]->name); } else { tMD_GenericParam *pGenericParam = FindGenericParam(pCoreType, i); if (pGenericParam != NULL) { sprintf(strchr(name, 0), pGenericParam->name); } else { sprintf(strchr(name, 0), "???"); } } } strcat(name, "]"); // Fill in the basic bits of the new type def. pTypeDef->pTypeDef = pTypeDef; pTypeDef->pMetaData = pMetaData; pTypeDef->flags = pCoreType->flags; pTypeDef->pGenericDefinition = pCoreType; for (i=0; i<numTypeArgs; i++) { if (ppTypeArgs[i] == NULL) { pTypeDef->isGenericDefinition = 1; break; } } pTypeDef->nameSpace = pCoreType->nameSpace; pTypeDef->name = (STRING)mallocForever((U32)strlen(name)+1); strcpy(pTypeDef->name, name); pTypeDef->ppClassTypeArgs = pInst->pTypeArgs; pTypeDef->extends = pCoreType->extends; pTypeDef->tableIndex = pCoreType->tableIndex; pTypeDef->fieldList = pCoreType->fieldList; pTypeDef->methodList = pCoreType->methodList; pTypeDef->numFields = pCoreType->numFields; pTypeDef->numMethods = pCoreType->numMethods; pTypeDef->numVirtualMethods = pCoreType->numVirtualMethods; pTypeDef->pNestedIn = pCoreType->pNestedIn; pTypeDef->isPrimed = 1; MetaData_Fill_TypeDef_(pTypeDef, ppTypeArgs, NULL); return pTypeDef; }
static void CreateNewArrayType(tMD_TypeDef *pNewArrayType, tMD_TypeDef *pElementType, tMD_TypeDef **ppClassTypeArgs, tMD_TypeDef **ppMethodTypeArgs) { MetaData_Fill_TypeDef(types[TYPE_SYSTEM_ARRAY_NO_TYPE], NULL, NULL); memcpy(pNewArrayType, types[TYPE_SYSTEM_ARRAY_NO_TYPE], sizeof(tMD_TypeDef)); pNewArrayType->pArrayElementType = pElementType; pNewArrayType->isFilled = 1; // Auto-generate the generic interfaces IEnumerable<T>, ICollection<T> and IList<T> for this array { tInterfaceMap *pInterfaceMap, *pAllIMs; tMD_TypeDef *pInterfaceT; tMD_MethodDef *pMethod; U32 orgNumInterfaces; if (genericArrayMethodsInited == 0) { GetMethodDefs(); } orgNumInterfaces = pNewArrayType->numInterfaces; pNewArrayType->numInterfaces += 3; pAllIMs = (tInterfaceMap*)mallocForever(pNewArrayType->numInterfaces * sizeof(tInterfaceMap)); memcpy(pAllIMs, pNewArrayType->pInterfaceMaps, orgNumInterfaces * sizeof(tInterfaceMap)); pNewArrayType->pInterfaceMaps = pAllIMs; // Get the IEnumerable<T> interface pInterfaceMap = &pAllIMs[orgNumInterfaces + 0]; pInterfaceT = Generics_GetGenericTypeFromCoreType(types[TYPE_SYSTEM_COLLECTIONS_GENERIC_IENUMERABLE_T], 1, &pElementType); pInterfaceMap->pInterface = pInterfaceT; pInterfaceMap->pVTableLookup = NULL; pInterfaceMap->ppMethodVLookup = mallocForever(pInterfaceT->numVirtualMethods * sizeof(tMD_MethodDef*)); pMethod = Generics_GetMethodDefFromCoreMethod(ppGenericArrayMethods[GENERICARRAYMETHODS_Internal_GetGenericEnumerator], pNewArrayType, 1, &pElementType); pInterfaceMap->ppMethodVLookup[0] = pMethod; // Get the ICollection<T> interface pInterfaceMap = &pAllIMs[orgNumInterfaces + 1]; pInterfaceT = Generics_GetGenericTypeFromCoreType(types[TYPE_SYSTEM_COLLECTIONS_GENERIC_ICOLLECTION_T], 1, &pElementType); pInterfaceMap->pInterface = pInterfaceT; pInterfaceMap->pVTableLookup = NULL; pInterfaceMap->ppMethodVLookup = mallocForever(pInterfaceT->numVirtualMethods * sizeof(tMD_MethodDef*)); pInterfaceMap->ppMethodVLookup[0] = ppGenericArrayMethods[GENERICARRAYMETHODS_get_Length]; pInterfaceMap->ppMethodVLookup[1] = ppGenericArrayMethods[GENERICARRAYMETHODS_get_IsReadOnly]; pInterfaceMap->ppMethodVLookup[2] = Generics_GetMethodDefFromCoreMethod(ppGenericArrayMethods[GENERICARRAYMETHODS_Internal_GenericAdd], pNewArrayType, 1, &pElementType); pInterfaceMap->ppMethodVLookup[3] = ppGenericArrayMethods[GENERICARRAYMETHODS_Internal_GenericClear]; pInterfaceMap->ppMethodVLookup[4] = Generics_GetMethodDefFromCoreMethod(ppGenericArrayMethods[GENERICARRAYMETHODS_Internal_GenericContains], pNewArrayType, 1, &pElementType); pInterfaceMap->ppMethodVLookup[5] = Generics_GetMethodDefFromCoreMethod(ppGenericArrayMethods[GENERICARRAYMETHODS_Internal_GenericCopyTo], pNewArrayType, 1, &pElementType); pInterfaceMap->ppMethodVLookup[6] = Generics_GetMethodDefFromCoreMethod(ppGenericArrayMethods[GENERICARRAYMETHODS_Internal_GenericRemove], pNewArrayType, 1, &pElementType); // Get the IList<T> interface pInterfaceMap = &pAllIMs[orgNumInterfaces + 2]; pInterfaceT = Generics_GetGenericTypeFromCoreType(types[TYPE_SYSTEM_COLLECTIONS_GENERIC_ILIST_T], 1, &pElementType); //, ppClassTypeArgs, ppMethodTypeArgs); pInterfaceMap->pInterface = pInterfaceT; pInterfaceMap->pVTableLookup = NULL; pInterfaceMap->ppMethodVLookup = mallocForever(pInterfaceT->numVirtualMethods * sizeof(tMD_MethodDef*)); pInterfaceMap->ppMethodVLookup[0] = Generics_GetMethodDefFromCoreMethod(ppGenericArrayMethods[GENERICARRAYMETHODS_Internal_GenericIndexOf], pNewArrayType, 1, &pElementType); pInterfaceMap->ppMethodVLookup[1] = Generics_GetMethodDefFromCoreMethod(ppGenericArrayMethods[GENERICARRAYMETHODS_Internal_GenericInsert], pNewArrayType, 1, &pElementType); pInterfaceMap->ppMethodVLookup[2] = ppGenericArrayMethods[GENERICARRAYMETHODS_Internal_GenericRemoveAt]; pInterfaceMap->ppMethodVLookup[3] = Generics_GetMethodDefFromCoreMethod(ppGenericArrayMethods[GENERICARRAYMETHODS_Internal_GenericGetItem], pNewArrayType, 1, &pElementType); pInterfaceMap->ppMethodVLookup[4] = Generics_GetMethodDefFromCoreMethod(ppGenericArrayMethods[GENERICARRAYMETHODS_Internal_GenericSetItem], pNewArrayType, 1, &pElementType); } log_f(2, "Array: Array[%s.%s]\n", pElementType->nameSpace, pElementType->name); }