if (seg)
{
- // Can't assert this when it's callled by everyone (it's true when it's called by mark cards).
- //assert (in_range_for_segment (o, seg));
if (in_range_for_segment (o, seg))
{
dprintf (2, ("obj %Ix belongs to segment %Ix(-%Ix)", o, (uint8_t*)heap_segment_mem(seg), (uint8_t*)heap_segment_reserved(seg)));
#endif //SEG_MAPPING_TABLE
size_t gcard_of ( uint8_t*);
-void gset_card (size_t card);
#define memref(i) *(uint8_t**)(i)
#if !defined(FEATURE_PAL)
if (!gc_thread_no_affinitize_p)
{
- //We are about to set affinity for GC threads, it is a good place to setup NUMA and
- //CPU groups, because the process mask, processor number, group number are all
- //readyly available.
+ // We are about to set affinity for GC threads. It is a good place to set up NUMA and
+ // CPU groups because the process mask, processor number, and group number are all
+ // readily available.
if (CPUGroupInfo::CanEnableGCCPUGroups())
set_thread_group_affinity_for_heap(heap_number, &affinity);
else
}
#ifdef CARD_BUNDLE
+// Get the card bundle table for the specified card table.
inline
uint32_t*& card_table_card_bundle_table (uint32_t* c_table)
{
#endif //BACKGROUND_GC
-
void gc_heap::fix_card_table ()
{
+#ifdef NO_WRITE_BARRIER
#ifdef WRITE_WATCH
heap_segment* seg = heap_segment_rw (generation_start_segment (generation_of (max_generation)));
dprintf (3,("Found %Id pages written", bcount));
for (unsigned i = 0; i < bcount; i++)
{
- for (unsigned j = 0; j< (card_size*card_word_width)/OS_PAGE_SIZE; j++)
+ // Set the card words corresponding to the entire page.
+ for (unsigned j = 0; j < (card_size*card_word_width)/OS_PAGE_SIZE; j++)
{
card_table [card_word (card_of (g_addresses [i]))+j] = ~0u;
}
card_of (g_addresses [i]), (size_t)g_addresses [i],
card_of (g_addresses [i]+OS_PAGE_SIZE), (size_t)g_addresses [i]+OS_PAGE_SIZE));
}
+
if (bcount >= array_size){
base_address = g_addresses [array_size-1] + OS_PAGE_SIZE;
bcount = array_size;
}
#endif //BACKGROUND_GC
#endif //WRITE_WATCH
+#endif //NO_WRITE_BARRIER
}
#ifdef BACKGROUND_GC
artificial_pinned_size = ps;
}
-// Because we have the artifical pinning, we can't gaurantee that pinned and npinned
+// Because we have the artificial pinning, we can't guarantee that pinned and npinned
// plugs are always interleaved.
void gc_heap::store_plug_gap_info (uint8_t* plug_start,
uint8_t* plug_end,
size_t end_word = card_word (end_card);
if (start_word < end_word)
{
+ // Figure out the bit positions of the cards within their words
unsigned bits = card_bit (start_card);
card_table [start_word] &= lowbits (~0, bits);
for (size_t i = start_word+1; i < end_word; i++)
}
else
{
+ // If the start and end cards are in the same word, just clear the appropriate card
+ // bits in that word.
card_table [start_word] &= (lowbits (~0, card_bit (start_card)) |
highbits (~0, card_bit (end_card)));
}
// copy [srccard, ...[ to [dst_card, end_card[
// This will set the same bit twice. Can be optimized.
inline
-void gc_heap::copy_cards (size_t dst_card, size_t src_card,
- size_t end_card, BOOL nextp)
+void gc_heap::copy_cards (size_t dst_card,
+ size_t src_card,
+ size_t end_card,
+ BOOL nextp)
{
// If the range is empty, this function is a no-op - with the subtlety that
// either of the accesses card_table[srcwrd] or card_table[dstwrd] could be
size_t dstwrd = card_word (dst_card);
unsigned int srctmp = card_table[srcwrd];
unsigned int dsttmp = card_table[dstwrd];
+
for (size_t card = dst_card; card < end_card; card++)
{
if (srctmp & (1 << srcbit))
dsttmp |= 1 << dstbit;
else
dsttmp &= ~(1 << dstbit);
+
if (!(++srcbit % 32))
{
srctmp = card_table[++srcwrd];
srcbit = 0;
}
+
if (nextp)
{
if (srctmp & (1 << srcbit))
dsttmp |= 1 << dstbit;
}
+
if (!(++dstbit % 32))
{
card_table[dstwrd] = dsttmp;
dstbit = 0;
}
}
+
card_table[dstwrd] = dsttmp;
}
}
#ifdef CARD_BUNDLE
+
+// Find the first non-zero card word between cardw and cardw_end.
+// The index of the word we find is returned in cardw.
BOOL gc_heap::find_card_dword (size_t& cardw, size_t cardw_end)
{
dprintf (3, ("gc: %d, find_card_dword cardw: %Ix, cardw_end: %Ix",
size_t end_cardb = cardw_card_bundle (align_cardw_on_bundle (cardw_end));
while (1)
{
- //find a non null bundle
- while ((cardb < end_cardb) &&
- (card_bundle_set_p (cardb)==0))
+ // Find a non-zero bundle
+ while ((cardb < end_cardb) && (card_bundle_set_p (cardb) == 0))
{
cardb++;
}
+
if (cardb == end_cardb)
return FALSE;
- //find a non empty card word
+ // We found a bundle, so go through its words and find a non-zero card word
uint32_t* card_word = &card_table[max(card_bundle_cardw (cardb),cardw)];
uint32_t* card_word_end = &card_table[min(card_bundle_cardw (cardb+1),cardw_end)];
- while ((card_word < card_word_end) &&
- !(*card_word))
+ while ((card_word < card_word_end) && !(*card_word))
{
card_word++;
}
+
if (card_word != card_word_end)
{
- cardw = (card_word - &card_table [0]);
+ cardw = (card_word - &card_table[0]);
return TRUE;
}
else if ((cardw <= card_bundle_cardw (cardb)) &&
card_bundle_cardw (cardb+1)));
card_bundle_clear (cardb);
}
+
cardb++;
}
}
while (card_word < card_word_end)
{
- if ((*card_word) != 0)
+ if (*card_word != 0)
{
cardw = (card_word - &card_table [0]);
return TRUE;
}
+
card_word++;
}
- return FALSE;
+ return FALSE;
}
-
}
#endif //CARD_BUNDLE
-BOOL gc_heap::find_card (uint32_t* card_table, size_t& card,
- size_t card_word_end, size_t& end_card)
+// Find cards that are set between two points in a card table.
+// Parameters
+// card_table : The card table.
+// card : [in/out] As input, the card to start searching from.
+// As output, the first card that's set.
+// card_word_end : The card word at which to stop looking.
+// end_card : [out] The last card which is set.
+BOOL gc_heap::find_card(uint32_t* card_table,
+ size_t& card,
+ size_t card_word_end,
+ size_t& end_card)
{
uint32_t* last_card_word;
- uint32_t y;
- uint32_t z;
+ uint32_t card_word_value;
+ uint32_t bit_position;
+
// Find the first card which is set
-
last_card_word = &card_table [card_word (card)];
- z = card_bit (card);
- y = (*last_card_word) >> z;
- if (!y)
+ bit_position = card_bit (card);
+ card_word_value = (*last_card_word) >> bit_position;
+ if (!card_word_value)
{
- z = 0;
+ bit_position = 0;
#ifdef CARD_BUNDLE
- size_t lcw = card_word(card)+1;
+ // Using the card bundle, go through the remaining card words between here and
+ // card_word_end until we find one that is non-zero.
+ size_t lcw = card_word(card) + 1;
if (gc_heap::find_card_dword (lcw, card_word_end) == FALSE)
+ {
return FALSE;
+ }
else
{
last_card_word = &card_table [lcw];
- y = *last_card_word;
+ card_word_value = *last_card_word;
}
#else //CARD_BUNDLE
+ // Go through the remaining card words between here and card_word_end until we find
+ // one that is non-zero.
do
{
++last_card_word;
}
+ while ((last_card_word < &card_table [card_word_end]) && !(*last_card_word));
- while ((last_card_word < &card_table [card_word_end]) &&
- !(*last_card_word));
if (last_card_word < &card_table [card_word_end])
- y = *last_card_word;
+ {
+ card_word_value = *last_card_word;
+ }
else
+ {
+ // We failed to find any non-zero card words before we got to card_word_end
return FALSE;
+ }
#endif //CARD_BUNDLE
}
-
// Look for the lowest bit set
- if (y)
+ if (card_word_value)
{
- while (!(y & 1))
+ while (!(card_word_value & 1))
{
- z++;
- y = y / 2;
+ bit_position++;
+ card_word_value = card_word_value / 2;
}
}
- card = (last_card_word - &card_table [0])* card_word_width + z;
+
+ // card is the card word index * card size + the bit index within the card
+ card = (last_card_word - &card_table[0]) * card_word_width + bit_position;
+
do
{
- z++;
- y = y / 2;
- if ((z == card_word_width) &&
- (last_card_word < &card_table [card_word_end]))
- {
+ // Keep going until we get to an un-set card.
+ bit_position++;
+ card_word_value = card_word_value / 2;
+ // If we reach the end of the card word and haven't hit a 0 yet, start going
+ // card word by card word until we get to one that's not fully set (0xFFFF...)
+ // or we reach card_word_end.
+ if ((bit_position == card_word_width) && (last_card_word < &card_table [card_word_end]))
+ {
do
{
- y = *(++last_card_word);
- }while ((last_card_word < &card_table [card_word_end]) &&
+ card_word_value = *(++last_card_word);
+ } while ((last_card_word < &card_table [card_word_end]) &&
+
#ifdef _MSC_VER
- (y == (1 << card_word_width)-1)
+ (card_word_value == (1 << card_word_width)-1)
#else
// if left shift count >= width of type,
// gcc reports error.
- (y == ~0u)
+ (card_word_value == ~0u)
#endif // _MSC_VER
);
- z = 0;
+ bit_position = 0;
}
- } while (y & 1);
+ } while (card_word_value & 1);
- end_card = (last_card_word - &card_table [0])* card_word_width + z;
+ end_card = (last_card_word - &card_table [0])* card_word_width + bit_position;
+
//dprintf (3, ("find_card: [%Ix, %Ix[ set", card, end_card));
dprintf (3, ("fc: [%Ix, %Ix[", card, end_card));
return TRUE;
#ifdef BACKGROUND_GC
dprintf (3, ("current_sweep_pos is %Ix, saved_sweep_ephemeral_seg is %Ix(%Ix)",
current_sweep_pos, saved_sweep_ephemeral_seg, saved_sweep_ephemeral_start));
+
heap_segment* soh_seg = heap_segment_rw (generation_start_segment (generation_of (max_generation)));
- PREFIX_ASSUME(soh_seg != NULL);
- while (soh_seg )
+ PREFIX_ASSUME(soh_seg != NULL);
+
+ while (soh_seg)
{
dprintf (3, ("seg %Ix, bgc_alloc: %Ix, alloc: %Ix",
soh_seg,
heap_segment_background_allocated (soh_seg),
heap_segment_allocated (soh_seg)));
+
soh_seg = heap_segment_next_rw (soh_seg);
}
#endif //BACKGROUND_GC
uint8_t* low = gc_low;
uint8_t* high = gc_high;
- size_t end_card = 0;
+ size_t end_card = 0;
+
generation* oldest_gen = generation_of (max_generation);
int curr_gen_number = max_generation;
- uint8_t* gen_boundary = generation_allocation_start
- (generation_of (curr_gen_number - 1));
- uint8_t* next_boundary = (compute_next_boundary
- (gc_low, curr_gen_number, relocating));
+ uint8_t* gen_boundary = generation_allocation_start(generation_of(curr_gen_number - 1));
+ uint8_t* next_boundary = compute_next_boundary(gc_low, curr_gen_number, relocating);
+
heap_segment* seg = heap_segment_rw (generation_start_segment (oldest_gen));
-
PREFIX_ASSUME(seg != NULL);
- uint8_t* beg = generation_allocation_start (oldest_gen);
- uint8_t* end = compute_next_end (seg, low);
- uint8_t* last_object = beg;
+ uint8_t* beg = generation_allocation_start (oldest_gen);
+ uint8_t* end = compute_next_end (seg, low);
+ uint8_t* last_object = beg;
size_t cg_pointers_found = 0;
- size_t card_word_end = (card_of (align_on_card_word (end)) /
- card_word_width);
+ size_t card_word_end = (card_of (align_on_card_word (end)) / card_word_width);
size_t n_eph = 0;
size_t n_gen = 0;
size_t n_card_set = 0;
- uint8_t* nhigh = (relocating ?
- heap_segment_plan_allocated (ephemeral_heap_segment) : high);
+ uint8_t* nhigh = (relocating ? heap_segment_plan_allocated (ephemeral_heap_segment) : high);
BOOL foundp = FALSE;
- uint8_t* start_address = 0;
- uint8_t* limit = 0;
+ uint8_t* start_address = 0;
+ uint8_t* limit = 0;
size_t card = card_of (beg);
#ifdef BACKGROUND_GC
BOOL consider_bgc_mark_p = FALSE;
{
if (card_of(last_object) > card)
{
+ // cg means cross-generational
dprintf (3, ("Found %Id cg pointers", cg_pointers_found));
if (cg_pointers_found == 0)
{
n_card_set -= (card_of (last_object) - card);
total_cards_cleared += (card_of (last_object) - card);
}
- n_eph +=cg_pointers_found;
+
+ n_eph += cg_pointers_found;
cg_pointers_found = 0;
card = card_of (last_object);
}
+
if (card >= end_card)
{
- foundp = find_card (card_table, card, card_word_end, end_card);
+ // Find the first card that's set (between card and card_word_end)
+ foundp = find_card(card_table, card, card_word_end, end_card);
if (foundp)
{
- n_card_set+= end_card - card;
+ // We found card(s) set.
+ n_card_set += end_card - card;
start_address = max (beg, card_address (card));
}
+
limit = min (end, card_address (end_card));
}
- if ((!foundp) || (last_object >= end) || (card_address (card) >= end))
+
+ if (!foundp || (last_object >= end) || (card_address (card) >= end))
{
- if ((foundp) && (cg_pointers_found == 0))
+ if (foundp && (cg_pointers_found == 0))
{
dprintf(3,(" Clearing cards [%Ix, %Ix[ ", (size_t)card_address(card),
(size_t)end));
n_card_set -= (card_of (end) - card);
total_cards_cleared += (card_of (end) - card);
}
- n_eph +=cg_pointers_found;
+
+ n_eph += cg_pointers_found;
cg_pointers_found = 0;
+
if ((seg = heap_segment_next_in_range (seg)) != 0)
{
#ifdef BACKGROUND_GC
}
}
+ // We've found a card and will now go through the objects in it.
assert (card_set_p (card));
{
- uint8_t* o = last_object;
-
+ uint8_t* o = last_object;
o = find_first_object (start_address, last_object);
- //Never visit an object twice.
- assert (o >= last_object);
+ // Never visit an object twice.
+ assert (o >= last_object);
- //dprintf(3,("Considering card %Ix start object: %Ix, %Ix[ boundary: %Ix",
- dprintf(3, ("c: %Ix, o: %Ix, l: %Ix[ boundary: %Ix",
- card, (size_t)o, (size_t)limit, (size_t)gen_boundary));
+ //dprintf(3,("Considering card %Ix start object: %Ix, %Ix[ boundary: %Ix",
+ dprintf(3, ("c: %Ix, o: %Ix, l: %Ix[ boundary: %Ix",
+ card, (size_t)o, (size_t)limit, (size_t)gen_boundary));
while (o < limit)
{
if (card_table_refcount (ct) == 0)
{
destroy_card_table (ct);
- g_gc_card_table = 0;
+ g_gc_card_table = nullptr;
#ifdef FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP
SoftwareWriteWatch::StaticClose();
#endif // FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP
((CObjectHeader*)obj)->GetHeader()->SetBit(BIT_SBLK_FINALIZER_RUN);
}
-#endif // FEATURE_PREMORTEM_FINALIZATION
-
-#ifdef FEATURE_PREMORTEM_FINALIZATION
//--------------------------------------------------------------------
//