Exemplo n.º 1
0
        internal static unsafe void VerifyFirst(UIntPtr previousObjectAddr,
                                                UIntPtr objectAddr)
        {
            UIntPtr page = PageTable.Page(objectAddr);

            if (previousObjectAddr != UIntPtr.Zero)
            {
                UIntPtr previousPage = PageTable.Page(previousObjectAddr);
                UIntPtr pageCursor   = previousPage + 1;
                while (pageCursor < page)
                {
                    uint    cursorOffset = PageTable.Extra(pageCursor);
                    UIntPtr objAddr      = (PageTable.PageAddr(pageCursor) +
                                            cursorOffset - OFFSET_SKEW);
                    if (!(cursorOffset <= OFFSET_NO_DATA ||
                          BumpAllocator.IsUnusedSpace(objAddr) ||
                          Allocator.IsAlignment(objAddr) ||
                          BumpAllocator.IsRestOfPageZero(objAddr)))
                    {
                        VTable.DebugPrint
                            ("cursorOffset={0:x} OFFSET_NO_DATA={1:x} objAddr={2:x} unused={3} isalign={4} iszero={5}\n",
                            __arglist((cursorOffset),
                                      (OFFSET_NO_DATA),
                                      ((long)objAddr),
                                      (BumpAllocator.IsUnusedSpace(objAddr)),
                                      (Allocator.IsAlignment(objAddr)),
                                      (BumpAllocator.IsRestOfPageZero(objAddr))));
                    }
                    VTable.Assert(cursorOffset <= OFFSET_NO_DATA ||
                                  BumpAllocator.IsUnusedSpace(objAddr) ||
                                  Allocator.IsAlignment(objAddr) ||
                                  BumpAllocator.IsRestOfPageZero(objAddr),
                                  "VerifyFirst 1");
                    pageCursor++;
                }
            }
            uint offset = PageTable.Extra(page);

            if (offset > OFFSET_NO_DATA)
            {
                UIntPtr firstAddr =
                    PageTable.PageAddr(page) + offset - OFFSET_SKEW;
                if (!(firstAddr == objectAddr ||
                      (firstAddr + UIntPtr.Size == objectAddr &&
                       Allocator.IsAlignment(firstAddr))))
                {
                    VTable.DebugPrint
                        ("firstAddr={0:x} objectAddr={1:x} isalign={2}\n",
                        __arglist(((long)firstAddr),
                                  ((long)objectAddr),
                                  (Allocator.IsAlignment(firstAddr))));
                }
                VTable.Assert(firstAddr == objectAddr ||
                              (firstAddr + 4 == objectAddr &&
                               Allocator.IsAlignment(firstAddr)),
                              "VerifyFirst 2");
            }
        }
Exemplo n.º 2
0
        internal static unsafe void ClearThreadStack(Thread thread)
        {
            short   threadIndex = (short)thread.threadIndex;
            UIntPtr endPage     = PageTable.Page(CallStack.StackBase(thread));
            UIntPtr startPage   = endPage - 1;

            VTable.Assert(PageTable.IsStackPage(PageTable.Type(startPage)));
            VTable.Assert(PageTable.Extra(startPage) == threadIndex);
            while (startPage > 0 &&
                   PageTable.IsStackPage(PageTable.Type(startPage - 1)) &&
                   PageTable.Extra(startPage - 1) == threadIndex)
            {
                startPage--;
            }
            UIntPtr startAddr = PageTable.PageAddr(startPage);
            UIntPtr size      = PageTable.RegionSize(endPage - startPage);

            SetUnallocatedPages(startAddr, size);
        }
Exemplo n.º 3
0
        /*
         * Returns a pointer to the beginning of an object such that the
         * pointer is less than or equal to addr.  N.B. Before may return a
         * pointer to an alignment or an unused space token.
         */
        private static UIntPtr Before(UIntPtr addr)
        {
            UIntPtr page   = PageTable.Page(addr);
            uint    offset = PageTable.Extra(page);

            // OFFSET_NO_DATA and negative offsets should always fail this
            // test.
            if (PageTable.PageAddr(page) + (offset - OFFSET_SKEW) > addr)
            {
                // If the addr is an interior pointer of an object on a
                // previous page, go back one entry.
                --page;
                offset = PageTable.Extra(page);
            }
            if (offset == OFFSET_NO_DATA)
            {
                // Scroll back until we find a page entry with real data in
                // it.  This handles the case of a large object allocated
                // across pages.
                do
                {
                    --page;
                    offset = PageTable.Extra(page);
                }while (offset == OFFSET_NO_DATA);
            }
            VTable.Assert(offset > OFFSET_NO_DATA, "No offset data");
            // Unused: since we currently do not use negative offsets in the
            // page table.  This would be more efficient for really big
            // objects, but the OFFSET_NO_DATA value works fine too.

            /*
             * // Scroll backwards using big steps.  Offset will never be
             * // OFFSET_NO_DATA in this loop.
             * while (offset < OFFSET_NO_DATA) {
             * entry += (offset - OFFSET_SKEW);
             * offset = *entry;
             * }
             */
            return(PageTable.PageAddr(page) + (offset - OFFSET_SKEW));
        }
Exemplo n.º 4
0
        /*
         * Returns a pointer to the first object on the given page.
         * N.B. If called on a page with no ~allocated~ first object it may
         * return a pointer to the unused space token.
         */
        internal static UIntPtr First(UIntPtr page)
        {
            uint    offset   = PageTable.Extra(page);
            UIntPtr pageAddr = PageTable.PageAddr(page);
            UIntPtr currAddr;

            if (offset != OFFSET_NO_DATA)
            {
                currAddr = pageAddr + (offset - OFFSET_SKEW);
            }
            else
            {
                currAddr = Before(pageAddr);
                VTable.Assert(currAddr <= pageAddr);
                UIntPtr nextPageStart = PageTable.PagePad(currAddr + 1);
                while (currAddr < pageAddr)
                {
                    if (Allocator.IsAlignment(currAddr))
                    {
                        currAddr += UIntPtr.Size;
                    }
                    else if (BumpAllocator.IsUnusedSpace(currAddr))
                    {
                        currAddr = PageTable.PagePad(currAddr) + PreHeader.Size;
                    }
                    else
                    {
                        if (currAddr >= nextPageStart)
                        {
                            InteriorPtrTable.SetFirst(currAddr);
                            nextPageStart = PageTable.PagePad(currAddr + 1);
                        }
                        currAddr += ObjectSize(currAddr);
                    }
                }
            }
            currAddr = Allocator.SkipAlignment(currAddr);
            return(currAddr);
        }
Exemplo n.º 5
0
        private static UIntPtr FirstPtrFromInteriorTable(UIntPtr c)
        {
            UIntPtr cardAddr     = CardTable.CardAddr(c);
            UIntPtr nextCardAddr = CardTable.NextCardAddr(c);
            UIntPtr page         = PageTable.Page(cardAddr);
            UIntPtr pageAddr     = PageTable.PageAddr(page);
            UIntPtr currAddr;

            if (page == 0)
            {
                currAddr = PtrToNextObject(pageAddr,
                                           (UIntPtr)PreHeader.Size, nextCardAddr);
            }
            else
            {
                short offset = PageTable.Extra(page);
                currAddr = UIntPtr.Zero;
                if (offset != InteriorPtrTable.OFFSET_NO_DATA)
                {
                    currAddr = pageAddr + (offset - InteriorPtrTable.OFFSET_SKEW);
                }

                // In general, we expect currAddr <= cardAddr. Or in the extreme
                // case, when the object starts from the page boundary,
                // currAddr - Object.HEADER_BYTES <= cardAddr. The contrary
                // cases has to be handled by searching previous pages.

                if (currAddr == UIntPtr.Zero ||
                    (currAddr > cardAddr &&
                     currAddr - PreHeader.Size > cardAddr))
                {
                    // look from previous pages, in case that an object on
                    // them spans to the current page. In that case, we should
                    // should use that object's ptr.

                    currAddr = InteriorPtrTable.Last(page - 1);

                    // Usually, Last() returns a pointer before or at the page
                    // boundary. However, there is one exception: when an object
                    // exactly fits to the last byte of the previous page, and the next
                    // object starts right from the page boundary (the first byte of
                    // the next page), then the pointer to this next object is returned.
                    // Example found: objPtr =3d09fa8, size=60, pageboundary=
                    // 3d0a000, next objPtr=3d0a008. Then returned pointer is
                    // 3d0a008, which is beyond the page boundary.

                    VTable.Assert(currAddr <= pageAddr ||
                                  currAddr - PreHeader.Size <= pageAddr,
                                  "object is expected before page or right at the beginning of it");
                }
            }
            VTable.Assert(currAddr < nextCardAddr, "object is expected before next card");

            while (currAddr < nextCardAddr)
            {
                if (Allocator.IsAlignment(currAddr))
                {
                    currAddr += UIntPtr.Size;
                }
                else if (BumpAllocator.IsUnusedSpace(currAddr))
                {
                    currAddr = PageTable.PagePad(currAddr) + PreHeader.Size;
                }
                else
                {
                    UIntPtr size = InteriorPtrTable.ObjectSize(currAddr);
                    if (currAddr + size - PreHeader.Size > cardAddr)
                    {
                        return(currAddr);
                    }
                    currAddr += size;
                }
            }
            VTable.Assert(false, "No obj ptr found by looking at interior table");
            return(UIntPtr.Zero);
        }