Ejemplo n.º 1
0
        public static tMetaData *GetResolutionScopeMetaData(tMetaData *pMetaData, /*IDX_TABLE*/ uint resolutionScopeToken,
                                                            tMD_TypeDef **ppInNestedType)
        {
            switch (MetaData.TABLE_ID(resolutionScopeToken))
            {
            case MetaDataTable.MD_TABLE_ASSEMBLYREF:
            {
                tMD_AssemblyRef *pAssemblyRef;

                pAssemblyRef = (tMD_AssemblyRef *)MetaData.GetTableRow(pMetaData, resolutionScopeToken);
                *ppInNestedType = null;
                return(CLIFile.GetMetaDataForAssembly(pAssemblyRef->name));
            }

            case MetaDataTable.MD_TABLE_TYPEREF:
            {
                tMD_TypeDef *pTypeDef;

                pTypeDef = MetaData.GetTypeDefFromDefRefOrSpec(pMetaData, resolutionScopeToken, null, null);
                *ppInNestedType = pTypeDef;
                return(pTypeDef->pMetaData);
            }

            default:
                Sys.Crash("MetaData.GetResolutionScopeMetaData(): Cannot resolve token: 0x%08x", resolutionScopeToken);
                return(null);
            }
        }
Ejemplo n.º 2
0
        public static tMD_TypeDef *GetTypeDefFromFullName(/*STRING*/ byte *assemblyName, /*STRING*/ byte *nameSpace, /*STRING*/ byte *name)
        {
            tMetaData *pTypeMetaData;

            pTypeMetaData = CLIFile.GetMetaDataForAssembly(assemblyName);

            // Note that this cannot get a nested class, as this final parameter is always null
            return(MetaData.GetTypeDefFromName(pTypeMetaData, nameSpace, name, null, /* assertExists */ 1));
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Returns a DNA TypeDef for a given type.
        /// </summary>
        /// <param name="type">The fully qualified name of the type (namespace and type name)</param>
        /// <returns>The TypeDef or 0 if no type by that name was found</returns>
        public static ulong FindType(string type)
        {
            byte *className = stackalloc byte[128];
            byte *nameSpace = stackalloc byte[128];

            if (!_isInitialized)
            {
                Init();
            }

            string[] split = type.Split('.');

            if (split.Length < 1)
            {
                throw new System.ArgumentException("Type must have at least a type name");
            }

            if (split.Length > 1)
            {
                System.Text.StringBuilder sb = new System.Text.StringBuilder();
                for (int i = 0; i < split.Length - 1; i++)
                {
                    if (i > 0)
                    {
                        sb.Append('.');
                    }
                    sb.Append(split[i]);
                }
                S.strncpy(nameSpace, sb.ToString(), 128);
            }
            else
            {
                nameSpace[0] = 0;
            }
            S.strncpy(className, split[split.Length - 1], 128);

            // Find any overload of the named method; assume it's the right one.
            // Specifying it exactly (type generic args, method generic args, arguments themselves, picking the
            // inherited methods if needed), is complex and not required at the moment.
            tMD_TypeDef *pTypeDef = CLIFile.FindTypeInAllLoadedAssemblies(nameSpace, className);

            if (pTypeDef->fillState < Type.TYPE_FILL_ALL)
            {
                MetaData.Fill_TypeDef(pTypeDef, null, null);
            }

            return((ulong)pTypeDef);
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Initializes the DNA script engine.
        /// </summary>
        /// <param name="memsize">The heap memory size to use (note: can not be expanded)</param>
        /// <param name="assemblySearchPaths">Array of assembly search paths to use when loading assemblies</param>
        public static void Init(int memsize = DEFAULT_MEM_SIZE, string[] assemblySearchPaths = null)
        {
            if (_isInitialized)
            {
                throw new System.InvalidOperationException("Dna has already been initialized.  Use Dna.Reset() to reset the interpreter");
            }

            if (assemblySearchPaths == null)
            {
                assemblySearchPaths = defaultAssemblySearchPaths;
            }
            #if UNITY_EDITOR
            string[] finalAssemblySearchPaths = new string[assemblySearchPaths.Length];
            string   unityDir   = UnityEditor.EditorApplication.applicationContentsPath;
            string   projectDir = System.IO.Path.GetDirectoryName(UnityEngine.Application.dataPath);
            for (int i = 0; i < assemblySearchPaths.Length; i++)
            {
                finalAssemblySearchPaths[i] = assemblySearchPaths[i]
                                              .Replace("${UNITY_DIR}", unityDir)
                                              .Replace("${PROJECT_DIR}", projectDir);
            }
            #else
            string[] finalAssemblySearchPaths = assemblySearchPaths;
            #endif

            Mem.Init(memsize);
            H.Init();
            Sys.Init();
            JIT.Init();
            JIT_Execute.Init();
            DnaObject.Init();
            MetaData.Init();
            MonoType.Init();
            Generics.Init();
            Serialization.Init();
            Heap.Init();
            Finalizer.Init();
            InternalCall.Init();
            CLIFile.Init(finalAssemblySearchPaths);
            Type.Init();

            _isInitialized = true;
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Resets entire DNA environment to it's initial state, clearing all DnaObject references to null.
        /// </summary>
        public static void Reset()
        {
            Type.Clear();
            CLIFile.Clear();
            InternalCall.Clear();
            Finalizer.Clear();
            Heap.Clear();
            Generics.Clear();
            MonoType.Clear();
            MetaData.Clear();
            DnaObject.Clear();
            JIT_Execute.Clear();
            JIT.Clear();
            Sys.Clear();
            H.Clear();
            Mem.Clear();

            _isInitialized = false;
        }
Ejemplo n.º 6
0
        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);
        }
Ejemplo n.º 7
0
        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);
        }
Ejemplo n.º 8
0
        public static void GarbageCollect()
        {
#if NO
            tHeapRoots   heapRoots;
            tHeapEntry * pNode;
            tHeapEntry **pUp = stackalloc tHeapEntry *[MAX_TREE_DEPTH * 2];
            int          top;
            tHeapEntry * pToDelete   = null;
            SIZE_T       orgHeapSize = trackHeapSize;
            uint         orgNumNodes = numNodes;
            #if DIAG_GC
            ulong startTime;
            #endif

            Mem.heapcheck();

            numCollections++;

        #if DIAG_GC
            startTime = microTime();
        #endif

            heapRoots.capacity     = 64;
            heapRoots.num          = 0;
            heapRoots.pHeapEntries = (tHeapRootEntry *)Mem.malloc(heapRoots.capacity * (SIZE_T)sizeof(tHeapRootEntry));

            Thread.GetHeapRoots(&heapRoots);
            CLIFile.GetHeapRoots(&heapRoots);

            // Mark phase
            while (heapRoots.num > 0)
            {
                tHeapRootEntry *pRootsEntry;
                uint            i;
                uint            moreRootsAdded = 0;
                uint            rootsEntryNumPointers;
                void **         pRootsEntryMem;

                // Get a piece of memory off the list of heap memory roots.
                pRootsEntry           = &heapRoots.pHeapEntries[heapRoots.num - 1];
                rootsEntryNumPointers = pRootsEntry->numPointers;
                pRootsEntryMem        = pRootsEntry->pMem;
                // Mark this entry as done
                pRootsEntry->numPointers = 0;
                pRootsEntry->pMem        = null;
                // Iterate through all pointers in it
                for (i = 0; i < rootsEntryNumPointers; i++)
                {
                    void *pMemRef = pRootsEntryMem[i];
                    // Quick escape for known non-memory
                    if (pMemRef == null)
                    {
                        continue;
                    }
                    // Find this piece of heap memory in the tracking tree.
                    // Note that the 2nd memory address comparison MUST be >, not >= as might be expected,
                    // to allow for a zero-sized memory to be detected (and not garbage collected) properly.
                    // E.g. The object class has zero memory.
                    pNode = pHeapTreeRoot;
                    while (pNode != nil)
                    {
                        if (pMemRef < (void *)pNode)
                        {
                            pNode = (tHeapEntry *)pNode->pLink[0];
                        }
                        else if ((byte *)pMemRef > ((byte *)pNode) + GetSize(pNode) + sizeof(tHeapEntry))
                        {
                            pNode = (tHeapEntry *)pNode->pLink[1];
                        }
                        else
                        {
                            // Found memory. See if it's already been marked.
                            // If it's already marked, then don't do anything.
                            // It it's not marked, then add all of its memory to the roots, and mark it.
                            if (pNode->marked == 0)
                            {
                                tMD_TypeDef *pType = pNode->pTypeDef;

                                // Not yet marked, so mark it, and add it to heap roots.
                                pNode->marked = 1;

                                // Don't look at the contents of strings, arrays of primitive Type.types, or WeakReferences
                                if (pType->stackType == EvalStack.EVALSTACK_O ||
                                    pType->stackType == EvalStack.EVALSTACK_VALUETYPE ||
                                    pType->stackType == EvalStack.EVALSTACK_PTR)
                                {
                                    if (pType != Type.types[Type.TYPE_SYSTEM_STRING] &&
                                        (!MetaData.TYPE_ISARRAY(pType) ||
                                         pType->pArrayElementType->stackType == EvalStack.EVALSTACK_O ||
                                         pType->pArrayElementType->stackType == EvalStack.EVALSTACK_VALUETYPE ||
                                         pType->pArrayElementType->stackType == EvalStack.EVALSTACK_PTR))
                                    {
                                        if (pType != Type.types[Type.TYPE_SYSTEM_WEAKREFERENCE])
                                        {
                                            Heap.SetRoots(&heapRoots, ((byte *)&pNode->pSync + sizeof(PTR)), GetSize(pNode));
                                            moreRootsAdded = 1;
                                        }
                                    }
                                }
                            }
                            break;
                        }
                    }
                }
                if (moreRootsAdded == 0)
                {
                    heapRoots.num--;
                }
            }

            Mem.free(heapRoots.pHeapEntries);

            // Sweep phase
            // Traverse nodes
            pUp[0] = pHeapTreeRoot;
            top    = 1;
            while (top != 0)
            {
                // Get this node
                pNode = pUp[--top];
                // Act on this node
                if (pNode->marked != 0)
                {
                    if (pNode->marked != 0xff)
                    {
                        // Still in use (but not marked undeletable), so unmark
                        pNode->marked = 0;
                    }
                }
                else
                {
                    // Not in use any more, so put in deletion queue if it does not need Finalizing
                    // If it does need Finalizing, then don't garbage collect, and put in Finalization queue.
                    if (pNode->needToFinalize != 0)
                    {
                        if (pNode->needToFinalize == 1)
                        {
                            Finalizer.AddFinalizer((/*HEAP_PTR*/ byte *)pNode + sizeof(tHeapEntry));
                            // Mark it has having been placed in the finalization queue.
                            // When it has been finalized, then this will be set to 0
                            pNode->needToFinalize = 2;
                            // If this object is being targetted by weak-ref(s), handle it
                            if (pNode->pSync != null)
                            {
                                RemoveWeakRefTarget(pNode, 0);
                                Mem.free(pNode->pSync);
                            }
                        }
                    }
                    else
                    {
                        // If this object is being targetted by weak-ref(s), handle it
                        if (pNode->pSync != null)
                        {
                            RemoveWeakRefTarget(pNode, 1);
                            Mem.free(pNode->pSync);
                        }
                        // Use pSync to point to next entry in this linked-list.
                        pNode->pSync = (tSync *)pToDelete;
                        pToDelete    = pNode;
                    }
                }
                // Get next node(s)
                if (pNode->pLink[1] != (PTR)nil)
                {
                    pUp[top++] = (tHeapEntry *)pNode->pLink[1];
                }
                if (pNode->pLink[0] != (PTR)nil)
                {
                    pUp[top++] = (tHeapEntry *)pNode->pLink[0];
                }
            }

            // Delete all unused memory nodes.
            while (pToDelete != null)
            {
                tHeapEntry *pThis = pToDelete;
                pToDelete     = (tHeapEntry *)(pToDelete->pSync);
                pHeapTreeRoot = TreeRemove(pHeapTreeRoot, pThis);
                if (pThis->monoHandle == 1)
                {
                    void *hptr = *(void **)((byte *)pThis + sizeof(tHeapEntry));
                    if (hptr != null)
                    {
                        H.Free(hptr);
                    }
                }
                numNodes--;
                trackHeapSize -= GetSize(pThis) + (uint)sizeof(tHeapEntry);
                Mem.free(pThis);
            }

            Mem.heapcheck();

        #if DIAG_GC
            gcTotalTime += microTime() - startTime;
        #endif

            Sys.log_f(1, "--- GARBAGE --- [Size: %d -> %d] [Nodes: %d -> %d]\n",
                      orgHeapSize, trackHeapSize, orgNumNodes, numNodes);

        #if DIAG_GC
            Sys.log_f(1, "GC time = %d ms\n", gcTotalTime / 1000);
        #endif
            #endif
        }