Esempio n. 1
0
        /*
         * Returns a pointer past the last object _that_fits_completely_ on
         * the given page.  Note that the "last" object on a page may
         * actually start on a previous page.
         */
        internal static UIntPtr Last(UIntPtr page)
        {
            UIntPtr currAddr = InteriorPtrTable.First(page);
            UIntPtr endAddr  = PageTable.PageAddr(page + 1);

            // Look out for the unused space token: this page may not
            // have been completely allocated: its "first" object might not
            // be valid.
            if (BumpAllocator.IsUnusedSpace(currAddr) || currAddr >= endAddr)
            {
                // Back up to the previous object.  Should be fast
                // since First updated the InteriorPtrTable entries.
                currAddr = Before(PageTable.PageAddr(page));
            }
            // REVIEW this is very similar to Find(addr) below.
            VTable.Assert(currAddr <= endAddr);
            while (true)
            {
                // Watch out for alignment padding; advance the pointer if
                // it points to a syncblock index rather than a vtable
                // pointer.  Note that we must do this before scrolling,
                // since the page table value was set before we knew the
                // required alignment.
                if (Allocator.IsAlignment(currAddr))
                {
                    currAddr += UIntPtr.Size;
                }
                else if (BumpAllocator.IsUnusedSpace(currAddr))
                {
                    UIntPtr nextAddr =
                        PageTable.PagePad(currAddr) + PreHeader.Size;
                    if (nextAddr >= endAddr)
                    {
                        return(currAddr);
                    }
                    else
                    {
                        currAddr = nextAddr;
                    }
                }
                else
                {
                    VTable.Assert(currAddr <= endAddr);
                    UIntPtr size     = ObjectSize(currAddr);
                    UIntPtr postAddr = currAddr + size;
                    if (postAddr > endAddr)
                    {
                        if (postAddr - PreHeader.Size > endAddr)
                        {
                            // The object spills over onto the next page
                            return(currAddr);
                        }
                        else
                        {
                            // The object ended at or before the page boundary
                            return(postAddr);
                        }
                    }
                    else
                    {
                        currAddr = postAddr;
                    }
                }
            }
        }