@@ -8460,19 +8460,13 @@ uint32_t* translate_mark_array (uint32_t* ma)
8460
8460
return (uint32_t*)((uint8_t*)ma - size_mark_array_of (0, g_gc_lowest_address));
8461
8461
}
8462
8462
8463
- // from and end must be page aligned addresses.
8464
- void gc_heap::clear_mark_array (uint8_t* from, uint8_t* end, BOOL check_only/*=TRUE*/
8465
8463
#ifdef FEATURE_BASICFREEZE
8466
- , BOOL read_only/*=FALSE*/
8467
- #endif // FEATURE_BASICFREEZE
8468
- )
8464
+ // end must be page aligned addresses.
8465
+ void gc_heap::clear_mark_array (uint8_t* from, uint8_t* end, BOOL read_only/*=FALSE*/)
8469
8466
{
8470
- if(!gc_can_use_concurrent)
8471
- return;
8467
+ assert (gc_can_use_concurrent);
8472
8468
8473
- #ifdef FEATURE_BASICFREEZE
8474
8469
if (!read_only)
8475
- #endif // FEATURE_BASICFREEZE
8476
8470
{
8477
8471
assert (from == align_on_mark_word (from));
8478
8472
}
@@ -8489,45 +8483,41 @@ void gc_heap::clear_mark_array (uint8_t* from, uint8_t* end, BOOL check_only/*=T
8489
8483
size_t beg_word = mark_word_of (align_on_mark_word (from));
8490
8484
//align end word to make sure to cover the address
8491
8485
size_t end_word = mark_word_of (align_on_mark_word (end));
8492
- dprintf (3, ("Calling clearing mark array [%Ix, %Ix[ for addresses [%Ix, %Ix[(%s) ",
8486
+ dprintf (3, ("Calling clearing mark array [%Ix, %Ix[ for addresses [%Ix, %Ix[",
8493
8487
(size_t)mark_word_address (beg_word),
8494
8488
(size_t)mark_word_address (end_word),
8495
- (size_t)from, (size_t)end,
8496
- (check_only ? "check_only" : "clear")));
8497
- if (!check_only)
8498
- {
8499
- uint8_t* op = from;
8500
- while (op < mark_word_address (beg_word))
8501
- {
8502
- mark_array_clear_marked (op);
8503
- op += mark_bit_pitch;
8504
- }
8489
+ (size_t)from, (size_t)end));
8505
8490
8506
- memset (&mark_array[beg_word], 0, (end_word - beg_word)*sizeof (uint32_t));
8491
+ uint8_t* op = from;
8492
+ while (op < mark_word_address (beg_word))
8493
+ {
8494
+ mark_array_clear_marked (op);
8495
+ op += mark_bit_pitch;
8507
8496
}
8497
+
8498
+ memset (&mark_array[beg_word], 0, (end_word - beg_word)*sizeof (uint32_t));
8499
+
8508
8500
#ifdef _DEBUG
8509
- else
8501
+ //Beware, it is assumed that the mark array word straddling
8502
+ //start has been cleared before
8503
+ //verify that the array is empty.
8504
+ size_t markw = mark_word_of (align_on_mark_word (from));
8505
+ size_t markw_end = mark_word_of (align_on_mark_word (end));
8506
+ while (markw < markw_end)
8510
8507
{
8511
- //Beware, it is assumed that the mark array word straddling
8512
- //start has been cleared before
8513
- //verify that the array is empty.
8514
- size_t markw = mark_word_of (align_on_mark_word (from));
8515
- size_t markw_end = mark_word_of (align_on_mark_word (end));
8516
- while (markw < markw_end)
8517
- {
8518
- assert (!(mark_array [markw]));
8519
- markw++;
8520
- }
8521
- uint8_t* p = mark_word_address (markw_end);
8522
- while (p < end)
8523
- {
8524
- assert (!(mark_array_marked (p)));
8525
- p++;
8526
- }
8508
+ assert (!(mark_array [markw]));
8509
+ markw++;
8510
+ }
8511
+ uint8_t* p = mark_word_address (markw_end);
8512
+ while (p < end)
8513
+ {
8514
+ assert (!(mark_array_marked (p)));
8515
+ p++;
8527
8516
}
8528
8517
#endif //_DEBUG
8529
8518
}
8530
8519
}
8520
+ #endif // FEATURE_BASICFREEZE
8531
8521
#endif //BACKGROUND_GC
8532
8522
8533
8523
//These work on untranslated card tables
@@ -9458,6 +9448,7 @@ void gc_heap::copy_brick_card_table()
9458
9448
}
9459
9449
9460
9450
#ifdef FEATURE_BASICFREEZE
9451
+ // Note that we always insert at the head of the max_generation segment list.
9461
9452
BOOL gc_heap::insert_ro_segment (heap_segment* seg)
9462
9453
{
9463
9454
#ifdef FEATURE_EVENT_TRACE
@@ -9477,7 +9468,6 @@ BOOL gc_heap::insert_ro_segment (heap_segment* seg)
9477
9468
return FALSE;
9478
9469
}
9479
9470
9480
- //insert at the head of the segment list
9481
9471
generation* gen2 = generation_of (max_generation);
9482
9472
heap_segment* oldhead = generation_start_segment (gen2);
9483
9473
heap_segment_next (seg) = oldhead;
@@ -9515,13 +9505,12 @@ BOOL gc_heap::insert_ro_segment (heap_segment* seg)
9515
9505
// which portion of the mark array was committed and only decommit that.
9516
9506
void gc_heap::remove_ro_segment (heap_segment* seg)
9517
9507
{
9518
- //clear the mark bits so a new segment allocated in its place will have a clear mark bits
9508
+ //clear the mark bits so a new segment allocated in its place will have a clear mark bits
9519
9509
#ifdef BACKGROUND_GC
9520
9510
if (gc_can_use_concurrent)
9521
9511
{
9522
9512
clear_mark_array (align_lower_mark_word (max (heap_segment_mem (seg), lowest_address)),
9523
- align_on_card_word (min (heap_segment_allocated (seg), highest_address)),
9524
- false); // read_only segments need the mark clear
9513
+ align_on_card_word (min (heap_segment_allocated (seg), highest_address)));
9525
9514
}
9526
9515
#endif //BACKGROUND_GC
9527
9516
@@ -11000,20 +10989,39 @@ inline size_t my_get_size (Object* ob)
11000
10989
#endif //COLLECTIBLE_CLASS
11001
10990
11002
10991
#ifdef BACKGROUND_GC
10992
+ #ifdef FEATURE_BASICFREEZE
11003
10993
inline
11004
10994
void gc_heap::seg_clear_mark_array_bits_soh (heap_segment* seg)
11005
10995
{
11006
10996
uint8_t* range_beg = 0;
11007
10997
uint8_t* range_end = 0;
11008
10998
if (bgc_mark_array_range (seg, FALSE, &range_beg, &range_end))
11009
10999
{
11010
- clear_mark_array (range_beg, align_on_mark_word (range_end), FALSE
11011
- #ifdef FEATURE_BASICFREEZE
11012
- , TRUE
11013
- #endif // FEATURE_BASICFREEZE
11014
- );
11000
+ clear_mark_array (range_beg, align_on_mark_word (range_end), TRUE);
11001
+ }
11002
+ }
11003
+
11004
+ inline
11005
+ void gc_heap::seg_set_mark_array_bits_soh (heap_segment* seg)
11006
+ {
11007
+ uint8_t* range_beg = 0;
11008
+ uint8_t* range_end = 0;
11009
+ if (bgc_mark_array_range (seg, FALSE, &range_beg, &range_end))
11010
+ {
11011
+ size_t beg_word = mark_word_of (align_on_mark_word (range_beg));
11012
+ size_t end_word = mark_word_of (align_on_mark_word (range_end));
11013
+
11014
+ uint8_t* op = range_beg;
11015
+ while (op < mark_word_address (beg_word))
11016
+ {
11017
+ mark_array_set_marked (op);
11018
+ op += mark_bit_pitch;
11019
+ }
11020
+
11021
+ memset (&mark_array[beg_word], 0xFF, (end_word - beg_word)*sizeof (uint32_t));
11015
11022
}
11016
11023
}
11024
+ #endif //FEATURE_BASICFREEZE
11017
11025
11018
11026
void gc_heap::bgc_clear_batch_mark_array_bits (uint8_t* start, uint8_t* end)
11019
11027
{
@@ -26493,6 +26501,19 @@ void gc_heap::mark_phase (int condemned_gen_number, BOOL mark_only_p)
26493
26501
}
26494
26502
}
26495
26503
26504
+ #ifdef FEATURE_BASICFREEZE
26505
+ #ifdef USE_REGIONS
26506
+ assert (!ro_segments_in_range);
26507
+ #else //USE_REGIONS
26508
+ if (ro_segments_in_range)
26509
+ {
26510
+ dprintf(3,("Marking in range ro segments"));
26511
+ mark_ro_segments();
26512
+ // Should fire an ETW event here.
26513
+ }
26514
+ #endif //USE_REGIONS
26515
+ #endif //FEATURE_BASICFREEZE
26516
+
26496
26517
dprintf(3,("Marking Roots"));
26497
26518
26498
26519
GCScan::GcScanRoots(GCHeap::Promote,
@@ -27538,6 +27559,18 @@ void gc_heap::process_ephemeral_boundaries (uint8_t* x,
27538
27559
}
27539
27560
#endif //!USE_REGIONS
27540
27561
27562
+ #ifdef FEATURE_BASICFREEZE
27563
+ inline
27564
+ void gc_heap::seg_set_mark_bits (heap_segment* seg)
27565
+ {
27566
+ uint8_t* o = heap_segment_mem (seg);
27567
+ while (o < heap_segment_allocated (seg))
27568
+ {
27569
+ set_marked (o);
27570
+ o = o + Align (size(o));
27571
+ }
27572
+ }
27573
+
27541
27574
inline
27542
27575
void gc_heap::seg_clear_mark_bits (heap_segment* seg)
27543
27576
{
@@ -27548,36 +27581,77 @@ void gc_heap::seg_clear_mark_bits (heap_segment* seg)
27548
27581
{
27549
27582
clear_marked (o);
27550
27583
}
27551
- o = o + Align (size (o));
27584
+ o = o + Align (size (o));
27552
27585
}
27553
27586
}
27554
27587
27555
- #ifdef FEATURE_BASICFREEZE
27556
- void gc_heap::sweep_ro_segments (heap_segment* start_seg)
27588
+ // We have to do this for in range ro segments because these objects' life time isn't accurately
27589
+ // expressed. The expectation is all objects on ro segs are live. So we just artifically mark
27590
+ // all of them on the in range ro segs.
27591
+ void gc_heap::mark_ro_segments()
27557
27592
{
27558
- //go through all of the segment in range and reset the mark bit
27559
- heap_segment* seg = start_seg ;
27560
-
27561
- while (seg )
27593
+ #ifdef USE_REGIONS
27594
+ assert (!ro_segments_in_range) ;
27595
+ #else //USE_REGIONS
27596
+ if ((settings.condemned_generation == max_generation) && ro_segments_in_range )
27562
27597
{
27563
- if (heap_segment_read_only_p (seg) &&
27564
- heap_segment_in_range_p (seg))
27598
+ heap_segment* seg = generation_start_segment (generation_of (max_generation));
27599
+
27600
+ while (seg)
27565
27601
{
27566
- #ifdef BACKGROUND_GC
27567
- if (settings.concurrent)
27602
+ if (!heap_segment_read_only_p (seg))
27603
+ break;
27604
+
27605
+ if (heap_segment_in_range_p (seg))
27568
27606
{
27569
- seg_clear_mark_array_bits_soh (seg);
27607
+ #ifdef BACKGROUND_GC
27608
+ if (settings.concurrent)
27609
+ {
27610
+ seg_set_mark_array_bits_soh (seg);
27611
+ }
27612
+ else
27613
+ #endif //BACKGROUND_GC
27614
+ {
27615
+ seg_set_mark_bits (seg);
27616
+ }
27570
27617
}
27571
- else
27618
+ seg = heap_segment_next (seg);
27619
+ }
27620
+ }
27621
+ #endif //USE_REGIONS
27622
+ }
27623
+
27624
+ void gc_heap::sweep_ro_segments()
27625
+ {
27626
+ #ifdef USE_REGIONS
27627
+ assert (!ro_segments_in_range);
27628
+ #else //USE_REGIONS
27629
+ if ((settings.condemned_generation == max_generation) && ro_segments_in_range)
27630
+ {
27631
+ heap_segment* seg = generation_start_segment (generation_of (max_generation));;
27632
+
27633
+ while (seg)
27634
+ {
27635
+ if (!heap_segment_read_only_p (seg))
27636
+ break;
27637
+
27638
+ if (heap_segment_in_range_p (seg))
27572
27639
{
27573
- seg_clear_mark_bits (seg);
27574
- }
27575
- #else //BACKGROUND_GC
27576
- seg_clear_mark_bits (seg);
27640
+ #ifdef BACKGROUND_GC
27641
+ if (settings.concurrent)
27642
+ {
27643
+ seg_clear_mark_array_bits_soh (seg);
27644
+ }
27645
+ else
27577
27646
#endif //BACKGROUND_GC
27647
+ {
27648
+ seg_clear_mark_bits (seg);
27649
+ }
27650
+ }
27651
+ seg = heap_segment_next (seg);
27578
27652
}
27579
- seg = heap_segment_next (seg);
27580
27653
}
27654
+ #endif //USE_REGIONS
27581
27655
}
27582
27656
#endif // FEATURE_BASICFREEZE
27583
27657
@@ -28956,16 +29030,8 @@ void gc_heap::plan_phase (int condemned_gen_number)
28956
29030
}
28957
29031
28958
29032
#ifdef FEATURE_BASICFREEZE
28959
- #ifdef USE_REGIONS
28960
- assert (!ro_segments_in_range);
28961
- #else //USE_REGIONS
28962
- if ((generation_start_segment (condemned_gen1) != ephemeral_heap_segment) &&
28963
- ro_segments_in_range)
28964
- {
28965
- sweep_ro_segments (generation_start_segment (condemned_gen1));
28966
- }
28967
- #endif //USE_REGIONS
28968
- #endif // FEATURE_BASICFREEZE
29033
+ sweep_ro_segments();
29034
+ #endif //FEATURE_BASICFREEZE
28969
29035
28970
29036
#ifndef MULTIPLE_HEAPS
28971
29037
int condemned_gen_index = get_stop_generation_index (condemned_gen_number);
@@ -35007,6 +35073,20 @@ void gc_heap::background_mark_phase ()
35007
35073
35008
35074
dprintf (GTC_LOG, ("FM: h%d: loh: %Id, soh: %Id, poh: %Id", heap_number, total_loh_size, total_soh_size, total_poh_size));
35009
35075
35076
+ #ifdef FEATURE_BASICFREEZE
35077
+ #ifdef USE_REGIONS
35078
+ assert (!ro_segments_in_range);
35079
+ #else //USE_REGIONS
35080
+ if (ro_segments_in_range)
35081
+ {
35082
+ dprintf (2, ("nonconcurrent marking in range ro segments"));
35083
+ mark_ro_segments();
35084
+ //concurrent_print_time_delta ("nonconcurrent marking in range ro segments");
35085
+ concurrent_print_time_delta ("NRRO");
35086
+ }
35087
+ #endif //USE_REGIONS
35088
+ #endif //FEATURE_BASICFREEZE
35089
+
35010
35090
dprintf (2, ("nonconcurrent marking stack roots"));
35011
35091
GCScan::GcScanRoots(background_promote,
35012
35092
max_generation, max_generation,
@@ -42364,13 +42444,8 @@ void gc_heap::background_sweep()
42364
42444
#endif //DOUBLY_LINKED_FL
42365
42445
42366
42446
#ifdef FEATURE_BASICFREEZE
42367
- generation* max_gen = generation_of (max_generation);
42368
- if ((generation_start_segment (max_gen) != ephemeral_heap_segment) &&
42369
- ro_segments_in_range)
42370
- {
42371
- sweep_ro_segments (generation_start_segment (max_gen));
42372
- }
42373
- #endif // FEATURE_BASICFREEZE
42447
+ sweep_ro_segments();
42448
+ #endif //FEATURE_BASICFREEZE
42374
42449
42375
42450
if (current_c_gc_state != c_gc_state_planning)
42376
42451
{
@@ -45350,6 +45425,9 @@ bool GCHeap::IsPromoted(Object* object)
45350
45425
if (o)
45351
45426
{
45352
45427
((CObjectHeader*)o)->Validate(TRUE, TRUE, is_marked);
45428
+
45429
+ // Frozen objects aren't expected to be "not promoted" here
45430
+ assert(is_marked || !IsInFrozenSegment(object));
45353
45431
}
45354
45432
#endif //_DEBUG
45355
45433
0 commit comments