Skip to content
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
This fixes an issue in Server GC where an item in the finalizer queue…
… became stale due to not being relocated.

The problem was that a finalizable object was allocated on one heap, but registered in the finalizer queue of another heap (this is possible due to heap balancing). In CFinalize::UpdatePromotedGenerations, we ask for the generation of an object, and move the object to the correct section of the finalizer queue. In the error case, we obtained the wrong result for the generation of the object because it lives on another heap, and that heap hadn't set the final generation for the region containing the object yet.

The fix simply fetches the heap from the alloc context after the allocation. That is the correct heap to register the object on.
  • Loading branch information
PeterSolMS committed Jun 22, 2021
commit 5a043d386946310758f729edf4fd7c45af798c05
16 changes: 16 additions & 0 deletions src/coreclr/gc/gc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42286,6 +42286,13 @@ GCHeap::Alloc(gc_alloc_context* context, size_t size, uint32_t flags REQD_ALIGN_
#endif // FEATURE_STRUCTALIGN
}

#ifdef MULTIPLE_HEAPS
// the heap may have changed due to heap balancing - it's important
// to register the object for finalization on the heap it was allocated on
hp = acontext->get_alloc_heap()->pGenGCHeap;
assert (hp != nullptr);
#endif //MULTIPLE_HEAPS

CHECK_ALLOC_AND_POSSIBLY_REGISTER_FOR_FINALIZATION(newAlloc, size, flags & GC_ALLOC_FINALIZE);

#ifdef USE_REGIONS
Expand Down Expand Up @@ -44409,6 +44416,9 @@ CFinalize::RelocateFinalizationData (int gen, gc_heap* hp)
unsigned int Seg = gen_segment (gen);

Object** startIndex = SegQueue (Seg);

dprintf (3, ("RelocateFinalizationData gen=%d, [%Ix,%Ix[", gen, startIndex, SegQueue (FreeList)));

for (Object** po = startIndex; po < SegQueue (FreeList);po++)
{
GCHeap::Relocate (po, &sc);
Expand All @@ -44418,6 +44428,8 @@ CFinalize::RelocateFinalizationData (int gen, gc_heap* hp)
void
CFinalize::UpdatePromotedGenerations (int gen, BOOL gen_0_empty_p)
{
dprintf(3, ("UpdatePromotedGenerations gen=%d, gen_0_empty_p=%d", gen, gen_0_empty_p));

// update the generation fill pointers.
// if gen_0_empty is FALSE, test each object to find out if
// it was promoted or not
Expand All @@ -44442,6 +44454,8 @@ CFinalize::UpdatePromotedGenerations (int gen, BOOL gen_0_empty_p)
int new_gen = g_theGCHeap->WhichGeneration (*po);
if (new_gen != i)
{
dprintf (3, ("Moving object %Ix->%Ix from gen %d to gen %d", po, *po, i, new_gen));

if (new_gen > i)
{
//promotion
Expand Down Expand Up @@ -44473,6 +44487,8 @@ CFinalize::GrowArray()
}
memcpy (newArray, m_Array, oldArraySize*sizeof(Object*));

dprintf (3, ("Grow finalizer array [%Ix,%Ix[ -> [%Ix,%Ix[", m_Array, m_EndArray, newArray, &m_Array[newArraySize]));

//adjust the fill pointers
for (int i = 0; i < FreeList; i++)
{
Expand Down