Exemple #1
0
        // Loads a single table, returns pointer to table in memory.
        public static void *LoadSingleTable(tMetaData *pThis, tRVA *pRVA, int tableID, void **ppTable)
        {
            int             numRows = (int)pThis->tables.numRows[tableID];
            int             rowLen = tableRowSize[tableID];
            int             i, row;
            /*char**/ byte *pDef   = tableDefs[tableID];
            int             defLen = (int)S.strlen(pDef);
            void *          pRet;
            byte *          pSource = (byte *)*ppTable;
            byte *          pDest;
            uint            v = 0;
            SIZE_T          p = 0;

            // Allocate memory for destination table
            pRet  = Mem.malloc((SIZE_T)(numRows * rowLen));
            pDest = (byte *)pRet;

            // Load table
            int srcLen = 0;

            for (row = 0; row < numRows; row++)
            {
                byte *pSrcStart = pSource;
                for (i = 0; i < defLen; i += 2)
                {
                    byte d = pDef[i];
                    if (d < MAX_TABLES)
                    {
                        if (pThis->tables.numRows[d] < 0x10000)
                        {
                            // Use 16-bit offset
                            v        = GetU16(pSource);
                            pSource += 2;
                        }
                        else
                        {
                            // Use 32-bit offset
                            v        = GetU32(pSource);
                            pSource += 4;
                        }
                        v |= (uint)d << 24;
                    }
                    else
                    {
                        switch ((char)d)
                        {
                        case 'c':                         // 8-bit value
                            v = *(byte *)pSource;
                            pSource++;
                            break;

                        case 's':                         // 16-bit short
                            v        = GetU16(pSource);
                            pSource += 2;
                            break;

                        case 'i':                         // 32-bit int
                            v        = GetU32(pSource);
                            pSource += 4;
                            break;

                        case '0':
                        case '1':
                        case '2':
                        case '3':
                        case '4':
                        case '5':
                        case '6':
                        case '7':
                        case '8':
                        case '9':
                        case ':':
                        case ';':
                        case '<':
                        {
                            int            ofs            = pDef[i] - '0';
                            /*char*/ byte *pCoding        = codedTags[ofs];
                            int            tagBits        = codedTagBits[ofs];
                            byte           tag            = (byte)(*pSource & ((1 << tagBits) - 1));
                            int            idxIntoTableID = pCoding[tag];                          // The actual table index that we're looking for
                            if (idxIntoTableID < 0 || idxIntoTableID > MAX_TABLES)
                            {
                                Sys.Crash("Error: Bad table index: 0x%02x\n", idxIntoTableID);
                            }
                            if (pThis->tables.codedIndex32Bit[ofs] != 0)
                            {
                                // Use 32-bit number
                                v        = GetU32(pSource) >> tagBits;
                                pSource += 4;
                            }
                            else
                            {
                                // Use 16-bit number
                                v        = GetU16(pSource) >> tagBits;
                                pSource += 2;
                            }
                            v |= (uint)idxIntoTableID << 24;
                        }
                        break;

                        case 'S':                         // index into string heap
                            if (pThis->index32BitString != 0)
                            {
                                v        = GetU32(pSource);
                                pSource += 4;
                            }
                            else
                            {
                                v        = GetU16(pSource);
                                pSource += 2;
                            }
                            p = (PTR)(pThis->strings.pStart + v);
                            // NOTE: Quick way to validate metadata loading, check if all strings are valid!
                            if (S.isvalidstr((byte *)p) == 0)
                            {
                                Sys.Crash("Invalid string %s", (PTR)p);
                            }
                            break;

                        case 'G':                         // index into GUID heap
                            if (pThis->index32BitGUID != 0)
                            {
                                v        = GetU32(pSource);
                                pSource += 4;
                            }
                            else
                            {
                                v        = GetU16(pSource);
                                pSource += 2;
                            }
                            p = (PTR)(pThis->GUIDs.pGUID1 + ((v - 1) * 16));
                            break;

                        case 'B':                         // index into BLOB heap
                            if (pThis->index32BitBlob != 0)
                            {
                                v        = GetU32(pSource);
                                pSource += 4;
                            }
                            else
                            {
                                v        = GetU16(pSource);
                                pSource += 2;
                            }
                            p = (PTR)(pThis->blobs.pStart + v);
                            break;

                        case '^':                         // RVA to convert to pointer
                            v        = GetU32(pSource);
                            pSource += 4;
                            p        = (PTR)RVA.FindData(pRVA, v);
                            break;

                        case 'm':                         // Pointer to this metadata
                            p = (PTR)pThis;
                            break;

                        case 'l':                         // Is this the last table entry?
                            v = (row == numRows - 1) ? (uint)1 : (uint)0;
                            break;

                        case 'I':                         // Original table index
                            v = MetaData.MAKE_TABLE_INDEX((uint)tableID, (uint)(row + 1));
                            break;

                        case 'x':                         // Nothing, use 0
                            v = 0;
                            p = 0;
                            break;

                        default:
                            Sys.Crash("Cannot handle MetaData source definition character '%c' (0x%02X)\n", d, d);
                            break;
                        }
                    }
                    switch ((char)pDef[i + 1])
                    {
                    case '*':
                        *(SIZE_T *)pDest = p;
                        pDest           += sizeof(SIZE_T);
                        break;

                    case 'i':
                        *(uint *)pDest = v;
                        pDest         += 4;
                        break;

                    case 's':
                        *(ushort *)pDest = (ushort)v;
                        pDest           += 2;
                        break;

                    case 'c':
                        *(byte *)pDest = (byte)v;
                        pDest++;
                        break;

                    case 'x':
                        // Do nothing
                        break;

                    default:
                        Sys.Crash("Cannot handle MetaData destination definition character '%c'\n", pDef[i + 1]);
                        break;
                    }
                }
                if (srcLen == 0)
                {
                    srcLen = (int)(pSource - pSrcStart);
                }
            }

            Sys.log_f(1, "Loaded MetaData table 0x%02X; %d rows %d len\n", tableID, numRows, srcLen);

            // Update the parameter to the position after this table
            *ppTable = pSource;
            // Return new table information
            return(pRet);
        }
Exemple #2
0
        public static byte *scatprintf(byte *bfr, byte *end, string fmt, params object[] args)
        {
            if (bfr == null || fmt == null)
            {
                throw new System.NullReferenceException();
            }
            Mem.heapcheck();
            int   curarg = 0;
            int   i      = 0;
            int   fmtLen = fmt.Length;
            byte *b      = bfr;
            byte *e      = end;

            while (i < fmtLen)
            {
                char ch = fmt[i];
                if (ch == '%' && i + 1 < fmtLen)
                {
                    i++;
                    ch = fmt[i];
                    if (ch == 's')
                    {
                        object sarg = args[curarg];
                        curarg++;
                        if (sarg == null)
                        {
                            if (b + 4 > e)
                            {
                                throw new System.IndexOutOfRangeException();
                            }
                            *b++ = (byte)'n';
                            *b++ = (byte)'u';
                            *b++ = (byte)'l';
                            *b++ = (byte)'l';
                        }
                        else if (sarg is string)
                        {
                            string str = (string)sarg;
                            for (int j = 0; j < str.Length; j++)
                            {
                                if (b >= e)
                                {
                                    throw new System.IndexOutOfRangeException();
                                }
                                *b++ = (byte)str[j];
                            }
                        }
                        else if (sarg is PTR)
                        {
                            byte *s = (byte *)((PTR)sarg);
                            if (s == null)
                            {
                                if (b + 4 >= e)
                                {
                                    throw new System.IndexOutOfRangeException();
                                }
                                *b++ = (byte)'n';
                                *b++ = (byte)'u';
                                *b++ = (byte)'l';
                                *b++ = (byte)'l';
                            }
                            else
                            {
                                while (*s != 0)
                                {
                                    if (b >= e)
                                    {
                                        throw new System.IndexOutOfRangeException();
                                    }
                                    *b++ = *s++;
                                }
                            }
                        }
                        else
                        {
                            throw new System.ArgumentException();
                        }
                    }
                    else if (ch == 'x' || ch == 'X' || ch == 'd')
                    {
                        int    v;
                        object arg = args[curarg];
                        if (arg is int)
                        {
                            v = (int)arg;
                        }
                        else if (arg is uint)
                        {
                            v = (int)(uint)arg;
                        }
                        else if (arg is long)
                        {
                            v = (int)(long)arg;
                        }
                        else if (arg is ulong)
                        {
                            v = (int)(ulong)arg;
                        }
                        else
                        {
                            throw new System.ArgumentException();
                        }
                        curarg++;
                        string vs = (ch == 'x' || ch == 'X' ? v.ToString("X") : v.ToString());
                        for (int j = 0; j < vs.Length; j++)
                        {
                            if (b >= e)
                            {
                                throw new System.IndexOutOfRangeException();
                            }
                            *b++ = (byte)vs[j];
                        }
                    }
                    else if (ch == 'l' && i + 2 < fmtLen && fmt[i + 1] == 'l' && (fmt[i + 2] == 'x' || fmt[i + 2] == 'X' || fmt[i + 2] == 'd'))
                    {
                        i += 2;
                        ch = fmt[i];
                        long lv = System.Convert.ToInt64(args[curarg]);
                        curarg++;
                        string lvs = (ch == 'x' || ch == 'X' ? lv.ToString("X") : lv.ToString());
                        for (int j = 0; j < lvs.Length; j++)
                        {
                            if (b >= e)
                            {
                                throw new System.IndexOutOfRangeException();
                            }
                            *b++ = (byte)lvs[j];
                        }
                    }
                    else if (ch == '0' && i + 2 < fmtLen && (fmt[i + 1] >= '0' && fmt[i + 1] <= '9') && (fmt[i + 2] == 'x' || fmt[i + 2] == 'X' || fmt[i + 2] == 'd'))
                    {
                        char l0 = fmt[i + 1];
                        i += 2;
                        ch = fmt[i];
                        int    v0;
                        object arg = args[curarg];
                        if (arg is int)
                        {
                            v0 = (int)arg;
                        }
                        else if (arg is uint)
                        {
                            v0 = (int)(uint)arg;
                        }
                        else if (arg is long)
                        {
                            v0 = (int)(long)arg;
                        }
                        else if (arg is ulong)
                        {
                            v0 = (int)(ulong)arg;
                        }
                        else
                        {
                            throw new System.ArgumentException();
                        }
                        curarg++;
                        string vs0 = (ch == 'x' || ch == 'X' ? v0.ToString("X" + l0) : v0.ToString("D" + l0));
                        for (int j = 0; j < vs0.Length; j++)
                        {
                            if (b >= e)
                            {
                                throw new System.IndexOutOfRangeException();
                            }
                            *b++ = (byte)vs0[j];
                        }
                    }
                    else
                    {
                        if (b >= e)
                        {
                            throw new System.IndexOutOfRangeException();
                        }
                        *b++ = (byte)ch;
                    }
                }
                else
                {
                    if (b >= e)
                    {
                        throw new System.IndexOutOfRangeException();
                    }
                    *b++ = (byte)ch;
                }
                i++;
            }

            // Null terminator
            *b = 0;

            Mem.heapcheck();

            return(b);
        }
Exemple #3
0
        static int InternalLoadAndRun(bool tryRun, string[] args)
        {
            if (!_isInitialized)
            {
                Init();
            }

            /*char**/ byte * pFileName = new S(args[0]);
            int              argc      = args.Length;
            /*char**/ byte **argv      = S.buildArray(args);
            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, argc, argv);
                }
                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);
        }
Exemple #4
0
        public static uint Update(uint maxInstr, int *pReturnCode)
        {
            tThread *pThread;
            tThread *pPrevThread;
            uint     status;

            pThread = pAllThreads;
            // Set the initial thread to the RUNNING state.
            pThread->state = THREADSTATE_RUNNING;
            // Set the initial CurrentThread
            pCurrentThread = pThread;

            for (;;)
            {
                uint minSleepTime = 0xffffffff;
                int  threadExitValue;

                status = JIT_Execute.Execute(pThread, maxInstr);
                switch (status)
                {
                case Thread.THREAD_STATUS_EXIT:
                    threadExitValue = pThread->threadExitValue;
                    Sys.log_f(1, "Thread ID#%d exited. Return value: %d\n", (int)pThread->threadID, (int)threadExitValue);
                    // Remove the current thread from the running threads list.
                    // Note that this list may have changed since before the call to JitOps.JIT_Execute().
                    {
                        if (pAllThreads == pThread)
                        {
                            pAllThreads = pAllThreads->pNextThread;
                        }
                        else
                        {
                            tThread *pThread1 = pAllThreads;
                            while (pThread1->pNextThread != pThread)
                            {
                                pThread1 = pThread1->pNextThread;
                            }
                            pThread1->pNextThread = pThread1->pNextThread->pNextThread;
                        }
                    }
                    // Delete the current thread
                    Thread.Delete(pThread);
                    // If there are no more threads left running, then exit application (by returning)
                    // Threads that are unstarted or background do not stop the exit
                    // [Steve edit] Threads that are suspended also do not stop the exit. This is because you'd just
                    // wait forever for them if they did. Note that 'exit' doesn't mean tearing down the process
                    // like in a regular .NET runtime case. The application state is still there and we can make
                    // further calls into it to create new threads.
                    {
                        tThread *pThread2 = pAllThreads;
                        uint     canExit  = 1;
                        while (pThread2 != null)
                        {
                            if (
                                ((pThread2->state & THREADSTATE_BACKGROUND) == 0) &&
                                ((pThread2->state & (~THREADSTATE_BACKGROUND)) != THREADSTATE_UNSTARTED) &&
                                ((pThread2->state & (~THREADSTATE_BACKGROUND)) != THREADSTATE_SUSPENDED))
                            {
                                canExit = 0;
                                break;
                            }
                            pThread2 = pThread2->pNextThread;
                        }
                        if (canExit != 0)
                        {
                            if (pReturnCode != null)
                            {
                                *pReturnCode = threadExitValue;
                            }
                            return(THREADSTATE_STOPPED);
                        }
                    }
                    pThread = pAllThreads;     // This is not really correct, but it'll work for the time being
                    break;

                case THREAD_STATUS_RUNNING:
                case THREAD_STATUS_LOCK_EXIT:
                    // Nothing to do
                    break;

                case THREAD_STATUS_ASYNC:
                    pThread->pAsync->startTime = Sys.msTime();
                    break;
                }

                // Move on to the next thread.
                // Find the next thread that isn't sleeping or blocked on IO
                pPrevThread = pThread;
                for (;;)
                {
                    pThread = pThread->pNextThread;
                    if (pThread == null)
                    {
                        // That was the thread -- return!
                        return(THREADSTATE_RUNNING);
                    }
                    // Set the CurrentThread correctly
                    pCurrentThread = pThread;
                    if ((pThread->state & (~THREADSTATE_BACKGROUND)) != 0)
                    {
                        // Thread is not running
                        continue;
                    }
                    if (pThread->pAsync != null)
                    {
                        // Discover if whatever is being waited for is finished
                        tAsyncCall *pAsync = pThread->pAsync;
                        if (pAsync->sleepTime >= 0)
                        {
                            // This is a sleep
                            ulong nowTime          = Sys.msTime();
                            int   msSleepRemaining = pAsync->sleepTime - (int)(nowTime - pAsync->startTime);
                            if (msSleepRemaining <= 0)
                            {
                                // Sleep is finished
                                break;
                            }
                            // Sleep is not finished, so continue to next thread
                            if ((uint)msSleepRemaining < minSleepTime)
                            {
                                minSleepTime = (uint)msSleepRemaining;
                            }
                        }
                        else
                        {
                            // This is blocking IO, or a lock
                            tMethodState *pMethodState = pThread->pCurrentMethodState;
                            byte *        pThis;
                            uint          thisOfs;
                            uint          unblocked;

                            if (MetaData.METHOD_ISSTATIC(pMethodState->pMethod))
                            {
                                pThis   = null;
                                thisOfs = 0;
                            }
                            else
                            {
                                pThis   = *(byte **)pMethodState->pParamsLocals;
                                thisOfs = 4;
                            }
                            unblocked = ((fnInternalCallCheck)H.ToObj(pAsync->checkFn))(null, pThis, pMethodState->pParamsLocals + thisOfs, pMethodState->pEvalStack, pAsync);
                            if (unblocked != 0)
                            {
                                // The IO has unblocked, and the return value is ready.
                                // So delete the async object.
                                // TODO: The async->state object needs to be deleted somehow (maybe)
                                Mem.free(pAsync);
                                // And remove it from the thread
                                pThread->pAsync = null;
                                break;
                            }
                            minSleepTime = 5;
                        }
                    }
                    else
                    {
                        // Thread is ready to run
                        break;
                    }
                    if (pThread == pPrevThread)
                    {
                        // When it gets here, it means that all threads are currently blocked.
                        //printf("All blocked; sleep(%d)\n", minSleepTime);
                        Sys.SleepMS(minSleepTime);
                    }
                }
            }
        }
Exemple #5
0
        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);
        }
Exemple #6
0
        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);
        }
Exemple #7
0
        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);
        }
Exemple #8
0
 public static void Init()
 {
     methodNameBuf = (byte *)Mem.malloc((SIZE_T)METHOD_NAME_BUF_SIZE);
 }
Exemple #9
0
 public static void SetParameters(tMethodState *pMethodState, tMD_MethodDef *pCallMethod, byte *pParams)
 {
     Mem.memcpy(pMethodState->pParamsLocals, pParams, pCallMethod->parameterStackSize);
 }
Exemple #10
0
        public static void Fill_MethodDef(tMD_TypeDef *pParentType, tMD_MethodDef *pMethodDef,
                                          tMD_TypeDef **ppClassTypeArgs, tMD_TypeDef **ppMethodTypeArgs)
        {
            /*SIG*/ byte *sig;
            uint          i, entry, totalSize, start;

            if (pMethodDef->isFilled == 1)
            {
                return;
            }

            // Note: parent type can be null for module level methods (not typical in C# assemblies)
            pMethodDef->pParentType = pParentType;
            pMethodDef->pMethodDef  = pMethodDef;
            pMethodDef->isFilled    = 1;

            if (pMethodDef->isGenericDefinition != 0)
            {
                // Generic definition method, so can't do any more.
                //Sys.log_f("Method<>: %s.%s.%s()\n", pParentType->nameSpace, pParentType->name, pMethodDef->name);
                return;
            }

            sig   = MetaData.GetBlob(pMethodDef->signature, null);
            entry = MetaData.DecodeSigEntry(&sig);
            if ((entry & SIG_METHODDEF_GENERIC) != 0)
            {
                // Has generic parameters. Read how many, but don't care about the answer
                MetaData.DecodeSigEntry(&sig);
            }
            pMethodDef->numberOfParameters = (ushort)(MetaData.DecodeSigEntry(&sig) + (MetaData.METHOD_ISSTATIC(pMethodDef)?0:1));
            pMethodDef->pReturnType        = Type.GetTypeFromSig(pMethodDef->pMetaData, &sig, ppClassTypeArgs, ppMethodTypeArgs, null);
            if (pMethodDef->pReturnType != null && pMethodDef->pReturnType->fillState < Type.TYPE_FILL_ALL)
            {
                Fill_Defer(pMethodDef->pReturnType, ppClassTypeArgs, ppMethodTypeArgs);
            }
            pMethodDef->pParams = (tParameter *)Mem.malloc((SIZE_T)(pMethodDef->numberOfParameters * sizeof(tParameter)));
            totalSize           = 0;
            start = 0;
            if (!MetaData.METHOD_ISSTATIC(pMethodDef))
            {
                // Fill in parameter info for the 'this' pointer
                pMethodDef->pParams->offset = 0;
                if (pParentType->isValueType != 0)
                {
                    // If this is a value-type then the 'this' pointer is actually an IntPtr to the value-type's location
                    pMethodDef->pParams->size          = sizeof(PTR);
                    pMethodDef->pParams->pStackTypeDef = Type.types[Type.TYPE_SYSTEM_INTPTR];
                }
                else
                {
                    pMethodDef->pParams->size          = sizeof(PTR);
                    pMethodDef->pParams->pStackTypeDef = pParentType;
                }
                totalSize = sizeof(PTR);
                start     = 1;
            }
            for (i = start; i < pMethodDef->numberOfParameters; i++)
            {
                tMD_TypeDef *pStackTypeDef;
                tMD_TypeDef *pByRefTypeDef;
                uint         size;

                pByRefTypeDef = null;
                pStackTypeDef = Type.GetTypeFromSig(pMethodDef->pMetaData, &sig, ppClassTypeArgs, ppMethodTypeArgs, &pByRefTypeDef);
                if (pStackTypeDef != null)
                {
                    if (pStackTypeDef->fillState < Type.TYPE_FILL_LAYOUT)
                    {
                        MetaData.Fill_TypeDef(pStackTypeDef, null, null, Type.TYPE_FILL_LAYOUT);
                    }
                    else if (pStackTypeDef->fillState < Type.TYPE_FILL_ALL)
                    {
                        MetaData.Fill_Defer(pStackTypeDef, null, null);
                    }
                    size = pStackTypeDef->stackSize;
                }
                else
                {
                    size = 0;
                }
                if (pByRefTypeDef != null)
                {
                    if (pByRefTypeDef->fillState < Type.TYPE_FILL_LAYOUT)
                    {
                        MetaData.Fill_TypeDef(pByRefTypeDef, null, null, Type.TYPE_FILL_LAYOUT);
                    }
                    else if (pByRefTypeDef->fillState < Type.TYPE_FILL_ALL)
                    {
                        MetaData.Fill_Defer(pByRefTypeDef, null, null);
                    }
                }
                pMethodDef->pParams[i].pStackTypeDef = pStackTypeDef;
                pMethodDef->pParams[i].pByRefTypeDef = pByRefTypeDef;
                pMethodDef->pParams[i].offset        = totalSize;
                pMethodDef->pParams[i].size          = size;
                totalSize += size;
            }
            pMethodDef->parameterStackSize = totalSize;
        }
Exemple #11
0
        static tMD_MethodDef *FindMethodInType(tMD_TypeDef *pTypeDef, /*STRING*/ byte *name, tMetaData *pSigMetaData,
                                               /*BLOB_*/ byte *sigBlob, tMD_TypeDef **ppClassTypeArgs, tMD_TypeDef **ppMethodTypeArgs)
        {
            uint         i;
            tMD_TypeDef *pLookInType = pTypeDef;

            if (pLookInType->fillState < Type.TYPE_FILL_MEMBERS)
            {
                MetaData.Fill_TypeDef(pTypeDef, ppClassTypeArgs, ppMethodTypeArgs, Type.TYPE_FILL_MEMBERS);
            }

            do
            {
                for (i = 0; i < pLookInType->numMethods; i++)
                {
                    if (MetaData.CompareNameAndSig(name, sigBlob, pSigMetaData, ppClassTypeArgs, ppMethodTypeArgs,
                                                   pLookInType->ppMethods[i], pLookInType->ppClassTypeArgs, null) != 0)
                    {
                        return(pLookInType->ppMethods[i]);
                    }
                }
                pLookInType = pLookInType->pParent;
            } while (pLookInType != null);

            {
                // Error reporting!!
                uint            entry, numParams, j;
                /*SIG*/ byte *  sig;
                /*char**/ byte *pMsg, pMsgPos, pMsgEnd;
                tMD_TypeDef *   pParamTypeDef;

                pMsgPos = pMsg = (byte *)Mem.malloc(MSG_BUF_SIZE);
                pMsgEnd = pMsg + MSG_BUF_SIZE;
                *pMsg = 0;
                sig   = MetaData.GetBlob(sigBlob, &j);
                entry = MetaData.DecodeSigEntry(&sig);
                if ((entry & SIG_METHODDEF_HASTHIS) == 0)
                {
                    pMsgPos = S.scatprintf(pMsgPos, pMsgEnd, "static ");
                }
                if ((entry & SIG_METHODDEF_GENERIC) != 0)
                {
                    // read number of generic type args - don't care what it is
                    MetaData.DecodeSigEntry(&sig);
                }
                numParams     = MetaData.DecodeSigEntry(&sig);
                pParamTypeDef = Type.GetTypeFromSig(pSigMetaData, &sig, ppClassTypeArgs, ppMethodTypeArgs, null);         // return type
                if (pParamTypeDef != null)
                {
                    pMsgPos = S.scatprintf(pMsgPos, pMsgEnd, "%s ", (PTR)pParamTypeDef->name);
                }
                pMsgPos = S.scatprintf(pMsgPos, pMsgEnd, "%s.%s.%s(", (PTR)pTypeDef->nameSpace, (PTR)pTypeDef->name, (PTR)name);
                for (j = 0; j < numParams; j++)
                {
                    pParamTypeDef = Type.GetTypeFromSig(pSigMetaData, &sig, ppClassTypeArgs, ppMethodTypeArgs, null);
                    if (j > 0)
                    {
                        pMsgPos = S.scatprintf(pMsgPos, pMsgEnd, ",");
                    }
                    if (pParamTypeDef != null)
                    {
                        pMsgPos = S.scatprintf(pMsgPos, pMsgEnd, "%s", (PTR)pParamTypeDef->name);
                    }
                    else
                    {
                        pMsgPos = S.scatprintf(pMsgPos, pMsgEnd, "???");
                    }
                }
                Sys.Crash("FindMethodInType(): Cannot find method %s)", (PTR)pMsg);
            }
            return(null);
        }
Exemple #12
0
        // 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);
        }
Exemple #13
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->monoGCHandle == 1)
                {
                    void *hptr = *(void **)((byte *)pThis + sizeof(tHeapEntry));
                    if (hptr != null)
                    {
                        GCHandle h = System.Runtime.InteropServices.GCHandle.FromIntPtr((System.IntPtr)hptr);
                        h.Free();
                    }
                }
                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
        }
Exemple #14
0
        public static tAsyncCall *InternalReplace(tJITCallNative *pCallNative, byte *pThis_, byte *pParams, byte *pReturnValue)
        {
            tSystemString *pThis = (tSystemString *)pThis_;
            tSystemString *pOld  = (*((tSystemString **)(pParams + 0)));
            tSystemString *pNew  = (*((tSystemString **)(pParams + Sys.S_PTR)));
            tSystemString *pResult;
            uint           thisLen, oldLen, newLen;
            char *         pThisChar0, pOldChar0, pNewChar0, pResultChar0;
            uint           i, j, replacements, dstIndex;
            uint           resultLen;

            // This function (correctly) assumes that the old string is not empty
            thisLen    = pThis->length;
            oldLen     = pOld->length;
            newLen     = pNew->length;
            pThisChar0 = tSystemString.GetChars(pThis);
            pOldChar0  = tSystemString.GetChars(pOld);
            pNewChar0  = tSystemString.GetChars(pNew);

            replacements = 0;
            for (i = 0; i < thisLen - oldLen + 1; i++)
            {
                uint match = 1;
                for (j = 0; j < oldLen; j++)
                {
                    if (pThisChar0[i + j] != pOldChar0[j])
                    {
                        match = 0;
                        break;
                    }
                }
                if (match != 0)
                {
                    i += oldLen - 1;
                    replacements++;
                }
            }
            resultLen    = thisLen - (oldLen - newLen) * replacements;
            pResult      = CreateStringHeapObj(resultLen);
            pResultChar0 = tSystemString.GetChars(pResult);
            dstIndex     = 0;
            for (i = 0; i < thisLen; i++)
            {
                uint match = 1;
                if (i < thisLen - oldLen + 1)
                {
                    for (j = 0; j < oldLen; j++)
                    {
                        match = 1;
                        if (pThisChar0[i + j] != pOldChar0[j])
                        {
                            match = 0;
                            break;
                        }
                    }
                }
                else
                {
                    match = 0;
                }
                if (match != 0)
                {
                    Mem.memcpy(&pResultChar0[dstIndex], pNewChar0, newLen << 1);
                    dstIndex += newLen;
                    i        += oldLen - 1;
                }
                else
                {
                    pResultChar0[dstIndex++] = pThisChar0[i];
                }
            }
            Sys.INTERNALCALL_RESULT_PTR(pReturnValue, pResult);

            return(null);
        }
Exemple #15
0
        public static tAsyncCall *InternalTrim(tJITCallNative *pCallNative, byte *pThis_, byte *pParams, byte *pReturnValue)
        {
            tSystemString *    pThis = (tSystemString *)pThis_;
            /*HEAP_PTR*/ byte *pWhiteChars;
            uint           trimType, i, j, checkCharsLen;
            uint           ofsStart, ofsEnd;
            ushort *       pCheckChars;
            uint           isWhiteSpace;
            tSystemString *pRet;
            ushort         c;
            char *         pChars, pRetChars;

            pWhiteChars   = (*((/*HEAP_PTR*/ byte **)(pParams + 0)));
            trimType      = (*((uint *)(pParams + Sys.S_PTR)));
            pCheckChars   = (ushort *)System_Array.GetElements(pWhiteChars);
            checkCharsLen = System_Array.GetLength(pWhiteChars);

            ofsStart = 0;
            ofsEnd   = pThis->length;
            pChars   = tSystemString.GetChars(pThis);
            if ((trimType & 1) != 0)
            {
                // Trim start
                for (i = ofsStart; i < ofsEnd; i++)
                {
                    // Check if each char is in the array
                    isWhiteSpace = 0;
                    c            = pChars[i];
                    for (j = 0; j < checkCharsLen; j++)
                    {
                        if (c == pCheckChars[j])
                        {
                            isWhiteSpace = 1;
                            break;
                        }
                    }
                    if (isWhiteSpace == 0)
                    {
                        ofsStart = i;
                        break;
                    }
                }
            }
            if ((trimType & 2) != 0)
            {
                // Trim end
                for (i = ofsEnd - 1; i >= ofsStart; i--)
                {
                    // Check if each char is in the array
                    isWhiteSpace = 0;
                    c            = pChars[i];
                    for (j = 0; j < checkCharsLen; j++)
                    {
                        if (c == pCheckChars[j])
                        {
                            isWhiteSpace = 1;
                            break;
                        }
                    }
                    if (isWhiteSpace == 0)
                    {
                        ofsEnd = i + 1;
                        break;
                    }
                }
            }

            pRet      = CreateStringHeapObj(ofsEnd - ofsStart);
            pRetChars = tSystemString.GetChars(pRet);
            Mem.memcpy(pRetChars, &pChars[ofsStart], (SIZE_T)((ofsEnd - ofsStart) << 1));
            Sys.INTERNALCALL_RESULT_PTR(pReturnValue, pRet);

            return(null);
        }