Пример #1
0
 public static void Clear()
 {
     pHeapTreeRoot  = nil = null;
     trackHeapSize  = 0;
     heapSizeMax    = 0;
     numNodes       = 0;
     numCollections = 0;
 }
Пример #2
0
 static tSync *EnsureSync(tHeapEntry *pHeapEntry)
 {
     if (pHeapEntry->pSync == null)
     {
         tSync *pSync = ((tSync *)Mem.malloc((SIZE_T)sizeof(tSync)));
         Mem.memset(pSync, 0, (SIZE_T)sizeof(tSync));
         pHeapEntry->pSync = pSync;
     }
     return(pHeapEntry->pSync);
 }
Пример #3
0
 static void DeleteSync(tHeapEntry *pHeapEntry)
 {
     if (pHeapEntry->pSync != null)
     {
         if (pHeapEntry->pSync->count == 0 && pHeapEntry->pSync->weakRef == null)
         {
             Mem.free(pHeapEntry->pSync);
             pHeapEntry->pSync = null;
         }
     }
 }
Пример #4
0
 static tHeapEntry *TreeSkew(tHeapEntry *pRoot)
 {
     if (((tHeapEntry *)pRoot->pLink[0])->level == pRoot->level && pRoot->level != 0)
     {
         tHeapEntry *pSave = (tHeapEntry *)pRoot->pLink[0];
         pRoot->pLink[0] = pSave->pLink[1];
         pSave->pLink[1] = (PTR)pRoot;
         pRoot           = pSave;
     }
     return(pRoot);
 }
Пример #5
0
        // Returns the previous first weak-ref in target targetted by weakref
        public static /*HEAP_PTR*/ byte *SetWeakRefTarget(/*HEAP_PTR*/ byte *target, /*HEAP_PTR*/ byte *weakRef)
        {
            tHeapEntry *       pTarget = GET_HEAPENTRY(target);
            tSync *            pSync;
            /*HEAP_PTR*/ byte *prevWeakRef;

            pSync          = EnsureSync(pTarget);
            prevWeakRef    = pSync->weakRef;
            pSync->weakRef = weakRef;
            return(prevWeakRef);
        }
Пример #6
0
        // Get the size of a heap entry, NOT including the header
        // This works by returning the size of the type, unless the type is an array or a string,
        // which are the only two type that can have variable sizes
        static uint GetSize(tHeapEntry *pHeapEntry)
        {
            tMD_TypeDef *pType = pHeapEntry->pTypeDef;

            if (MetaData.TYPE_ISARRAY(pType))
            {
                // If it's an array, return the array length * array element size
                return(System_Array.GetNumBytes(null /* This is ok */, (/*HEAP_PTR*/ byte *)(pHeapEntry + 1), pType->pArrayElementType));
            }
            // If it's not array, just return the instance memory size
            return(pType->instanceMemSize);
        }
Пример #7
0
 public static void Init()
 {
     // Initialise vars
     trackHeapSize = 0;
     heapSizeMax   = MIN_HEAP_SIZE;
     // Create nil node - for leaf termination
     nil = ((tHeapEntry *)Mem.mallocForever((SIZE_T)sizeof(tHeapEntry)));
     Mem.memset(nil, 0, (SIZE_T)sizeof(tHeapEntry));
     nil->pLink[0] = nil->pLink[1] = (PTR)nil;
     // Set the heap tree as empty
     pHeapTreeRoot = nil;
 }
Пример #8
0
        public static /*HEAP_PTR*/ byte *AllocType(tMD_TypeDef *pTypeDef)
        {
            //printf("Heap.AllocType('%s')\n", pTypeDef->name);
            byte *pInst = Alloc(pTypeDef, pTypeDef->instanceMemSize);

            if (pTypeDef->hasMonoBase != 0)
            {
                tHeapEntry *pHeapEntry = (tHeapEntry *)((byte *)pInst - sizeof(tHeapEntry));
                pHeapEntry->monoHandle = 1;
            }

            return(pInst);
        }
Пример #9
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);
 }
Пример #10
0
        public static /*HEAP_PTR*/ byte *Clone(/*HEAP_PTR*/ byte *obj)
        {
            tHeapEntry *       pObj = GET_HEAPENTRY(obj);
            /*HEAP_PTR*/ byte *clone;
            uint  size = GetSize(pObj);
            byte *pMem;

            clone = Alloc(pObj->pTypeDef, size);

            pMem = (byte *)&pObj->pSync + sizeof(PTR);
            Mem.memcpy((void *)clone, pMem, size);

            return(clone);
        }
Пример #11
0
        public static void Clear()
        {
            // This frees all references in the DNA heap to all mono objects
            if (pHeapTreeRoot != null)
            {
                FreeAllGCHandles();
            }

            pHeapTreeRoot  = nil = null;
            trackHeapSize  = 0;
            heapSizeMax    = 0;
            numNodes       = 0;
            numCollections = 0;
        }
Пример #12
0
        // Get the size of a heap entry, NOT including the header
        // This works by returning the size of the type, unless the type is an array or a string,
        // which are the only two type that can have variable sizes
        static uint GetSize(tHeapEntry *pHeapEntry)
        {
            tMD_TypeDef *pType = pHeapEntry->pTypeDef;

            if (pType == Type.types[Type.TYPE_SYSTEM_STRING])
            {
                // If it's a string, return the string length in bytes
                return(System_String.GetNumBytes((/*HEAP_PTR*/ byte *)(pHeapEntry + 1)));
            }
            if (MetaData.TYPE_ISARRAY(pType))
            {
                // If it's an array, return the array length * array element size
                return(System_Array.GetNumBytes(null /* This is ok */, (/*HEAP_PTR*/ byte *)(pHeapEntry + 1), pType->pArrayElementType));
            }
            // If it's not string or array, just return the instance memory size
            return(pType->instanceMemSize);
        }
Пример #13
0
 public static tMD_TypeDef *GetType(/*HEAP_PTR*/ byte *heapObj)
 {
     #if DEBUG_HEAP
     if (heapObj == null)
     {
         Sys.Crash("Null reference to heap obj");
     }
     #endif
     tHeapEntry *pHeapEntry = GET_HEAPENTRY(heapObj);
     #if DEBUG_HEAP
     if (pHeapEntry->signature != VALID_HEAP_OBJ_SIG)
     {
         Sys.Crash("Invalid heap object in GetMonoObject()");
     }
     #endif
     return(pHeapEntry->pTypeDef);
 }
Пример #14
0
        public static /*HEAP_PTR*/ byte *Alloc(tMD_TypeDef *pTypeDef, uint size)
        {
            tHeapEntry *pHeapEntry;
            uint        totalSize;
            byte *      pMem;

            if (pTypeDef == null)
            {
                Sys.Crash("Invalid heap type!");
            }

            totalSize = (uint)sizeof(tHeapEntry) + size;

            // Trigger garbage collection if required.
            if (trackHeapSize >= heapSizeMax)
            {
                GarbageCollect();
                heapSizeMax = (trackHeapSize + totalSize) << 1;
                if (heapSizeMax < trackHeapSize + totalSize + MIN_HEAP_SIZE)
                {
                    // Make sure there is always MIN_HEAP_SIZE available to allocate on the heap
                    heapSizeMax = trackHeapSize + totalSize + MIN_HEAP_SIZE;
                }
                if (heapSizeMax > trackHeapSize + totalSize + MAX_HEAP_EXCESS)
                {
                    // Make sure there is never more that MAX_HEAP_EXCESS space on the heap
                    heapSizeMax = trackHeapSize + totalSize + MAX_HEAP_EXCESS;
                }
            }

            pHeapEntry                 = (tHeapEntry *)Mem.malloc(totalSize);
            pHeapEntry->pTypeDef       = pTypeDef;
            pHeapEntry->signature      = VALID_HEAP_OBJ_SIG;
            pHeapEntry->pSync          = null;
            pHeapEntry->needToFinalize = (byte)((pTypeDef->pFinalizer != null) ? 1 : 0);
            pMem = (byte *)pHeapEntry + sizeof(tHeapEntry);
            Mem.memset(pMem, 0, size);
            trackHeapSize += totalSize;

            pHeapTreeRoot = TreeInsert(pHeapTreeRoot, pHeapEntry);
            numNodes++;

            return(pMem);
        }
Пример #15
0
        // Returns 1 if all is OK
        // Returns 0 if the wrong thread is releasing the sync, or if no thread hold the sync
        public static uint SyncExit(/*HEAP_PTR*/ byte *obj)
        {
            tHeapEntry *pHeapEntry = GET_HEAPENTRY(obj);
            tThread *   pThread    = Thread.GetCurrent();

            if (pHeapEntry->pSync == null)
            {
                return(0);
            }
            if (pHeapEntry->pSync->pThread != pThread)
            {
                return(0);
            }
            if (--pHeapEntry->pSync->count == 0)
            {
                DeleteSync(pHeapEntry);
            }
            return(1);
        }
Пример #16
0
        // Return 1 if lock succesfully got
        // Return 0 if couldn't get the lock this time
        public static uint SyncTryEnter(/*HEAP_PTR*/ byte *obj)
        {
            tHeapEntry *pHeapEntry = GET_HEAPENTRY(obj);
            tThread *   pThread    = Thread.GetCurrent();
            tSync *     pSync;

            pSync = EnsureSync(pHeapEntry);
            if (pSync->pThread == null)
            {
                pSync->pThread = pThread;
                pSync->count   = 1;
                return(1);
            }
            if (pSync->pThread == pThread)
            {
                pSync->count++;
                return(1);
            }
            return(0);
        }
Пример #17
0
        public static object GetMonoObject(/*HEAP_PTR*/ byte *heapObj)
        {
            tHeapEntry *pHeapEntry = GET_HEAPENTRY(heapObj);

            #if DEBUG_HEAP
            if (pHeapEntry->signature != VALID_HEAP_OBJ_SIG)
            {
                Sys.Crash("Invalid heap object in GetMonoObject()");
            }
            #endif
            if (pHeapEntry->monoHandle != 0)
            {
                void *p = *(void **)heapObj;
                if (p == null)
                {
                    return(null);
                }
                return(H.ToObj(p));
            }
            return(null);
        }
Пример #18
0
        public static object GetMonoObject(/*HEAP_PTR*/ byte *heapObj)
        {
            tHeapEntry *pHeapEntry = GET_HEAPENTRY(heapObj);

            #if DEBUG_HEAP
            if (pHeapEntry->signature != VALID_HEAP_OBJ_SIG)
            {
                Sys.Crash("Invalid heap object in GetMonoObject()");
            }
            #endif
            if (pHeapEntry->monoGCHandle != 0)
            {
                void *p = *(void **)heapObj;
                if (p == null)
                {
                    return(null);
                }
                GCHandle handle = (GCHandle)(System.IntPtr)p;
                return(handle.Target);
            }
            return(null);
        }
Пример #19
0
        public static void RemovedWeakRefTarget(/*HEAP_PTR*/ byte *target)
        {
            tHeapEntry *pTarget = GET_HEAPENTRY(target);

            DeleteSync(pTarget);
        }
Пример #20
0
        public static /*HEAP_PTR*/ byte **GetWeakRefAddress(/*HEAP_PTR*/ byte *target)
        {
            tHeapEntry *pTarget = GET_HEAPENTRY(target);

            return(&pTarget->pSync->weakRef);
        }
Пример #21
0
 static void RemoveWeakRefTarget(tHeapEntry *pTarget, uint removeLongRefs)
 {
     System_WeakReference.TargetGone(&pTarget->pSync->weakRef, removeLongRefs);
 }
Пример #22
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);
        }
Пример #23
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
        }
Пример #24
0
        public static void MakeDeletable(/*HEAP_PTR*/ byte *heapObj)
        {
            tHeapEntry *pHeapEntry = GET_HEAPENTRY(heapObj);

            pHeapEntry->marked = 0;
        }