Ejemplo n.º 1
0
        public static void FreeAllGCHandles()
        {
            tHeapEntry * pNode;
            tHeapEntry **pUp = stackalloc tHeapEntry *[MAX_TREE_DEPTH * 2];
            int          top;

            // Traverse nodes
            pUp[0] = pHeapTreeRoot;
            top    = 1;
            while (top != 0)
            {
                // Get this node
                pNode = pUp[--top];
                if (pNode->monoGCHandle != 0)
                {
                    void *hptr = *(void **)((byte *)pNode + sizeof(tHeapEntry));
                    if (hptr != null)
                    {
                        GCHandle h = System.Runtime.InteropServices.GCHandle.FromIntPtr((System.IntPtr)hptr);
                        h.Free();
                    }
                }
                // 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];
                }
            }
        }
Ejemplo n.º 2
0
 static tHeapEntry *TreeInsert(tHeapEntry *pRoot, tHeapEntry *pEntry)
 {
     if (pRoot == nil)
     {
         pRoot           = pEntry;
         pRoot->level    = 1;
         pRoot->pLink[0] = pRoot->pLink[1] = (PTR)nil;
         pRoot->marked   = 0;
     }
     else
     {
         tHeapEntry * pNode = pHeapTreeRoot;
         tHeapEntry **pUp = stackalloc tHeapEntry *[MAX_TREE_DEPTH];
         int          top = 0, dir;
         // Find leaf position to insert into tree. This first step is unbalanced
         for (;;)
         {
             pUp[top++] = pNode;
             dir        = ((PTR)pNode < (PTR)pEntry) ? 1 : 0; // 0 for left, 1 for right
             if (pNode->pLink[dir] == (PTR)nil)
             {
                 break;
             }
             pNode = (tHeapEntry *)pNode->pLink[dir];
         }
         // Create new node
         pNode->pLink[dir] = (PTR)pEntry;
         pEntry->level     = 1;
         pEntry->pLink[0]  = pEntry->pLink[1] = (PTR)nil;
         pEntry->marked    = 0;
         // Balance the tree
         while (--top >= 0)
         {
             if (top != 0)
             {
                 dir = (pUp[top - 1]->pLink[1] == (PTR)pUp[top]) ? 1 : 0;
             }
             pUp[top] = TreeSkew(pUp[top]);
             pUp[top] = TreeSplit(pUp[top]);
             if (top != 0)
             {
                 pUp[top - 1]->pLink[dir] = (PTR)pUp[top];
             }
             else
             {
                 pRoot = pUp[0];
             }
         }
     }
     return(pRoot);
 }
Ejemplo n.º 3
0
        public static void GarbageCollect()
        {
#if NO
            tHeapRoots   heapRoots;
            tHeapEntry * pNode;
            tHeapEntry **pUp = stackalloc tHeapEntry *[MAX_TREE_DEPTH * 2];
            int          top;
            tHeapEntry * pToDelete   = null;
            SIZE_T       orgHeapSize = trackHeapSize;
            uint         orgNumNodes = numNodes;
            #if DIAG_GC
            ulong startTime;
            #endif

            Mem.heapcheck();

            numCollections++;

        #if DIAG_GC
            startTime = microTime();
        #endif

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

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

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

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

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

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

            Mem.free(heapRoots.pHeapEntries);

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

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

            Mem.heapcheck();

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

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

        #if DIAG_GC
            Sys.log_f(1, "GC time = %d ms\n", gcTotalTime / 1000);
        #endif
            #endif
        }
Ejemplo n.º 4
0
        static tHeapEntry *TreeRemove(tHeapEntry *pRoot, tHeapEntry *pDelete)
        {
            if (pRoot != nil)
            {
                if (pRoot == pDelete)
                {
                    if (pRoot->pLink[0] != (PTR)nil && pRoot->pLink[1] != (PTR)nil)
                    {
                        tHeapEntry * pL0;
                        byte         l;
                        tHeapEntry * pHeir      = (tHeapEntry *)pRoot->pLink[0];
                        tHeapEntry **ppHeirLink = (tHeapEntry **)&pHeir->pLink[0];
                        while (pHeir->pLink[1] != (PTR)nil)
                        {
                            ppHeirLink = (tHeapEntry **)&pHeir->pLink[1];
                            pHeir      = (tHeapEntry *)pHeir->pLink[1];
                        }
                        // Swap the two nodes
                        pL0 = (tHeapEntry *)pHeir->pLink[0];
                        l   = pHeir->level;
                        // Bring heir to replace root
                        pHeir->pLink[0] = pRoot->pLink[0];
                        pHeir->pLink[1] = pRoot->pLink[1];
                        pHeir->level    = pRoot->level;
                        // Send root to replace heir
                        *ppHeirLink = pRoot;
                        pRoot->pLink[0] = (PTR)pL0;
                        pRoot->pLink[1] = (PTR)nil;
                        pRoot->level    = l;
                        // Set correct return value
                        pL0   = pRoot;
                        pRoot = pHeir;
                        // Delete the node that's been sent down
                        pRoot->pLink[0] = (PTR)TreeRemove((tHeapEntry *)pRoot->pLink[0], pL0);
                    }
                    else
                    {
                        pRoot = (tHeapEntry *)pRoot->pLink[pRoot->pLink[0] == (PTR)nil ? 1 : 0];
                    }
                }
                else
                {
                    int dir = (PTR)pRoot < (PTR)pDelete ? 1 : 0;
                    pRoot->pLink[dir] = (PTR)TreeRemove((tHeapEntry *)pRoot->pLink[dir], pDelete);
                }
            }

            if (((tHeapEntry *)pRoot->pLink[0])->level < pRoot->level - 1 || ((tHeapEntry *)pRoot->pLink[1])->level < pRoot->level - 1)
            {
                if (((tHeapEntry *)pRoot->pLink[1])->level > --pRoot->level)
                {
                    ((tHeapEntry *)pRoot->pLink[1])->level = pRoot->level;
                }
                pRoot           = TreeSkew(pRoot);
                pRoot->pLink[1] = (PTR)TreeSkew((tHeapEntry *)pRoot->pLink[1]);
                ((tHeapEntry *)pRoot->pLink[1])->pLink[1] = (PTR)TreeSkew((tHeapEntry *)((tHeapEntry *)pRoot->pLink[1])->pLink[1]);
                pRoot           = TreeSplit(pRoot);
                pRoot->pLink[1] = (PTR)TreeSplit((tHeapEntry *)pRoot->pLink[1]);
            }

            return(pRoot);
        }