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); }
internal static UIntPtr FirstObjPtrWithFieldInCard(UIntPtr c) { VTable.Assert(CardTable.IsValidCardNo(c), "Not valid card no"); VTable.Assert(CardTable.IsMyLiveGcCard(c), "Not my live GC card"); UIntPtr cardAddr = CardTable.CardAddr(c); UIntPtr nextCardAddr = CardTable.NextCardAddr(c); // Scan backward. May go to zombie areas UIntPtr cardBefore = c - 1; while (cardBefore >= CardTable.FirstCardNo && OffsetTable.NoObjectPtrToTheCard(cardBefore) && CardTable.IsMyGcCard(cardBefore)) { cardBefore--; } UIntPtr ptr; if (cardBefore < CardTable.FirstCardNo || !CardTable.IsMyGcCard(cardBefore)) { // this case happens when c is the first live card that has an object. VTable.Assert(CardTable.IsMyGcCard(cardBefore + 1), "The next card must be a GC card"); VTable.Assert(CardTable.CardAddr(cardBefore + 1) == CardTable.PageAddrOfCard(cardBefore + 1), "The next card must be at the boundary of a page"); UIntPtr pageAddr = CardTable.PageAddrOfCard(cardBefore + 1); ptr = PtrToNextObject(pageAddr, (UIntPtr)PreHeader.Size, nextCardAddr); } else { VTable.Assert(!OffsetTable.NoObjectPtrToTheCard(cardBefore), "A card with an object must have been found"); ptr = CardTable.CardAddr(cardBefore) + OffsetTable.GetOffset(cardBefore); } VTable.Assert(ptr < nextCardAddr, "No objptr in this card"); // Scan forward. Update offset table in the course. UIntPtr currentPtr = ptr; while (currentPtr < cardAddr) { UIntPtr size = OffsetTable.ObjectSize(currentPtr); if (currentPtr + size - PreHeader.Size > cardAddr) { VTable.Assert(CardTable.CardGeneration(CardTable.CardNo(currentPtr)) == CardTable.CardGeneration(c), "The whole object must be in the same generation"); break; } else { ptr = currentPtr; currentPtr = PtrToNextObject(currentPtr, size, nextCardAddr); VTable.Assert(CardTable.CardNo(ptr) <= CardTable.CardNo(currentPtr), "Previous ptr should be before current ptr"); if (CardTable.CardNo(ptr) < CardTable.CardNo(currentPtr)) { UIntPtr ptrC = CardTable.CardNo(ptr); UIntPtr offsetC = ptr - CardTable.CardAddr(ptrC); if (offsetC > GetOffset(ptrC)) { SetOffset(ptrC, offsetC); } } } } VTable.Assert(currentPtr != UIntPtr.Zero, "current ptr is zero"); VTable.Assert(currentPtr < nextCardAddr, "No objptr found in this card"); #if DEBUG_OFFSETTABLE UIntPtr temp = OffsetTable.FirstPtrFromInteriorTable(c); if (temp != currentPtr) { VTable.DebugPrint("Found ptr ({0:x8}) inconsistent with first ptr from interior table({1:x8})\n", __arglist(currentPtr, temp)); VTable.Assert(false); } #endif return(currentPtr); }