public static void Fill_TypeDef(tMD_TypeDef *pTypeDef, tMD_TypeDef **ppClassTypeArgs, tMD_TypeDef **ppMethodTypeArgs, uint resolve = Type.TYPE_FILL_ALL) { uint instanceMemSize, staticMemSize, virtualOfs, isDeferred, i, j; int lastPeriod; tMetaData * pMetaData; tMD_TypeDef *pParent; System.Type monoType; tMD_FieldDef * pFieldDefs; tMD_MethodDef *pMethodDefs; FieldInfo[] fieldInfos = null; FieldInfo fieldInfo; MethodInfo[] methodInfos = null; ConstructorInfo[] constructorInfos = null; MethodBase methodBase; tMD_MethodDef * pMethodDef; if (pTypeDef->fillState >= resolve) { return; } if (pTypeDef->monoType == null) { MetaData.Fill_TypeDef(pTypeDef, ppClassTypeArgs, ppMethodTypeArgs, resolve); return; } //Sys.printf("FILLING TYPE: %s\n", (PTR)pTypeDef->name); if (MetaData.typesToFill == null) { MetaData.Fill_StartDefer(); isDeferred = 1; } else { isDeferred = 0; } if (resolve < Type.TYPE_FILL_ALL) { MetaData.Fill_Defer(pTypeDef, ppClassTypeArgs, ppMethodTypeArgs); } MetaData.Fill_GetDeferredTypeArgs(pTypeDef, ref ppClassTypeArgs, ref ppMethodTypeArgs); monoType = H.ToObj(pTypeDef->monoType) as System.Type; pMetaData = pTypeDef->pMetaData; if (pTypeDef->fillState < Type.TYPE_FILL_PARENTS) { pTypeDef->fillState = Type.TYPE_FILL_PARENTS; // For Methods, we get only public if sealed, or public/protected if not sealed methodInfos = GetMethods(monoType); // For fields, we only get private fields for value types fieldInfos = GetFields(monoType); // For constructors, we get only public if sealed, or public/protected if not sealed constructorInfos = GetConstructors(monoType); pTypeDef->pTypeDef = pTypeDef; pTypeDef->pParent = MonoType.GetTypeForMonoType(monoType.BaseType, null, null); pParent = pTypeDef->pParent; pTypeDef->isValueType = (byte)(monoType.IsValueType ? 1 : 0); if (pParent != null) { MetaData.Fill_TypeDef(pParent, null, null, Type.TYPE_FILL_PARENTS); if (pParent->hasMonoBase == 0) { // If we have a mono base type, we have at least 1 non-blittable field pTypeDef->blittable = pParent->blittable; pTypeDef->fixedBlittable = pParent->fixedBlittable; } else { pTypeDef->blittable = pTypeDef->fixedBlittable = 0; } } else { // For mono types - reference types are NEVER blittable in our implementation pTypeDef->blittable = pTypeDef->fixedBlittable = pTypeDef->isValueType; } pTypeDef->alignment = 1; // Mark all ref types as having a base Mono Handle pointer as the first slot in their instance data. This allows // the Heap system to call FREE on this Handle whenever we garbage collect mono wrapped or derived heap objects. pTypeDef->hasMonoBase = (byte)(monoType.IsValueType ? 0 : 1); // If not primed, then work out how many methods & fields there are. if (pTypeDef->isPrimed == 0) { // Methods pTypeDef->numMethods = (uint)(constructorInfos.Length + methodInfos.Length); // Fields pTypeDef->numFields = (uint)fieldInfos.Length; } // If this is an enum type, then pretend its stack type is its underlying type if (pTypeDef->pParent == Type.types[Type.TYPE_SYSTEM_ENUM]) { pTypeDef->stackType = EvalStack.EVALSTACK_INT32; pTypeDef->stackSize = sizeof(PTR); pTypeDef->instanceMemSize = 4; pTypeDef->arrayElementSize = 4; pTypeDef->blittable = pTypeDef->fixedBlittable = 1; } if (pTypeDef->fillState >= resolve) { return; } } else { pParent = pTypeDef->pParent; } if (pTypeDef->fillState < Type.TYPE_FILL_LAYOUT) { pTypeDef->fillState = Type.TYPE_FILL_LAYOUT; if (pParent != null) { if (pParent->fillState < Type.TYPE_FILL_LAYOUT) { MetaData.Fill_TypeDef(pParent, null, null, Type.TYPE_FILL_LAYOUT); } else if (pParent->fillState < Type.TYPE_FILL_ALL) { MetaData.Fill_Defer(pParent, null, null); } } // This only needs to be done for non-generic Type.types, or for generic type that are not a definition // I.e. Fully instantiated generic Type.types if (pTypeDef->isGenericDefinition == 0) { // For fields, we only get private fields for value types if (fieldInfos == null) { fieldInfos = GetFields(monoType); } // 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 type can point to the containing type if (pTypeDef->stackSize == 0 && pTypeDef->isValueType == 0) { pTypeDef->stackType = EvalStack.EVALSTACK_O; pTypeDef->stackSize = sizeof(PTR); pTypeDef->alignment = sizeof(PTR); } // Resolve all fields - instance ONLY at this point, // because static fields in value-Type.types can be of the containing type, and the size is not yet known. staticMemSize = 0; if (pTypeDef->numFields > 0) { pTypeDef->ppFields = (tMD_FieldDef **)Mem.mallocForever((SIZE_T)(pTypeDef->numFields * sizeof(tMD_FieldDef *))); pFieldDefs = (tMD_FieldDef *)Mem.mallocForever((SIZE_T)(pTypeDef->numFields * sizeof(tMD_FieldDef))); Mem.memset(pFieldDefs, 0, (SIZE_T)(pTypeDef->numFields * sizeof(tMD_FieldDef))); } else { pFieldDefs = null; } instanceMemSize = 0; for (i = 0; i < fieldInfos.Length; i++) { fieldInfo = fieldInfos[i]; tMD_FieldDef *pFieldDef = &pFieldDefs[i]; pFieldDef->name = new S(fieldInfo.Name); pFieldDef->flags = (ushort)( (fieldInfo.IsStatic ? MetaData.FIELDATTRIBUTES_STATIC : 0) | (fieldInfo.IsLiteral ? MetaData.FIELDATTRIBUTES_LITERAL : 0) ); if (!fieldInfo.IsStatic) { if (fieldInfo.IsLiteral /*|| MetaData.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 MonoType.Fill_FieldDef(pTypeDef, fieldInfo, pFieldDef, 0, null, ppClassTypeArgs); } else { MonoType.Fill_FieldDef(pTypeDef, fieldInfo, pFieldDef, instanceMemSize, &(pTypeDef->alignment), ppClassTypeArgs); instanceMemSize = pFieldDef->memOffset + pFieldDef->memSize; } // Update blittable and fixedBlittable status for type - if any non-blittable fields are included set to 0 if (pTypeDef->blittable != 0 || pTypeDef->fixedBlittable != 0) { if (pFieldDef->pType->isValueType == 0 || pFieldDef->pType->blittable == 0) { pTypeDef->blittable = pTypeDef->fixedBlittable = 0; } else if (pFieldDef->pType->typeInitId == Type.TYPE_SYSTEM_INTPTR || pFieldDef->pType->typeInitId == Type.TYPE_SYSTEM_UINTPTR) { pTypeDef->fixedBlittable = 0; } } pTypeDef->ppFields[i] = pFieldDef; } } if (pTypeDef->instanceMemSize == 0) { if (pTypeDef->isValueType != 0) { // Our dna value types are the same size as they are in mono (hopefully!) pTypeDef->instanceMemSize = (instanceMemSize + (pTypeDef->alignment - 1)) & ~(pTypeDef->alignment - 1); } else { // For mono reference types, the instance size is ALWAYS ptr size because we're wrapping a mono GCHandle pointer pTypeDef->instanceMemSize = sizeof(PTR); } } // Sort out stack type and size. // Note that this may already be set, as some basic type 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.EVALSTACK_VALUETYPE; pTypeDef->stackSize = pTypeDef->instanceMemSize; } // Sort out array element size. Note that some basic type will have this preset. if (pTypeDef->arrayElementSize == 0) { pTypeDef->arrayElementSize = pTypeDef->stackSize; } // Make sure stack size is even multiple of stack alignment pTypeDef->stackSize = (pTypeDef->stackSize + (STACK_ALIGNMENT - 1)) & ~(STACK_ALIGNMENT - 1); // Handle static fields for (i = 0; i < fieldInfos.Length; i++) { fieldInfo = fieldInfos[i]; tMD_FieldDef *pFieldDef = &pFieldDefs[i]; if (fieldInfo.IsStatic) { if (fieldInfo.IsLiteral /*|| MetaData.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 MonoType.Fill_FieldDef(pTypeDef, fieldInfo, pFieldDef, 0, null, ppClassTypeArgs); } else { MonoType.Fill_FieldDef(pTypeDef, fieldInfo, pFieldDef, staticMemSize, null, ppClassTypeArgs); staticMemSize += pFieldDef->memSize; } pTypeDef->ppFields[i] = pFieldDef; } } } if (pTypeDef->fillState >= resolve) { return; } } if (pTypeDef->fillState < Type.TYPE_FILL_VTABLE) { pTypeDef->fillState = Type.TYPE_FILL_VTABLE; if (pParent != null) { if (pParent->fillState < Type.TYPE_FILL_VTABLE) { MetaData.Fill_TypeDef(pParent, null, null, Type.TYPE_FILL_VTABLE); } else if (pParent->fillState < Type.TYPE_FILL_ALL) { MetaData.Fill_Defer(pParent, null, null); } } // This only needs to be done for non-generic Type.types, or for generic type that are not a definition // I.e. Fully instantiated generic Type.types if (pTypeDef->isGenericDefinition == 0) { virtualOfs = (pParent != null) ? pParent->numVirtualMethods : 0; // For Methods, we get only public if sealed, or public/protected if not sealed if (methodInfos == null) { methodInfos = GetMethods(monoType); } // For constructors, we get only public if sealed, or public/protected if not sealed if (constructorInfos == null) { constructorInfos = GetConstructors(monoType); } // Populate methods pTypeDef->ppMethods = (tMD_MethodDef **)Mem.mallocForever((SIZE_T)(pTypeDef->numMethods * sizeof(tMD_MethodDef *))); pMethodDefs = (tMD_MethodDef *)Mem.mallocForever((SIZE_T)(pTypeDef->numMethods * sizeof(tMD_MethodDef))); Mem.memset(pMethodDefs, 0, (SIZE_T)(pTypeDef->numMethods * sizeof(tMD_MethodDef))); for (i = 0; i < pTypeDef->numMethods; i++) { methodBase = (i < constructorInfos.Length) ? (MethodBase)constructorInfos[i] : methodInfos[i - constructorInfos.Length]; pMethodDef = &pMethodDefs[i]; lastPeriod = methodBase.Name.LastIndexOf('.'); if (methodBase is ConstructorInfo || lastPeriod == -1) { pMethodDef->name = new S(methodBase.Name); } else { string nameMinusExclInterfaceName = methodBase.Name.Substring(lastPeriod + 1); pMethodDef->name = new S(nameMinusExclInterfaceName); } pMethodDef->monoMethodInfo = new H(methodBase); pMethodDef->pMetaData = pMetaData; pMethodDef->pParentType = pTypeDef; pMethodDef->flags = (ushort)( (methodBase.IsVirtual ? MetaData.METHODATTRIBUTES_VIRTUAL : 0) | (methodBase.IsStatic ? MetaData.METHODATTRIBUTES_STATIC : 0)); // NOTE: All mono calls are considered internal calls pMethodDef->implFlags = (ushort)MetaData.METHODIMPLATTRIBUTES_INTERNALCALL; pTypeDef->ppMethods[i] = pMethodDef; // Assign vtable slots if (methodBase.IsVirtual) { if (((MethodInfo)methodBase).GetBaseDefinition().DeclaringType == monoType) { // 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 = MetaData.FindVirtualOverriddenMethod(pTypeDef->pParent, pMethodDef); if (pVirtualOveriddenMethod == null) { if (pTypeDef->pParent->monoType == null) { // DNA types don't always have all base methods that Unity/Mono has. In those // cases, just add the missing method to the VTable as a new virtual method. pMethodDef->vTableOfs = virtualOfs++; } else { Sys.Crash("Unable to find virtual override %s", (PTR)(pMethodDef->name)); } } else { pMethodDef->vTableOfs = pVirtualOveriddenMethod->vTableOfs; } } } else { // Dummy value - make it obvious it's not valid! pMethodDef->vTableOfs = 0xffffffff; } pTypeDef->ppMethods[i] = pMethodDef; } // Create the virtual method table pTypeDef->numVirtualMethods = virtualOfs; // Resolve all members pTypeDef->pVTable = (tMD_MethodDef **)Mem.mallocForever((SIZE_T)(pTypeDef->numVirtualMethods * sizeof(tMD_MethodDef *))); // Copy initial vTable from parent if (pTypeDef->pParent != null) { Mem.memcpy(pTypeDef->pVTable, pTypeDef->pParent->pVTable, (SIZE_T)(pTypeDef->pParent->numVirtualMethods * sizeof(tMD_MethodDef *))); } for (i = 0; i < pTypeDef->numMethods; i++) { pMethodDef = pTypeDef->ppMethods[i]; methodBase = H.ToObj(pMethodDef->monoMethodInfo) as MethodBase; if (methodBase.IsStatic && methodBase.Name == ".cctor") { // This is a static constructor pTypeDef->pStaticConstructor = pMethodDef; } if (methodBase.IsStatic && pTypeDef->pParent != null && methodBase.Name == "Finalize") { // 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 (methodBase.IsVirtual) { if (pMethodDef->vTableOfs == 0xffffffff) { Sys.Crash("Illegal vtableoffset"); } if (pMethodDef->vTableOfs >= pTypeDef->numVirtualMethods) { Sys.Crash("Illegal vtableoffset"); } pTypeDef->pVTable[pMethodDef->vTableOfs] = 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; } } } if (pTypeDef->fillState >= resolve) { return; } } if (pTypeDef->fillState < Type.TYPE_FILL_MEMBERS) { pTypeDef->fillState = Type.TYPE_FILL_MEMBERS; if (pParent != null) { if (pParent->fillState < Type.TYPE_FILL_MEMBERS) { MetaData.Fill_TypeDef(pParent, null, null, Type.TYPE_FILL_MEMBERS); } else if (pParent->fillState < Type.TYPE_FILL_ALL) { MetaData.Fill_Defer(pParent, null, null); } } // This only needs to be done for non-generic Type.types, or for generic type that are not a definition // I.e. Fully instantiated generic Type.types if (pTypeDef->isGenericDefinition == 0) { // Fill all method definitions for this type for (i = 0; i < pTypeDef->numMethods; i++) { pMethodDef = pTypeDef->ppMethods[i]; methodBase = H.ToObj(pMethodDef->monoMethodInfo) as MethodBase; MonoType.Fill_MethodDef(pTypeDef, methodBase, pTypeDef->ppMethods[i], ppClassTypeArgs, ppMethodTypeArgs); } } if (pTypeDef->fillState >= resolve) { return; } } if (pTypeDef->fillState < Type.TYPE_FILL_INTERFACES) { pTypeDef->fillState = Type.TYPE_FILL_INTERFACES; if (pParent != null) { if (pParent->fillState < Type.TYPE_FILL_INTERFACES) { MetaData.Fill_TypeDef(pParent, null, null, Type.TYPE_FILL_INTERFACES); } else if (pParent->fillState < Type.TYPE_FILL_ALL) { MetaData.Fill_Defer(pParent, null, null); } } // This only needs to be done for non-generic Type.types, or for generic type that are not a definition // I.e. Fully instantiated generic Type.types if (pTypeDef->isGenericDefinition == 0) { // Map all interface method calls. This only needs to be done for Classes, not Interfaces // And is not done for generic definitions. if (!monoType.IsInterface) { System.Type[] interfaceTypes = monoType.GetInterfaces(); pTypeDef->numInterfaces = (uint)interfaceTypes.Length; if (interfaceTypes.Length > 0 && pTypeDef->isGenericDefinition == 0) { if (pTypeDef->pInterfaceMaps == null) { pTypeDef->pInterfaceMaps = (tInterfaceMap *)Mem.mallocForever((SIZE_T)(pTypeDef->numInterfaces * sizeof(tInterfaceMap))); } for (i = 0; i < interfaceTypes.Length; i++) { // Get the interface that this type implements tMD_TypeDef *pInterface = MonoType.GetTypeForMonoType(interfaceTypes[i], ppClassTypeArgs, ppMethodTypeArgs); Fill_TypeDef(pInterface, ppClassTypeArgs, null, Type.TYPE_FILL_VTABLE); InterfaceMapping interfaceMapping = monoType.GetInterfaceMap(interfaceTypes[i]); MetaData.Fill_TypeDef(pInterface, null, null); tInterfaceMap *pMap = &pTypeDef->pInterfaceMaps[i]; pMap->pInterface = pInterface; pMap->pVTableLookup = (uint *)Mem.mallocForever((SIZE_T)(pInterface->numVirtualMethods * sizeof(uint))); pMap->ppMethodVLookup = (tMD_MethodDef **)Mem.mallocForever((SIZE_T)(pInterface->numVirtualMethods * sizeof(tMD_MethodDef *))); MethodInfo[] interfaceMethods = interfaceMapping.InterfaceMethods; MethodInfo[] targetMethods = interfaceMapping.TargetMethods; // Discover interface mapping for each interface method for (j = 0; j < pInterface->numVirtualMethods; j++) { tMD_MethodDef *pInterfaceMethod = pInterface->pVTable[j]; tMD_MethodDef *pOverriddenMethod = FindInterfaceOverriddenMethod(pInterfaceMethod, interfaceMethods, targetMethods); if (pOverriddenMethod == null) { Sys.Crash("Unable to find override method %s in type %s.%s for interface %s.%s", (PTR)(pInterfaceMethod->name), (PTR)pTypeDef->nameSpace, (PTR)pTypeDef->name, (PTR)pInterface->nameSpace, (PTR)pInterface->name); } pMap->pVTableLookup[j] = pOverriddenMethod->vTableOfs; pMap->ppMethodVLookup[j] = pOverriddenMethod; } } } } } if (pTypeDef->fillState >= resolve) { return; } } if (pTypeDef->fillState < Type.TYPE_FILL_ALL) { pTypeDef->fillState = Type.TYPE_FILL_ALL; if (pParent != null && pParent->fillState < Type.TYPE_FILL_ALL) { MetaData.Fill_TypeDef(pParent, null, null, Type.TYPE_FILL_ALL); } if (isDeferred != 0) { MetaData.Fill_ResolveDeferred(); } } Sys.log_f(2, "Mono Type: %s.%s\n", (PTR)pTypeDef->nameSpace, (PTR)pTypeDef->name); }
public static tMD_MethodDef *GetMethodDefFromCoreMethod(tMD_MethodDef *pCoreMethod, tMD_TypeDef *pParentType, uint numTypeArgs, tMD_TypeDef **ppTypeArgs, HashSet <PTR> resolveTypes = null) { tGenericMethodInstance *pInst; tMD_MethodDef * pMethod; Mem.heapcheck(); // See if we already have an instance with the given type args pInst = pCoreMethod->pGenericMethodInstances; while (pInst != null) { if (pInst->numTypeArgs == numTypeArgs && Mem.memcmp(pInst->ppTypeArgs, ppTypeArgs, (SIZE_T)(numTypeArgs * sizeof(tMD_TypeDef *))) == 0) { return(pInst->pInstanceMethodDef); } pInst = pInst->pNext; } // We don't have an instance so create one now. pInst = (tGenericMethodInstance *)Mem.mallocForever((SIZE_T)(sizeof(tGenericMethodInstance))); pInst->pNext = pCoreMethod->pGenericMethodInstances; pCoreMethod->pGenericMethodInstances = pInst; pInst->numTypeArgs = numTypeArgs; pInst->ppTypeArgs = (tMD_TypeDef **)Mem.malloc((SIZE_T)(numTypeArgs * sizeof(tMD_TypeDef *))); Mem.memcpy(pInst->ppTypeArgs, ppTypeArgs, (SIZE_T)(numTypeArgs * sizeof(tMD_TypeDef *))); pInst->pInstanceMethodDef = pMethod = ((tMD_MethodDef *)Mem.mallocForever((SIZE_T)sizeof(tMD_MethodDef))); Mem.memset(pMethod, 0, (SIZE_T)sizeof(tMD_MethodDef)); pMethod->pMethodDef = pMethod; pMethod->pMetaData = pCoreMethod->pMetaData; pMethod->pCIL = pCoreMethod->pCIL; pMethod->implFlags = pCoreMethod->implFlags; pMethod->flags = pCoreMethod->flags; pMethod->name = pCoreMethod->name; pMethod->signature = pCoreMethod->signature; pMethod->vTableOfs = pCoreMethod->vTableOfs; pMethod->ppMethodTypeArgs = pInst->ppTypeArgs; if (pCoreMethod->monoMethodInfo != null) { System.Reflection.MethodInfo methodInfo = H.ToObj(pCoreMethod->monoMethodInfo) as System.Reflection.MethodInfo; System.Type[] typeArgs = new System.Type[(int)numTypeArgs]; for (uint i = 0; i < numTypeArgs; i++) { typeArgs[i] = MonoType.GetMonoTypeForType(ppTypeArgs[i]); if (typeArgs[i] == null) { Sys.Crash("Unable to find mono type for type arg %s.%s in for generic method %s", (PTR)ppTypeArgs[i]->nameSpace, (PTR)ppTypeArgs[i]->name, (PTR)pCoreMethod->name); } } System.Reflection.MethodInfo genericMethodInfo = methodInfo.MakeGenericMethod(typeArgs); MonoType.Fill_MethodDef(pParentType, genericMethodInfo, pMethod, pParentType->ppClassTypeArgs, pInst->ppTypeArgs); } else { MetaData.Fill_MethodDef(pParentType, pMethod, pParentType->ppClassTypeArgs, pInst->ppTypeArgs); } Mem.heapcheck(); return(pMethod); }