@@ -2522,6 +2522,8 @@ size_t gc_heap::bgc_loh_size_increased = 0;
25222522
25232523size_t gc_heap::bgc_poh_size_increased = 0;
25242524
2525+ size_t gc_heap::background_soh_size_end_mark = 0;
2526+
25252527size_t gc_heap::background_soh_alloc_count = 0;
25262528
25272529size_t gc_heap::background_uoh_alloc_count = 0;
@@ -28892,6 +28894,14 @@ void gc_heap::plan_phase (int condemned_gen_number)
2889228894 {
2889328895 dprintf (2,( "**** Doing Compacting GC ****"));
2889428896
28897+ #if defined(USE_REGIONS) && defined(BACKGROUND_GC)
28898+ if (should_update_end_mark_size())
28899+ {
28900+ background_soh_size_end_mark += generation_end_seg_allocated (older_gen) -
28901+ r_older_gen_end_seg_allocated;
28902+ }
28903+ #endif //USE_REGIONS && BACKGROUND_GC
28904+
2889528905#ifndef USE_REGIONS
2889628906 if (should_expand)
2889728907 {
@@ -29396,6 +29406,13 @@ void gc_heap::fix_generation_bounds (int condemned_gen_number,
2939629406 }
2939729407 }
2939829408#endif //MULTIPLE_HEAPS
29409+
29410+ #ifdef BACKGROUND_GC
29411+ if (should_update_end_mark_size())
29412+ {
29413+ background_soh_size_end_mark = generation_size (max_generation);
29414+ }
29415+ #endif //BACKGROUND_GC
2939929416#endif //!USE_REGIONS
2940029417
2940129418 {
@@ -29614,6 +29631,14 @@ void gc_heap::thread_final_regions (bool compact_p)
2961429631 generation_final_regions[gen_idx].tail = generation_tail_region (gen);
2961529632 }
2961629633
29634+ #ifdef BACKGROUND_GC
29635+ heap_segment* max_gen_tail_region = 0;
29636+ if (should_update_end_mark_size())
29637+ {
29638+ max_gen_tail_region = generation_final_regions[max_generation].tail;
29639+ }
29640+ #endif //BACKGROUND_GC
29641+
2961729642 // Step 2: for each region in the condemned generations, we thread it onto its planned generation
2961829643 // in our generation_final_regions array.
2961929644 for (int gen_idx = condemned_gen_number; gen_idx >= 0; gen_idx--)
@@ -29664,6 +29689,21 @@ void gc_heap::thread_final_regions (bool compact_p)
2966429689 }
2966529690 }
2966629691
29692+ #ifdef BACKGROUND_GC
29693+ if (max_gen_tail_region)
29694+ {
29695+ max_gen_tail_region = heap_segment_next (max_gen_tail_region);
29696+
29697+ while (max_gen_tail_region)
29698+ {
29699+ background_soh_size_end_mark += heap_segment_allocated (max_gen_tail_region) -
29700+ heap_segment_mem (max_gen_tail_region);
29701+
29702+ max_gen_tail_region = heap_segment_next (max_gen_tail_region);
29703+ }
29704+ }
29705+ #endif //BACKGROUND_GC
29706+
2966729707 // Step 4: if a generation doesn't have any regions, we need to get a new one for it;
2966829708 // otherwise we just set the head region as the start region for that generation.
2966929709 for (int gen_idx = 0; gen_idx <= max_generation; gen_idx++)
@@ -32927,6 +32967,11 @@ void gc_heap::decommit_mark_array_by_seg (heap_segment* seg)
3292732967 }
3292832968}
3292932969
32970+ bool gc_heap::should_update_end_mark_size()
32971+ {
32972+ return ((settings.condemned_generation == (max_generation - 1)) && (current_c_gc_state == c_gc_state_planning));
32973+ }
32974+
3293032975void gc_heap::background_mark_phase ()
3293132976{
3293232977 verify_mark_array_cleared();
@@ -33001,6 +33046,7 @@ void gc_heap::background_mark_phase ()
3300133046 bgc_begin_poh_size = total_poh_size;
3300233047 bgc_loh_size_increased = 0;
3300333048 bgc_poh_size_increased = 0;
33049+ background_soh_size_end_mark = 0;
3300433050
3300533051 dprintf (GTC_LOG, ("BM: h%d: loh: %Id, soh: %Id, poh: %Id", heap_number, total_loh_size, total_soh_size, total_poh_size));
3300633052
@@ -33481,6 +33527,8 @@ void gc_heap::background_mark_phase ()
3348133527 heap_segment_background_allocated (seg) = heap_segment_allocated (seg);
3348233528 }
3348333529
33530+ background_soh_size_end_mark += heap_segment_background_allocated (seg) - heap_segment_mem (seg);
33531+
3348433532 dprintf (3333, ("h%d gen%d seg %Ix (%Ix) background allocated is %Ix",
3348533533 heap_number, i, (size_t)(seg), heap_segment_mem (seg),
3348633534 heap_segment_background_allocated (seg)));
@@ -45097,11 +45145,11 @@ size_t GCHeap::GetTotalBytesInUse ()
4509745145 for (int i = 0; i < gc_heap::n_heaps; i++)
4509845146 {
4509945147 GCHeap* Hp = gc_heap::g_heaps [i]->vm_heap;
45100- tot_size += Hp->ApproxTotalBytesInUse (FALSE );
45148+ tot_size += Hp->ApproxTotalBytesInUse( );
4510145149 }
4510245150 return tot_size;
4510345151#else
45104- return ApproxTotalBytesInUse ();
45152+ return ApproxTotalBytesInUse();
4510545153#endif //MULTIPLE_HEAPS
4510645154}
4510745155
@@ -45156,58 +45204,56 @@ size_t GCHeap::ApproxTotalBytesInUse(BOOL small_heap_only)
4515645204 size_t totsize = 0;
4515745205 enter_spin_lock (&pGenGCHeap->gc_lock);
4515845206
45159- // the complication with the following code is that background GC may
45160- // remove the ephemeral segment while we are iterating
45161- // if so, we retry a couple times and ultimately may report a slightly wrong result
45162- for (int tries = 1; tries <= 3; tries++)
45207+ // For gen0 it's a bit complicated because we are currently allocating in it. We get the fragmentation first
45208+ // just so that we don't give a negative number for the resulting size.
45209+ generation* gen = pGenGCHeap->generation_of (0);
45210+ size_t gen0_frag = generation_free_list_space (gen) + generation_free_obj_space (gen);
45211+ uint8_t* current_alloc_allocated = pGenGCHeap->alloc_allocated;
45212+ heap_segment* current_eph_seg = pGenGCHeap->ephemeral_heap_segment;
45213+ size_t gen0_size = 0;
45214+ #ifdef USE_REGIONS
45215+ heap_segment* gen0_seg = generation_start_segment (gen);
45216+ while (gen0_seg)
4516345217 {
45164- heap_segment* eph_seg = generation_allocation_segment (pGenGCHeap->generation_of (0));
45165- // Get small block heap size info
45166- totsize = (pGenGCHeap->alloc_allocated - heap_segment_mem (eph_seg));
45167- heap_segment* seg1 = generation_start_segment (pGenGCHeap->generation_of (max_generation));
45168- while ((seg1 != eph_seg) && (seg1 != nullptr)
45169- #ifdef BACKGROUND_GC
45170- && (seg1 != pGenGCHeap->freeable_soh_segment)
45171- #endif //BACKGROUND_GC
45172- )
45218+ uint8_t* end = in_range_for_segment (current_alloc_allocated, gen0_seg) ?
45219+ current_alloc_allocated : heap_segment_allocated (gen0_seg);
45220+ gen0_size += end - heap_segment_mem (gen0_seg);
45221+
45222+ if (gen0_seg == current_eph_seg)
4517345223 {
45174- #ifdef BACKGROUND_GC
45175- if (!heap_segment_decommitted_p (seg1))
45176- #endif //BACKGROUND_GC
45177- {
45178- totsize += heap_segment_allocated (seg1) -
45179- heap_segment_mem (seg1);
45180- }
45181- seg1 = heap_segment_next (seg1);
45182- }
45183- if (seg1 == eph_seg)
4518445224 break;
45225+ }
4518545226 }
45227+ #else //USE_REGIONS
45228+ // For segments ephemeral seg does not change.
45229+ gen0_size = current_alloc_allocated - heap_segment_mem (current_eph_seg);
45230+ #endif //USE_REGIONS
4518645231
45187- //discount the fragmentation
45188- for (int i = 0; i <= max_generation; i++)
45232+ totsize = gen0_size - gen0_frag;
45233+
45234+ int stop_gen_index = max_generation;
45235+
45236+ if (gc_heap::current_c_gc_state == c_gc_state_planning)
45237+ {
45238+ // During BGC sweep since we can be deleting SOH segments, we avoid walking the segment
45239+ // list.
45240+ generation* oldest_gen = pGenGCHeap->generation_of (max_generation);
45241+ totsize = pGenGCHeap->background_soh_size_end_mark - generation_free_list_space (oldest_gen) - generation_free_obj_space (oldest_gen);
45242+ stop_gen_index--;
45243+ }
45244+
45245+ for (int i = (max_generation - 1); i <= stop_gen_index; i++)
4518945246 {
4519045247 generation* gen = pGenGCHeap->generation_of (i);
45191- totsize -= ( generation_free_list_space (gen) + generation_free_obj_space (gen) );
45248+ totsize += pGenGCHeap->generation_size (i) - generation_free_list_space (gen) - generation_free_obj_space (gen);
4519245249 }
4519345250
4519445251 if (!small_heap_only)
4519545252 {
4519645253 for (int i = uoh_start_generation; i < total_generation_count; i++)
4519745254 {
45198- heap_segment* seg2 = generation_start_segment (pGenGCHeap->generation_of (i));
45199-
45200- while (seg2 != 0)
45201- {
45202- totsize += heap_segment_allocated (seg2) -
45203- heap_segment_mem (seg2);
45204- seg2 = heap_segment_next (seg2);
45205- }
45206-
45207- //discount the fragmentation
45208- generation* uoh_gen = pGenGCHeap->generation_of (i);
45209- size_t frag = generation_free_list_space (uoh_gen) + generation_free_obj_space (uoh_gen);
45210- totsize -= frag;
45255+ generation* gen = pGenGCHeap->generation_of (i);
45256+ totsize += pGenGCHeap->generation_size (i) - generation_free_list_space (gen) - generation_free_obj_space (gen);
4521145257 }
4521245258 }
4521345259 leave_spin_lock (&pGenGCHeap->gc_lock);
0 commit comments