From: Julian Seward Date: Tue, 18 Nov 2008 23:40:00 +0000 (+0000) Subject: event_map_maybe_GC: handle corner case that was previously simply X-Git-Tag: svn/VALGRIND_3_4_0~111 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c9b2f7441741cf5884b1d17b1105450b5cf603b7;p=thirdparty%2Fvalgrind.git event_map_maybe_GC: handle corner case that was previously simply asserted on: if all the entries in the event map are in the same generation, then we have no LRU information at all with which to decide which entries to discard. So in this case throw away half of them randomly -- there's nothing better we can do. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@8783 --- diff --git a/helgrind/libhb_core.c b/helgrind/libhb_core.c index 15a64c845c..63f5b32f56 100644 --- a/helgrind/libhb_core.c +++ b/helgrind/libhb_core.c @@ -3065,20 +3065,9 @@ static void event_map_maybe_GC ( void ) } VG_(doneIterFM)( genMap ); - if (VG_(clo_verbosity) > 1) { - VG_(message)(Vg_DebugMsg, - "libhb: EvM GC: delete generations %lu and below, " - "retaining %lu entries", - maxGen, retained ); - } - VG_(deleteFM)( genMap, NULL, NULL ); - /* If this fails, it means there's only one generation in the - entire tree. So we're kind of in a bad situation, and need to - do some stop-gap measure, such as randomly deleting half the - entries. */ - tl_assert(retained < oldrefTreeN); + tl_assert(retained >= 0 && retained <= oldrefTreeN); /* Now make up a big list of the oldrefTree entries we want to delete. We can't simultaneously traverse the tree and delete @@ -3087,12 +3076,49 @@ static void event_map_maybe_GC ( void ) refs2del = VG_(newXA)( HG_(zalloc), "libhb.emmG.1", HG_(free), sizeof(OldRef*) ); - VG_(OSetGen_ResetIter)( oldrefTree ); - while ( (oldref = VG_(OSetGen_Next)( oldrefTree )) ) { - tl_assert(oldref->magic == OldRef_MAGIC); - if (oldref->gen <= maxGen) { - VG_(addToXA)( refs2del, &oldref ); + if (retained < oldrefTreeN) { + + /* This is the normal (expected) case. We discard any ref whose + generation number <= maxGen. */ + VG_(OSetGen_ResetIter)( oldrefTree ); + while ( (oldref = VG_(OSetGen_Next)( oldrefTree )) ) { + tl_assert(oldref->magic == OldRef_MAGIC); + if (oldref->gen <= maxGen) { + VG_(addToXA)( refs2del, &oldref ); + } } + if (VG_(clo_verbosity) > 1) { + VG_(message)(Vg_DebugMsg, + "libhb: EvM GC: delete generations %lu and below, " + "retaining %lu entries", + maxGen, retained ); + } + + } else { + + static UInt rand_seed = 0; /* leave as static */ + + /* Degenerate case: there's only one generation in the entire + tree, so we need to have some other way of deciding which + refs to throw away. Just throw out half of them randomly. */ + tl_assert(retained == oldrefTreeN); + VG_(OSetGen_ResetIter)( oldrefTree ); + while ( (oldref = VG_(OSetGen_Next)( oldrefTree )) ) { + UInt n; + tl_assert(oldref->magic == OldRef_MAGIC); + n = VG_(random)( &rand_seed ); + if ((n & 0xFFF) < 0x800) { + VG_(addToXA)( refs2del, &oldref ); + retained--; + } + } + if (VG_(clo_verbosity) > 1) { + VG_(message)(Vg_DebugMsg, + "libhb: EvM GC: randomly delete half the entries, " + "retaining %lu entries", + retained ); + } + } n2del = VG_(sizeXA)( refs2del );