Skip to content

Commit 06bb200

Browse files
authored
Mark overflow fix for regions (#60646)
1 parent ef2c904 commit 06bb200

File tree

2 files changed

+94
-48
lines changed

2 files changed

+94
-48
lines changed

src/coreclr/gc/gc.cpp

+81-42
Original file line numberDiff line numberDiff line change
@@ -2532,13 +2532,15 @@ uint8_t** gc_heap::background_mark_stack_array = 0;
25322532

25332533
size_t gc_heap::background_mark_stack_array_length = 0;
25342534

2535+
BOOL gc_heap::processed_eph_overflow_p = FALSE;
2536+
2537+
#ifdef USE_REGIONS
2538+
BOOL gc_heap::background_overflow_p = FALSE;
2539+
#else //USE_REGIONS
25352540
uint8_t* gc_heap::background_min_overflow_address =0;
25362541

25372542
uint8_t* gc_heap::background_max_overflow_address =0;
25382543

2539-
BOOL gc_heap::processed_eph_overflow_p = FALSE;
2540-
2541-
#ifndef USE_REGIONS
25422544
uint8_t* gc_heap::background_min_soh_overflow_address =0;
25432545

25442546
uint8_t* gc_heap::background_max_soh_overflow_address =0;
@@ -2548,7 +2550,7 @@ heap_segment* gc_heap::saved_overflow_ephemeral_seg = 0;
25482550
heap_segment* gc_heap::saved_sweep_ephemeral_seg = 0;
25492551

25502552
uint8_t* gc_heap::saved_sweep_ephemeral_start = 0;
2551-
#endif //!USE_REGIONS
2553+
#endif //USE_REGIONS
25522554

25532555
Thread* gc_heap::bgc_thread = 0;
25542556

@@ -23429,6 +23431,21 @@ void gc_heap::mark_object (uint8_t* o THREAD_NUMBER_DCL)
2342923431

2343023432
#ifdef BACKGROUND_GC
2343123433

23434+
#ifdef USE_REGIONS
23435+
void gc_heap::set_background_overflow_p (uint8_t* oo)
23436+
{
23437+
heap_segment* overflow_region = get_region_info_for_address (oo);
23438+
overflow_region->flags |= heap_segment_flags_overflow;
23439+
dprintf (3,("setting overflow flag for region %p", heap_segment_mem (overflow_region)));
23440+
#ifdef MULTIPLE_HEAPS
23441+
gc_heap* overflow_heap = heap_segment_heap (overflow_region);
23442+
#else
23443+
gc_heap* overflow_heap = nullptr;
23444+
#endif
23445+
overflow_heap->background_overflow_p = TRUE;
23446+
}
23447+
#endif //USE_REGIONS
23448+
2343223449
void gc_heap::background_mark_simple1 (uint8_t* oo THREAD_NUMBER_DCL)
2343323450
{
2343423451
uint8_t** mark_stack_limit = &background_mark_stack_array[background_mark_stack_array_length];
@@ -23495,9 +23512,13 @@ void gc_heap::background_mark_simple1 (uint8_t* oo THREAD_NUMBER_DCL)
2349523512
}
2349623513
else
2349723514
{
23498-
dprintf (3,("mark stack overflow for object %Ix ", (size_t)oo));
23515+
dprintf (3,("background mark stack overflow for object %Ix ", (size_t)oo));
23516+
#ifdef USE_REGIONS
23517+
set_background_overflow_p (oo);
23518+
#else //USE_REGIONS
2349923519
background_min_overflow_address = min (background_min_overflow_address, oo);
2350023520
background_max_overflow_address = max (background_max_overflow_address, oo);
23521+
#endif //USE_REGIONS
2350123522
}
2350223523
}
2350323524
else
@@ -23609,9 +23630,13 @@ void gc_heap::background_mark_simple1 (uint8_t* oo THREAD_NUMBER_DCL)
2360923630
}
2361023631
else
2361123632
{
23612-
dprintf (3,("mark stack overflow for object %Ix ", (size_t)oo));
23633+
dprintf (3,("background mark stack overflow for object %Ix ", (size_t)oo));
23634+
#ifdef USE_REGIONS
23635+
set_background_overflow_p (oo);
23636+
#else //USE_REGIONS
2361323637
background_min_overflow_address = min (background_min_overflow_address, oo);
2361423638
background_max_overflow_address = max (background_max_overflow_address, oo);
23639+
#endif //USE_REGIONS
2361523640
}
2361623641
}
2361723642
}
@@ -23887,13 +23912,13 @@ uint8_t* gc_heap::background_first_overflow (uint8_t* min_add,
2388723912
BOOL concurrent_p,
2388823913
BOOL small_object_p)
2388923914
{
23915+
#ifdef USE_REGIONS
23916+
return heap_segment_mem (seg);
23917+
#else
2389023918
uint8_t* o = 0;
2389123919

2389223920
if (small_object_p)
2389323921
{
23894-
#ifdef USE_REGIONS
23895-
return find_first_object (min_add, heap_segment_mem (seg));
23896-
#else
2389723922
if (in_range_for_segment (min_add, seg))
2389823923
{
2389923924
// min_add was the beginning of gen1 when we did the concurrent
@@ -23919,11 +23944,11 @@ uint8_t* gc_heap::background_first_overflow (uint8_t* min_add,
2391923944
}
2392023945
}
2392123946
}
23922-
#endif //USE_REGIONS
2392323947
}
2392423948

2392523949
o = max (heap_segment_mem (seg), min_add);
2392623950
return o;
23951+
#endif //USE_REGIONS
2392723952
}
2392823953

2392923954
void gc_heap::background_process_mark_overflow_internal (uint8_t* min_add, uint8_t* max_add,
@@ -23948,7 +23973,9 @@ void gc_heap::background_process_mark_overflow_internal (uint8_t* min_add, uint8
2394823973

2394923974
exclusive_sync* loh_alloc_lock = 0;
2395023975

23976+
#ifndef USE_REGIONS
2395123977
dprintf (2,("Processing Mark overflow [%Ix %Ix]", (size_t)min_add, (size_t)max_add));
23978+
#endif
2395223979
#ifdef MULTIPLE_HEAPS
2395323980
// We don't have each heap scan all heaps concurrently because we are worried about
2395423981
// multiple threads calling things like find_first_object.
@@ -23981,9 +24008,14 @@ void gc_heap::background_process_mark_overflow_internal (uint8_t* min_add, uint8
2398124008
#ifdef USE_REGIONS
2398224009
if (heap_segment_overflow_p (seg))
2398324010
{
23984-
assert (!concurrent_p);
23985-
current_min_add = max (heap_segment_mem (seg), min_add);
23986-
current_max_add = min (heap_segment_allocated (seg), max_add);
24011+
seg->flags &= ~heap_segment_flags_overflow;
24012+
current_min_add = heap_segment_mem (seg);
24013+
current_max_add = heap_segment_allocated (seg);
24014+
dprintf (2,("Processing Mark overflow [%Ix %Ix]", (size_t)current_min_add, (size_t)current_max_add));
24015+
}
24016+
else
24017+
{
24018+
current_min_add = current_max_add = 0;
2398724019
}
2398824020
#endif //USE_REGIONS
2398924021
uint8_t* o = hp->background_first_overflow (current_min_add, seg, concurrent_p, small_object_segments);
@@ -24034,15 +24066,19 @@ void gc_heap::background_process_mark_overflow_internal (uint8_t* min_add, uint8
2403424066
}
2403524067
}
2403624068

24037-
dprintf (2, ("went through overflow objects in segment %Ix (%d) (so far %Id marked)",
24038-
heap_segment_mem (seg), (small_object_segments ? 0 : 1), total_marked_objects));
24039-
24069+
#ifdef USE_REGIONS
24070+
if (current_max_add != 0)
24071+
#endif //USE_REGIONS
24072+
{
24073+
dprintf (2, ("went through overflow objects in segment %Ix (%d) (so far %Id marked)",
24074+
heap_segment_mem (seg), (small_object_segments ? 0 : 1), total_marked_objects));
24075+
}
2404024076
#ifndef USE_REGIONS
2404124077
if (concurrent_p && (seg == hp->saved_overflow_ephemeral_seg))
2404224078
{
2404324079
break;
2404424080
}
24045-
#endif //USE_REGIONS
24081+
#endif //!USE_REGIONS
2404624082
seg = heap_segment_next_in_range (seg);
2404724083
}
2404824084

@@ -24071,36 +24107,18 @@ BOOL gc_heap::background_process_mark_overflow (BOOL concurrent_p)
2407124107
if (concurrent_p)
2407224108
{
2407324109
assert (!processed_eph_overflow_p);
24074-
24110+
#ifndef USE_REGIONS
2407524111
if ((background_max_overflow_address != 0) &&
2407624112
(background_min_overflow_address != MAX_PTR))
2407724113
{
24078-
#ifdef USE_REGIONS
24079-
// We don't want to step into the ephemeral regions so remember these regions and
24080-
// be sure to process them later. An FGC cannot happen while we are going through
24081-
// the region lists.
24082-
for (int i = 0; i < max_generation; i++)
24083-
{
24084-
heap_segment* region = generation_start_segment (generation_of (i));
24085-
while (region)
24086-
{
24087-
if ((heap_segment_mem (region) <= background_max_overflow_address) &&
24088-
(heap_segment_allocated (region) >= background_min_overflow_address))
24089-
{
24090-
region->flags |= heap_segment_flags_overflow;
24091-
}
24092-
region = heap_segment_next (region);
24093-
}
24094-
}
24095-
#else //USE_REGIONS
2409624114
// We have overflow to process but we know we can't process the ephemeral generations
2409724115
// now (we actually could process till the current gen1 start but since we are going to
2409824116
// make overflow per segment, for now I'll just stop at the saved gen1 start.
2409924117
saved_overflow_ephemeral_seg = ephemeral_heap_segment;
2410024118
background_max_soh_overflow_address = heap_segment_reserved (saved_overflow_ephemeral_seg);
2410124119
background_min_soh_overflow_address = generation_allocation_start (generation_of (max_generation - 1));
24102-
#endif //USE_REGIONS
2410324120
}
24121+
#endif //!USE_REGIONS
2410424122
}
2410524123
else
2410624124
{
@@ -24114,12 +24132,18 @@ BOOL gc_heap::background_process_mark_overflow (BOOL concurrent_p)
2411424132
{
2411524133
// if there was no more overflow we just need to process what we didn't process
2411624134
// on the saved ephemeral segment.
24135+
#ifdef USE_REGIONS
24136+
if (!background_overflow_p)
24137+
#else
2411724138
if ((background_max_overflow_address == 0) && (background_min_overflow_address == MAX_PTR))
24139+
#endif //USE_REGIONS
2411824140
{
2411924141
dprintf (2, ("final processing mark overflow - no more overflow since last time"));
2412024142
grow_mark_array_p = FALSE;
2412124143
}
24122-
#ifndef USE_REGIONS
24144+
#ifdef USE_REGIONS
24145+
background_overflow_p = TRUE;
24146+
#else
2412324147
background_min_overflow_address = min (background_min_overflow_address,
2412424148
background_min_soh_overflow_address);
2412524149
background_max_overflow_address = max (background_max_overflow_address,
@@ -24131,8 +24155,12 @@ BOOL gc_heap::background_process_mark_overflow (BOOL concurrent_p)
2413124155

2413224156
BOOL overflow_p = FALSE;
2413324157
recheck:
24158+
#ifdef USE_REGIONS
24159+
if (background_overflow_p)
24160+
#else
2413424161
if ((! ((background_max_overflow_address == 0)) ||
2413524162
! ((background_min_overflow_address == MAX_PTR))))
24163+
#endif
2413624164
{
2413724165
overflow_p = TRUE;
2413824166

@@ -24155,11 +24183,17 @@ BOOL gc_heap::background_process_mark_overflow (BOOL concurrent_p)
2415524183
grow_mark_array_p = TRUE;
2415624184
}
2415724185

24186+
#ifdef USE_REGIONS
24187+
uint8_t* min_add = 0;
24188+
uint8_t* max_add = 0;
24189+
background_overflow_p = FALSE;
24190+
#else
2415824191
uint8_t* min_add = background_min_overflow_address;
2415924192
uint8_t* max_add = background_max_overflow_address;
2416024193

2416124194
background_max_overflow_address = 0;
2416224195
background_min_overflow_address = MAX_PTR;
24196+
#endif
2416324197

2416424198
background_process_mark_overflow_internal (min_add, max_add, concurrent_p);
2416524199
if (!concurrent_p)
@@ -32375,6 +32409,7 @@ void gc_heap::background_scan_dependent_handles (ScanContext *sc)
3237532409

3237632410
if (!s_fScanRequired)
3237732411
{
32412+
#ifndef USE_REGIONS
3237832413
uint8_t* all_heaps_max = 0;
3237932414
uint8_t* all_heaps_min = MAX_PTR;
3238032415
int i;
@@ -32390,6 +32425,7 @@ void gc_heap::background_scan_dependent_handles (ScanContext *sc)
3239032425
g_heaps[i]->background_max_overflow_address = all_heaps_max;
3239132426
g_heaps[i]->background_min_overflow_address = all_heaps_min;
3239232427
}
32428+
#endif //!USE_REGIONS
3239332429
}
3239432430

3239532431
dprintf(2, ("Starting all gc thread mark stack overflow processing"));
@@ -32920,12 +32956,14 @@ void gc_heap::background_mark_phase ()
3292032956
bpromoted_bytes (heap_number) = 0;
3292132957
static uint32_t num_sizedrefs = 0;
3292232958

32959+
#ifdef USE_REGIONS
32960+
background_overflow_p = FALSE;
32961+
#else
3292332962
background_min_overflow_address = MAX_PTR;
3292432963
background_max_overflow_address = 0;
32925-
#ifndef USE_REGIONS
3292632964
background_min_soh_overflow_address = MAX_PTR;
3292732965
background_max_soh_overflow_address = 0;
32928-
#endif //!USE_REGIONS
32966+
#endif //USE_REGIONS
3292932967
processed_eph_overflow_p = FALSE;
3293032968

3293132969
//set up the mark lists from g_mark_list
@@ -33125,7 +33163,7 @@ void gc_heap::background_mark_phase ()
3312533163

3312633164
enable_preemptive ();
3312733165

33128-
#ifdef MULTIPLE_HEAPS
33166+
#if defined(MULTIPLE_HEAPS) && !defined(USE_REGIONS)
3312933167
bgc_t_join.join(this, gc_join_concurrent_overflow);
3313033168
if (bgc_t_join.joined())
3313133169
{
@@ -33142,6 +33180,7 @@ void gc_heap::background_mark_phase ()
3314233180
all_heaps_max = g_heaps[i]->background_max_overflow_address;
3314333181
if (all_heaps_min > g_heaps[i]->background_min_overflow_address)
3314433182
all_heaps_min = g_heaps[i]->background_min_overflow_address;
33183+
3314533184
}
3314633185
for (i = 0; i < n_heaps; i++)
3314733186
{
@@ -33151,7 +33190,7 @@ void gc_heap::background_mark_phase ()
3315133190
dprintf(3, ("Starting all bgc threads after updating the overflow info"));
3315233191
bgc_t_join.restart();
3315333192
}
33154-
#endif //MULTIPLE_HEAPS
33193+
#endif //MULTIPLE_HEAPS && !USE_REGIONS
3315533194

3315633195
disable_preemptive (true);
3315733196

src/coreclr/gc/gcpriv.h

+13-6
Original file line numberDiff line numberDiff line change
@@ -2466,6 +2466,10 @@ class gc_heap
24662466
void verify_mark_bits_cleared (uint8_t* obj, size_t s);
24672467
PER_HEAP
24682468
void clear_all_mark_array();
2469+
#ifdef USE_REGIONS
2470+
PER_HEAP
2471+
void set_background_overflow_p (uint8_t* oo);
2472+
#endif
24692473

24702474
#ifdef BGC_SERVO_TUNING
24712475

@@ -4282,18 +4286,21 @@ class gc_heap
42824286
PER_HEAP
42834287
size_t background_mark_stack_array_length;
42844288

4289+
// We can't process the ephemeral range concurrently so we
4290+
// wait till final mark to process it.
42854291
PER_HEAP
4286-
uint8_t* background_min_overflow_address;
4292+
BOOL processed_eph_overflow_p;
42874293

4294+
#ifdef USE_REGIONS
42884295
PER_HEAP
4289-
uint8_t* background_max_overflow_address;
4296+
BOOL background_overflow_p;
4297+
#else
4298+
PER_HEAP
4299+
uint8_t* background_min_overflow_address;
42904300

4291-
// We can't process the ephemeral range concurrently so we
4292-
// wait till final mark to process it.
42934301
PER_HEAP
4294-
BOOL processed_eph_overflow_p;
4302+
uint8_t* background_max_overflow_address;
42954303

4296-
#ifndef USE_REGIONS
42974304
PER_HEAP
42984305
uint8_t* background_min_soh_overflow_address;
42994306

0 commit comments

Comments
 (0)