public static tMetaData *New() { tMetaData *pRet = ((tMetaData *)Mem.malloc((SIZE_T)sizeof(tMetaData))); Mem.memset(pRet, 0, (SIZE_T)sizeof(tMetaData)); return(pRet); }
public static void WrapMonoAssembly(tMetaData *pMetaData, System.Reflection.Assembly assembly) { System.Type[] types = assembly.GetTypes(); pMetaData->tables.numRows[MetaDataTable.MD_TABLE_TYPEDEF] = (uint)types.Length; tMD_TypeDef *pTypeDefs = (tMD_TypeDef *)Mem.malloc((SIZE_T)(sizeof(tMD_TypeDef) * types.Length)); Mem.memset(pTypeDefs, 0, (SIZE_T)(sizeof(tMD_TypeDef) * types.Length)); for (int i = 0; i < types.Length; i++) { tMD_TypeDef *pTypeDef = &pTypeDefs[i]; System.Type monoType = types[i]; pTypeDef->pMetaData = pMetaData; pTypeDef->name = new S(monoType.Name); pTypeDef->nameSpace = new S(monoType.Namespace); pTypeDef->monoType = new H(monoType); pTypeDef->flags = (monoType.IsInterface ? TYPEATTRIBUTES_INTERFACE : 0); pTypeDef->isValueType = (byte)(monoType.IsValueType ? 1 : 0); pTypeDef->isGenericDefinition = (byte)(types[i].IsGenericTypeDefinition ? 1 : 0); MonoType.monoTypes[monoType] = (PTR)pTypeDef; } pMetaData->tables.data[MetaDataTable.MD_TABLE_TYPEDEF] = (PTR)pTypeDefs; }
public static tRVA_Item *Create(tRVA *pThis, void *pFile, void *pSectionHeader) { tRVA_Item *pRet; uint rawOfs; uint rawSize; pRet = ((tRVA_Item *)Mem.malloc((SIZE_T)sizeof(tRVA_Item))); pRet->baseAddress = *(uint *)&((byte *)pSectionHeader)[12]; pRet->size = *(uint *)&((byte *)pSectionHeader)[8]; pRet->pData = Mem.malloc(pRet->size); Mem.memset(pRet->pData, 0, pRet->size); pRet->pNext = pThis->pFirstRVA; pThis->pFirstRVA = pRet; rawOfs = *(uint *)&((byte *)pSectionHeader)[20]; rawSize = *(uint *)&((byte *)pSectionHeader)[16]; if (rawOfs > 0) { if (rawSize > pRet->size) { rawSize = pRet->size; } Mem.memcpy(pRet->pData, ((byte *)pFile) + rawOfs, rawSize); } return(pRet); }
static tSync *EnsureSync(tHeapEntry *pHeapEntry) { if (pHeapEntry->pSync == null) { tSync *pSync = ((tSync *)Mem.malloc((SIZE_T)sizeof(tSync))); Mem.memset(pSync, 0, (SIZE_T)sizeof(tSync)); pHeapEntry->pSync = pSync; } return(pHeapEntry->pSync); }
public static void StackFree(tThread *pThread, void *pAddr) { tThreadStack *pStack = pThread->pThreadStack; #if _DEBUG ((uint *)pAddr)--; Mem.memset(pAddr, 0xfe, pStack->ofs - (uint)(((byte *)pAddr) - pStack->memory)); #endif pStack->ofs = (uint)(((byte *)pAddr) - pStack->memory); }
public static void Init() { // Initialise vars trackHeapSize = 0; heapSizeMax = MIN_HEAP_SIZE; // Create nil node - for leaf termination nil = ((tHeapEntry *)Mem.mallocForever((SIZE_T)sizeof(tHeapEntry))); Mem.memset(nil, 0, (SIZE_T)sizeof(tHeapEntry)); nil->pLink[0] = nil->pLink[1] = (PTR)nil; // Set the heap tree as empty pHeapTreeRoot = nil; }
public static tCLIFile *WrapMonoAssembly(/*char**/ byte *pAssemblyName) { tCLIFile * pRet; tFilesLoaded *pNewFile; tMetaData * pMetaData; System.Reflection.Assembly assembly = null; string assemblyName = Marshal.PtrToStringAnsi((System.IntPtr)pAssemblyName); System.Reflection.Assembly[] assemblies = System.AppDomain.CurrentDomain.GetAssemblies(); for (int i = 0; i < assemblies.Length; i++) { System.Reflection.Assembly assem = assemblies[i]; if (assem.GetName().Name == assemblyName) { assembly = assem; break; } } if (assembly == null) { Sys.Crash("Unable to load assembly file %s", (PTR)pAssemblyName); } pRet = ((tCLIFile *)Mem.malloc((SIZE_T)sizeof(tCLIFile))); Mem.memset(pRet, 0, (SIZE_T)sizeof(tCLIFile)); pRet->pMetaData = pMetaData = MetaData.New(); MetaData.WrapMonoAssembly(pMetaData, assembly); string codeBase = assembly.CodeBase; System.UriBuilder uri = new System.UriBuilder(codeBase); string path = System.Uri.UnescapeDataString(uri.Path); string assmName = System.IO.Path.GetFileNameWithoutExtension(path); pRet->assemblyName = new S(assmName); // Record that we've loaded this file pNewFile = ((tFilesLoaded *)Mem.mallocForever((SIZE_T)sizeof(tFilesLoaded))); pNewFile->pCLIFile = pRet; pNewFile->pNext = pFilesLoaded; pFilesLoaded = pNewFile; return(pRet); }
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; int i; 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; MetaData.Fill_MethodDef(pParentType, pMethod, pParentType->ppClassTypeArgs, pInst->ppTypeArgs); Mem.heapcheck(); return(pMethod); }
public static tAsyncCall *Clear(tJITCallNative *pCallNative, byte *pThis_, byte *pParams, byte *pReturnValue) { tSystemArray *pArray; uint index, length, elementSize; tMD_TypeDef * pArrayType; byte * pElements; pArray = (*((tSystemArray **)(pParams + 0))); index = (*((uint *)(pParams + Sys.S_PTR))); length = (*((uint *)(pParams + Sys.S_PTR + Sys.S_INT32))); pArrayType = Heap.GetType((/*HEAP_PTR*/ byte *)pArray); elementSize = pArrayType->pArrayElementType->arrayElementSize; pElements = tSystemArray.GetElements(pArray); Mem.memset(pElements + index * elementSize, 0, (SIZE_T)(length * elementSize)); return(null); }
public static tMethodState *Direct(tThread *pThread, tMD_MethodDef *pMethod, tMethodState *pCaller, uint isInternalNewObjCall) { tMethodState *pThis; Mem.heapcheck(); if (pMethod->isFilled == 0) { tMD_TypeDef *pTypeDef; pTypeDef = MetaData.GetTypeDefFromMethodDef(pMethod); MetaData.Fill_TypeDef(pTypeDef, null, null); } pThis = (tMethodState *)Thread.StackAlloc(pThread, (uint)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 = (byte *)Thread.StackAlloc(pThread, pThis->pMethod->pJITted->maxStack); pThis->stackOfs = 0; pThis->isInternalNewObjCall = isInternalNewObjCall; pThis->pNextDelegate = null; pThis->pDelegateParams = null; pThis->pParamsLocals = (byte *)Thread.StackAlloc(pThread, pMethod->parameterStackSize + pMethod->pJITted->localsStackSize); Mem.memset(pThis->pParamsLocals, 0, pMethod->parameterStackSize + pMethod->pJITted->localsStackSize); #if DIAG_METHOD_CALLS // Keep track of the number of times this method is called pMethod->callCount++; pThis->startTime = microTime(); #endif Mem.heapcheck(); return(pThis); }
public static /*HEAP_PTR*/ byte *Alloc(tMD_TypeDef *pTypeDef, uint size) { tHeapEntry *pHeapEntry; uint totalSize; byte * pMem; if (pTypeDef == null) { Sys.Crash("Invalid heap type!"); } totalSize = (uint)sizeof(tHeapEntry) + size; // Trigger garbage collection if required. if (trackHeapSize >= heapSizeMax) { GarbageCollect(); heapSizeMax = (trackHeapSize + totalSize) << 1; if (heapSizeMax < trackHeapSize + totalSize + MIN_HEAP_SIZE) { // Make sure there is always MIN_HEAP_SIZE available to allocate on the heap heapSizeMax = trackHeapSize + totalSize + MIN_HEAP_SIZE; } if (heapSizeMax > trackHeapSize + totalSize + MAX_HEAP_EXCESS) { // Make sure there is never more that MAX_HEAP_EXCESS space on the heap heapSizeMax = trackHeapSize + totalSize + MAX_HEAP_EXCESS; } } pHeapEntry = (tHeapEntry *)Mem.malloc(totalSize); pHeapEntry->pTypeDef = pTypeDef; pHeapEntry->signature = VALID_HEAP_OBJ_SIG; pHeapEntry->pSync = null; pHeapEntry->needToFinalize = (byte)((pTypeDef->pFinalizer != null) ? 1 : 0); pMem = (byte *)pHeapEntry + sizeof(tHeapEntry); Mem.memset(pMem, 0, size); trackHeapSize += totalSize; pHeapTreeRoot = TreeInsert(pHeapTreeRoot, pHeapEntry); numNodes++; return(pMem); }
public static tThread *New() { tThread *pThis; // Create thread and initial method state. This is allocated on the managed heap, and // mark as undeletable. When the thread exits, it was marked as deletable. pThis = (tThread *)Heap.AllocType(Type.types[Type.TYPE_SYSTEM_THREADING_THREAD]); Heap.MakeUndeletable((/*HEAP_PTR*/ byte *)pThis); Mem.memset(pThis, 0, (SIZE_T)sizeof(tThread)); pThis->threadID = ++threadID; Reset(pThis); // Add to list of all thread pThis->pNextThread = pAllThreads; pAllThreads = pThis; return(pThis); }
public static void *StackAlloc(tThread *pThread, uint size) { tThreadStack *pStack = pThread->pThreadStack; void * pAddr = pStack->memory + pStack->ofs; #if _DEBUG *(uint *)pAddr = 0xabababab; ((uint *)pAddr)++; pStack->ofs += 4; #endif pStack->ofs += size; if (pStack->ofs > tThreadStack.THREADSTACK_CHUNK_SIZE) { Sys.Crash("Thread-local stack is too large"); } #if _DEBUG Mem.memset(pAddr, 0xcd, size); *(uint *)(((byte *)pAddr) + size) = 0xfbfbfbfb; pStack->ofs += 4; #endif return(pAddr); }
// Value-Type.types will be boxed public static tAsyncCall *Internal_SetValue(tJITCallNative *pCallNative, byte *pThis_, byte *pParams, byte *pReturnValue) { tSystemArray * pArray = (tSystemArray *)pThis_; tMD_TypeDef * pArrayType, pObjType; uint index, elementSize; /*HEAP_PTR*/ byte *obj; tMD_TypeDef * pElementType; byte * pElement; pArrayType = Heap.GetType(pThis_); obj = (*((byte **)(pParams + 0))); pObjType = Heap.GetType(obj); pElementType = pArrayType->pArrayElementType; // Check to see if the Type is ok to put in the array if (!(Type.IsAssignableFrom(pElementType, pObjType) != 0 || (pElementType->pGenericDefinition == Type.types[Type.TYPE_SYSTEM_NULLABLE] && pElementType->ppClassTypeArgs[0] == pObjType))) { // Can't be done Sys.INTERNALCALL_RESULT_U32(pReturnValue, 0); return(null); } index = (*((uint *)(pParams + Sys.S_PTR))); #if WIN32 && _DEBUG // Do a bounds-check if (index >= pArray->length) { printf("[Array] Internal_SetValue() Bounds-check failed\n"); __debugbreak(); } #endif elementSize = pElementType->arrayElementSize; pElement = tSystemArray.GetElements(pArray) + elementSize * index; if (pElementType->isValueType != 0) { if (pElementType->pGenericDefinition == Type.types[Type.TYPE_SYSTEM_NULLABLE]) { // Nullable type, so treat specially if (obj == null) { Mem.memset(pElement, 0, elementSize); } else { *(uint *)pElement = 1; Mem.memcpy(pElement + 4, obj, elementSize - 4); } } else { // Get the value out of the box Mem.memcpy(pElement, obj, elementSize); } } else { // This must be a reference type, so it must be 32-bits wide *(/*HEAP_PTR*/ byte **)pElement = obj; } Sys.INTERNALCALL_RESULT_U32(pReturnValue, 1); return(null); }
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 void Fill_TypeDef(tMD_TypeDef *pTypeDef, tMD_TypeDef **ppClassTypeArgs, tMD_TypeDef **ppMethodTypeArgs, uint resolve = Type.TYPE_FILL_ALL) { /*IDX_TABLE*/ uint firstIdx, lastIdx, token; uint instanceMemSize, staticMemSize, virtualOfs, isDeferred, i, j; tMetaData * pMetaData = pTypeDef->pMetaData; tMD_TypeDef *pParent; if (pTypeDef->fillState >= resolve) { return; } if (pTypeDef->monoType != null) { MonoType.Fill_TypeDef(pTypeDef, ppClassTypeArgs, ppMethodTypeArgs, resolve); return; } // Sys.printf("FILLING TYPE: %s\n", (PTR)pTypeDef->name); // string name = System.Runtime.InteropServices.Marshal.PtrToStringAnsi((System.IntPtr)pTypeDef->name); if (typesToFill == null) { 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); // Fill parent info if (pTypeDef->fillState < Type.TYPE_FILL_PARENTS) { pTypeDef->fillState = Type.TYPE_FILL_PARENTS; pTypeDef->pTypeDef = pTypeDef; if (pTypeDef->alignment == 0) { pTypeDef->alignment = 1; } if (pTypeDef->pParent == null) { pTypeDef->pParent = MetaData.GetTypeDefFromDefRefOrSpec(pMetaData, pTypeDef->extends, ppClassTypeArgs, ppMethodTypeArgs); } pParent = pTypeDef->pParent; if (pParent != null) { if (pParent->fillState < Type.TYPE_FILL_PARENTS) { MetaData.Fill_TypeDef(pParent, null, null, Type.TYPE_FILL_PARENTS); } else if (pParent->fillState < Type.TYPE_FILL_ALL) { MetaData.Fill_Defer(pParent, null, null); } pTypeDef->hasMonoBase = pParent->hasMonoBase; 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 { pTypeDef->blittable = pTypeDef->fixedBlittable = 1; } // If this type is an interface, then return 0 if (pTypeDef->stackSize != 0) { pTypeDef->isValueType = (byte)(pTypeDef->stackType != EvalStack.EVALSTACK_O ? 1 : 0); } else if (MetaData.TYPE_ISINTERFACE(pTypeDef)) { pTypeDef->isValueType = 0; } else if (pTypeDef->nameSpace[0] == 'S' && S.strcmp(pTypeDef->nameSpace, new S(ref scSystem, "System")) == 0) { if ((pTypeDef->name[0] == 'V' && S.strcmp(pTypeDef->name, new S(ref scValueType, "ValueType")) == 0) || (pTypeDef->name[0] == 'E' && S.strcmp(pTypeDef->name, new S(ref scEnum, "Enum")) == 0)) { pTypeDef->isValueType = 1; } else if (pTypeDef->name[0] == 'O' && S.strcmp(pTypeDef->name, new S(ref scObject, "Object")) == 0) { pTypeDef->isValueType = 0; } else if (pParent != null) { pTypeDef->isValueType = pParent->isValueType; } } else if (pParent != null) { pTypeDef->isValueType = pParent->isValueType; } // If not primed, then work out how many methods & fields there are. if (pTypeDef->isPrimed == 0) { // Methods lastIdx = (pTypeDef->isLast != 0) ? MetaData.MAKE_TABLE_INDEX(MetaDataTable.MD_TABLE_METHODDEF, pTypeDef->pMetaData->tables.numRows[MetaDataTable.MD_TABLE_METHODDEF]) : (pTypeDef[1].methodList - 1); pTypeDef->numMethods = lastIdx - pTypeDef->methodList + 1; // Fields lastIdx = (pTypeDef->isLast != 0) ? MetaData.MAKE_TABLE_INDEX(MetaDataTable.MD_TABLE_FIELDDEF, pTypeDef->pMetaData->tables.numRows[MetaDataTable.MD_TABLE_FIELDDEF]) : (pTypeDef[1].fieldList - 1); pTypeDef->numFields = lastIdx - pTypeDef->fieldList + 1; } // 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; } // 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); } } if (pTypeDef->isGenericDefinition == 0) { // 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. firstIdx = pTypeDef->fieldList; lastIdx = firstIdx + pTypeDef->numFields - 1; staticMemSize = 0; if (pTypeDef->numFields > 0) { pTypeDef->ppFields = (tMD_FieldDef **)Mem.mallocForever((SIZE_T)(pTypeDef->numFields * sizeof(tMD_FieldDef *))); } instanceMemSize = (pParent == null ? 0 : pTypeDef->pParent->instanceMemSize); if (pTypeDef->hasMonoBase != 0 && pParent->hasMonoBase == 0) { // Some DNA types like String are actually wrappers around mono objects. In those cases, we need to allocate the // space in the instance memory for the GCHandle to the mono object. We distinguish this case from the case // where we're just extending a Mono Type object by checking if the parent also has the hasMonoBase flag set. instanceMemSize += (uint)sizeof(void *); } for (token = firstIdx, i = 0; token <= lastIdx; token++, i++) { tMD_FieldDef *pFieldDef; pFieldDef = MetaData.GetFieldDefFromDefOrRef(pMetaData, token, ppClassTypeArgs, ppMethodTypeArgs); if (!MetaData.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 = ((tMD_FieldDef *)Mem.mallocForever((SIZE_T)sizeof(tMD_FieldDef))); Mem.memcpy(pFieldCopy, pFieldDef, (SIZE_T)sizeof(tMD_FieldDef)); pFieldDef = pFieldCopy; } if (MetaData.FIELD_ISLITERAL(pFieldDef) || 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 MetaData.Fill_FieldDef(pTypeDef, pFieldDef, 0, null, ppClassTypeArgs); } else { MetaData.Fill_FieldDef(pTypeDef, 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) { pTypeDef->instanceMemSize = (instanceMemSize + (pTypeDef->alignment - 1)) & ~(pTypeDef->alignment - 1); } // 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 (token = firstIdx, i = 0; token <= lastIdx; token++, i++) { tMD_FieldDef *pFieldDef; pFieldDef = MetaData.GetFieldDefFromDefOrRef(pMetaData, token, ppClassTypeArgs, ppMethodTypeArgs); if (MetaData.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 = ((tMD_FieldDef *)Mem.mallocForever((SIZE_T)sizeof(tMD_FieldDef))); Mem.memcpy(pFieldCopy, pFieldDef, (SIZE_T)sizeof(tMD_FieldDef)); pFieldDef = pFieldCopy; } if (MetaData.FIELD_ISLITERAL(pFieldDef) || 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 MetaData.Fill_FieldDef(pTypeDef, pFieldDef, 0, null, ppClassTypeArgs); } else { MetaData.Fill_FieldDef(pTypeDef, pFieldDef, staticMemSize, null, ppClassTypeArgs); staticMemSize += pFieldDef->memSize; } pTypeDef->ppFields[i] = pFieldDef; } } if (staticMemSize > 0) { pTypeDef->pStaticFields = (byte *)Mem.mallocForever((SIZE_T)staticMemSize); Mem.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 (MetaData.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; } } if (pTypeDef->fillState >= resolve) { return; } } // 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->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); } } if (pTypeDef->isGenericDefinition == 0) { virtualOfs = (pParent != null) ? pParent->numVirtualMethods : 0; // Must create the virtual method table BEFORE any other type resolution is done // Note that this must not do ANY filling of type or methods. // This is to ensure that the parent object(s) in any type inheritance hierachy are allocated // their virtual method offset before derived Type.types. firstIdx = pTypeDef->methodList; lastIdx = firstIdx + pTypeDef->numMethods - 1; for (token = firstIdx; token <= lastIdx; token++) { tMD_MethodDef *pMethodDef; pMethodDef = MetaData.GetMethodDefFromDefRefOrSpec(pMetaData, token, ppClassTypeArgs, ppMethodTypeArgs); //Sys.printf("Method: %s\n", (PTR)pMethodDef->name); // This is needed, so array resolution can work correctly and FindVirtualOverriddenMethod() can work. pMethodDef->pParentType = pTypeDef; if (MetaData.METHOD_ISVIRTUAL(pMethodDef)) { if (MetaData.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); if (pVirtualOveriddenMethod == null) { Sys.Crash("Unable to find virtual override method for %s %s", (PTR)pTypeDef->name, (PTR)pMethodDef->name); } 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 all members firstIdx = pTypeDef->methodList; lastIdx = firstIdx + pTypeDef->numMethods - 1; pTypeDef->ppMethods = (tMD_MethodDef **)Mem.mallocForever((SIZE_T)(pTypeDef->numMethods * sizeof(tMD_MethodDef *))); pTypeDef->pVTable = (tMD_MethodDef **)Mem.mallocForever((SIZE_T)(pTypeDef->numVirtualMethods * sizeof(tMD_MethodDef *))); // Copy initial vTable from parent if (pTypeDef->pParent != null) { if (pTypeDef->pParent->fillState != Type.TYPE_FILL_MEMBERS) { Fill_TypeDef(pTypeDef->pParent, null, null, Type.TYPE_FILL_MEMBERS); } Mem.memcpy(pTypeDef->pVTable, pTypeDef->pParent->pVTable, (SIZE_T)(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 = ((tMD_MethodDef *)Mem.mallocForever((SIZE_T)sizeof(tMD_MethodDef))); Mem.memcpy(pMethodCopy, pMethodDef, (SIZE_T)sizeof(tMD_MethodDef)); pMethodDef = pMethodCopy; } if (MetaData.METHOD_ISSTATIC(pMethodDef) && S.strcmp(pMethodDef->name, ".cctor") == 0) { // This is a static constructor pTypeDef->pStaticConstructor = pMethodDef; } if (!MetaData.METHOD_ISSTATIC(pMethodDef) && pTypeDef->pParent != null && S.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 (MetaData.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; } } } 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); } } if (pTypeDef->isGenericDefinition == 0) { // Fill all method definitions for this type for (i = 0; i < pTypeDef->numMethods; i++) { MetaData.Fill_MethodDef(pTypeDef, 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); } } if (pTypeDef->isGenericDefinition == 0 && !MetaData.TYPE_ISINTERFACE(pTypeDef)) { if (pParent != null && pParent->fillState < Type.TYPE_FILL_INTERFACES) { MetaData.Fill_TypeDef(pParent, null, null, Type.TYPE_FILL_INTERFACES); } // Map all interface method calls. This only needs to be done for Classes, not Interfaces // And is not done for generic definitions. firstIdx = 0; if (pTypeDef->pParent != null) { j = pTypeDef->numInterfaces = pTypeDef->pParent->numInterfaces; } else { j = 0; } lastIdx = firstIdx; for (i = 1; i <= pMetaData->tables.numRows[MetaDataTable.MD_TABLE_INTERFACEIMPL]; i++) { tMD_InterfaceImpl *pInterfaceImpl; pInterfaceImpl = (tMD_InterfaceImpl *)MetaData.GetTableRow(pMetaData, MetaData.MAKE_TABLE_INDEX(MetaDataTable.MD_TABLE_INTERFACEIMPL, i)); if (pInterfaceImpl->class_ == pTypeDef->tableIndex) { // count how many interfaces are implemented pTypeDef->numInterfaces++; if (firstIdx == 0) { firstIdx = MetaData.MAKE_TABLE_INDEX(MetaDataTable.MD_TABLE_INTERFACEIMPL, i); } lastIdx = MetaData.MAKE_TABLE_INDEX(MetaDataTable.MD_TABLE_INTERFACEIMPL, i); } } if (pTypeDef->numInterfaces > 0) { uint mapNum; pTypeDef->pInterfaceMaps = (tInterfaceMap *)Mem.mallocForever((SIZE_T)(pTypeDef->numInterfaces * sizeof(tInterfaceMap))); // Copy interface maps from parent type if (j > 0) { Mem.memcpy(pTypeDef->pInterfaceMaps, pTypeDef->pParent->pInterfaceMaps, (SIZE_T)(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, Type.TYPE_FILL_INTERFACES); pMap = &pTypeDef->pInterfaceMaps[mapNum]; 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 *))); // Discover interface mapping for each interface method for (i = 0; i < pInterface->numVirtualMethods; i++) { tMD_MethodDef *pInterfaceMethod; tMD_MethodDef *pOverriddenMethod; pInterfaceMethod = pInterface->pVTable[i]; pOverriddenMethod = FindVirtualOverriddenMethod(pTypeDef, pInterfaceMethod); pMap->pVTableLookup[i] = pOverriddenMethod->vTableOfs; pMap->ppMethodVLookup[i] = pOverriddenMethod; } } else { Sys.Crash("Problem with interface class"); } } } } } if (pTypeDef->fillState >= resolve) { return; } } if (pTypeDef->fillState < Type.TYPE_FILL_ALL) { pTypeDef->fillState = Type.TYPE_FILL_ALL; if (pTypeDef->isGenericDefinition == 0 && pTypeDef->stackSize == 0) { j = 0; } if (pParent != null && pParent->fillState < Type.TYPE_FILL_ALL) { MetaData.Fill_TypeDef(pParent, null, null, Type.TYPE_FILL_ALL); } if (isDeferred != 0) { Fill_ResolveDeferred(); } } Sys.log_f(2, "Type: %s.%s\n", (PTR)pTypeDef->nameSpace, (PTR)pTypeDef->name); }
public static tMD_TypeDef *GetGenericTypeFromCoreType(tMD_TypeDef *pCoreType, uint numTypeArgs, tMD_TypeDef **ppTypeArgs) { tGenericInstance *pInst; tMD_TypeDef * pTypeDef; uint i; byte * name = stackalloc byte[NAME_BUF_SIZE]; byte * namePos, nameEnd; tMetaData *pMetaData; Mem.heapcheck(); pMetaData = pCoreType->pMetaData; MetaData.Fill_TypeDef(pCoreType, null, null, Type.TYPE_FILL_PARENTS); // 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 && Mem.memcmp(pInst->ppTypeArgs, ppTypeArgs, (SIZE_T)(numTypeArgs * sizeof(tMD_TypeDef *))) == 0) { return(pInst->pInstanceTypeDef); } pInst = pInst->pNext; } // This has not already been instantiated, so instantiate it now. pInst = (tGenericInstance *)Mem.mallocForever((SIZE_T)sizeof(tGenericInstance)); // Insert this into the chain of instantiations. pInst->pNext = pCoreType->pGenericInstances; pCoreType->pGenericInstances = pInst; // Copy the type args into the instantiation. 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 *))); Mem.heapcheck(); // Create the new instantiated type pInst->pInstanceTypeDef = pTypeDef = ((tMD_TypeDef *)Mem.mallocForever((SIZE_T)sizeof(tMD_TypeDef))); Mem.memset(pTypeDef, 0, (SIZE_T)sizeof(tMD_TypeDef)); // Make the name of the instantiation. namePos = name; nameEnd = namePos + NAME_BUF_SIZE - 1; namePos = S.scatprintf(namePos, nameEnd, "%s", (PTR)pCoreType->name); namePos = S.scatprintf(namePos, nameEnd, "["); for (i = 0; i < numTypeArgs; i++) { if (i > 0) { namePos = S.scatprintf(namePos, nameEnd, ","); } if (ppTypeArgs[i] != null) { namePos = S.scatprintf(namePos, nameEnd, "%s.%s", (PTR)ppTypeArgs[i]->nameSpace, (PTR)ppTypeArgs[i]->name); } else { tMD_GenericParam *pGenericParam = FindGenericParam(pCoreType, i); if (pGenericParam != null) { namePos = S.scatprintf(namePos, nameEnd, "%s", (PTR)pGenericParam->name); } else { namePos = S.scatprintf(namePos, nameEnd, "???"); } } } namePos = S.scatprintf(namePos, nameEnd, "]"); // 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; int nameLen = S.strlen(name) + 1; pTypeDef->name = (/*STRING*/ byte *)Mem.mallocForever((SIZE_T)nameLen); S.strncpy(pTypeDef->name, name, nameLen); pTypeDef->ppClassTypeArgs = pInst->ppTypeArgs; 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, pInst->ppTypeArgs, null, Type.TYPE_FILL_PARENTS); Mem.heapcheck(); return(pTypeDef); }
static int InternalLoadAndRun(bool tryRun, string[] args) { if (!_isInitialized) { Init(); } /*char**/ byte *pFileName = new S(args[0]); tCLIFile * pCLIFile; int retValue; #if DIAG_TOTAL_TIME ulong startTime; #endif #if DIAG_OPCODE_TIMES Mem.memset(opcodeTimes, 0, sizeof(opcodeTimes)); #endif #if DIAG_OPCODE_USE Mem.memset(opcodeNumUses, 0, sizeof(opcodeNumUses)); #endif pCLIFile = CLIFile.LoadAssembly(pFileName); #if DIAG_TOTAL_TIME startTime = microTime(); #endif if (tryRun) { if (pCLIFile->entryPoint != 0) { retValue = CLIFile.Execute(pCLIFile, args); } else { Sys.printf("File %s has no entry point, skipping execution\n", (PTR)pFileName); retValue = 0; } } else { retValue = 0; } #if DIAG_TOTAL_TIME printf("Total execution time = %d ms\n", (int)((microTime() - startTime) / 1000)); #endif #if DIAG_GC printf("Total GC time = %d ms\n", (int)(Heap.gcTotalTime / 1000)); #endif #if DIAG_METHOD_CALLS { uint numMethods, i; int howMany = 25; tMetaData *pCorLib; // Report on most-used methods pCorLib = CLIFile_GetMetaDataForAssembly("mscorlib"); numMethods = pCorLib->tables.numRows[MetaDataTable.MD_TABLE_METHODDEF]; printf("\nCorLib method usage:\n"); for (; howMany > 0; howMany--) { tMD_MethodDef *pMethod; uint maxCount = 0, maxIndex = 0; for (i = 1; i <= numMethods; i++) { pMethod = (tMD_MethodDef *)MetaData.GetTableRow(pCorLib, MetaData.MAKE_TABLE_INDEX(MetaDataTable.MD_TABLE_METHODDEF, i)); if (pMethod->callCount > maxCount) { maxCount = pMethod->callCount; maxIndex = i; } } pMethod = (tMD_MethodDef *)MetaData.GetTableRow(pCorLib, MetaData.MAKE_TABLE_INDEX(MetaDataTable.MD_TABLE_METHODDEF, maxIndex)); printf("%d: %s (%d)\n", (int)pMethod->callCount, Sys_GetMethodDesc(pMethod), (int)(pMethod->totalTime / 1000)); pMethod->callCount = 0; } printf("\n"); } { uint numMethods, i; int howMany = 25; tMetaData *pCorLib; // Report on most-used methods pCorLib = CLIFile_GetMetaDataForAssembly("mscorlib"); numMethods = pCorLib->tables.numRows[MetaDataTable.MD_TABLE_METHODDEF]; printf("\nCorLib method execution time:\n"); for (; howMany > 0; howMany--) { tMD_MethodDef *pMethod; ulong maxTime = 0; uint maxIndex = 0; for (i = 1; i <= numMethods; i++) { pMethod = (tMD_MethodDef *)MetaData.GetTableRow(pCorLib, MetaData.MAKE_TABLE_INDEX(MetaDataTable.MD_TABLE_METHODDEF, i)); if (pMethod->totalTime > maxTime) { maxTime = pMethod->totalTime; maxIndex = i; } } pMethod = (tMD_MethodDef *)MetaData.GetTableRow(pCorLib, MetaData.MAKE_TABLE_INDEX(MetaDataTable.MD_TABLE_METHODDEF, maxIndex)); printf("%d: %s (%d)\n", (int)pMethod->callCount, Sys_GetMethodDesc(pMethod), (int)(pMethod->totalTime / 1000)); pMethod->totalTime = 0; } printf("\n"); } #endif #if DIAG_OPCODE_TIMES { int howMany = 25; uint i; printf("\nOpCodes execution time:\n"); for (; howMany > 0; howMany--) { ulong maxTime = 0; uint maxIndex = 0; for (i = 0; i < JitOps.JIT_OPCODE_MAXNUM; i++) { if (opcodeTimes[i] > maxTime) { maxTime = opcodeTimes[i]; maxIndex = i; } } printf("0x%03x: %dms (used %d times) (ave = %d)\n", maxIndex, (int)(maxTime / 1000), (int)opcodeNumUses[maxIndex], (int)(maxTime / opcodeNumUses[maxIndex])); opcodeTimes[maxIndex] = 0; } } #endif #if DIAG_OPCODE_USE { int howMany = 25; uint i, j; printf("\nOpcode use:\n"); for (j = 1; howMany > 0; howMany--, j++) { uint maxUse = 0; uint maxIndex = 0; for (i = 0; i < JitOps.JIT_OPCODE_MAXNUM; i++) { if (opcodeNumUses[i] > maxUse) { maxUse = opcodeNumUses[i]; maxIndex = i; } } printf("%02d 0x%03x: %d\n", j, maxIndex, maxUse); opcodeNumUses[maxIndex] = 0; } } #endif //Sys.Crash("FINISHED!!!"); return(retValue); }
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); }
public static tMetaData *GetMetaDataForAssembly(byte *pAssemblyName) { tFilesLoaded *pFiles; int monoAssembly = 0; tCLIFile * pCLIFile = null; tMD_Assembly *pThisAssembly = null; tMetaData ** ppChildMetaData = null; int i, j, childCount; // Check corlib assemblies i = 0; while (dnaCorlibAssemblies[i] != null) { if (S.strcmp(pAssemblyName, dnaCorlibAssemblies[i]) == 0) { pAssemblyName = scCorLib; break; } i++; } // Look in already-loaded files first pFiles = pFilesLoaded; while (pFiles != null) { pCLIFile = pFiles->pCLIFile; if (S.strcmp(pAssemblyName, pCLIFile->assemblyName) == 0) { // Found the correct assembly, so return its meta-data return(pCLIFile->pMetaData); } pFiles = pFiles->pNext; } // Mono/Unity assemblies only load metadata, no code if (monoAssemblies != null) { i = 0; while (monoAssemblies[i] != null) { if (S.strcmp(pAssemblyName, monoAssemblies[i]) == 0) { if (i == 0) { // Handle "UnityEngine" assemblies j = 0; childCount = 0; while (unityModuleAssemblies[j] != null) { childCount++; j++; } ppChildMetaData = (tMetaData **)Mem.malloc((SIZE_T)((childCount + 1) * sizeof(tMetaData *))); Mem.memset(ppChildMetaData, 0, (SIZE_T)((childCount + 1) * sizeof(tMetaData *))); j = 0; while (unityModuleAssemblies[j] != null) { ppChildMetaData[j] = GetMetaDataForAssembly(unityModuleAssemblies[j]); j++; } } monoAssembly = 1; break; } i++; } } // Assembly not loaded, so load it if possible if (monoAssembly != 0) { pCLIFile = CLIFile.WrapMonoAssembly(pAssemblyName); if (pCLIFile == null) { Sys.Crash("Cannot load required mono assembly file: %s.dll", (PTR)pAssemblyName); } } else { byte *fileName = stackalloc byte[256]; S.snprintf(fileName, 256, "%s.dll", (PTR)pAssemblyName); pCLIFile = CLIFile.LoadAssembly(fileName); if (pCLIFile == null) { Sys.Crash("Cannot load required assembly file: %s.dll", (PTR)pAssemblyName); } } pCLIFile->pMetaData->ppChildMetaData = ppChildMetaData; return(pCLIFile->pMetaData); }