diff options
Diffstat (limited to 'src/gc/gc.cpp')
-rw-r--r-- | src/gc/gc.cpp | 168 |
1 files changed, 51 insertions, 117 deletions
diff --git a/src/gc/gc.cpp b/src/gc/gc.cpp index 6187938ff8..66c8b6afbc 100644 --- a/src/gc/gc.cpp +++ b/src/gc/gc.cpp @@ -389,7 +389,7 @@ void log_va_msg(const char *fmt, va_list args) int pid_len = sprintf_s (&pBuffer[buffer_start], BUFFERSIZE - buffer_start, "[%5d]", (uint32_t)GCToOSInterface::GetCurrentThreadIdForLogging()); buffer_start += pid_len; memset(&pBuffer[buffer_start], '-', BUFFERSIZE - buffer_start); - int msg_len = _vsnprintf(&pBuffer[buffer_start], BUFFERSIZE - buffer_start, fmt, args ); + int msg_len = _vsnprintf_s(&pBuffer[buffer_start], BUFFERSIZE - buffer_start, _TRUNCATE, fmt, args ); if (msg_len == -1) { msg_len = BUFFERSIZE - buffer_start; @@ -1402,9 +1402,6 @@ int mark_time, plan_time, sweep_time, reloc_time, compact_time; #ifndef MULTIPLE_HEAPS -#define ephemeral_low g_gc_ephemeral_low -#define ephemeral_high g_gc_ephemeral_high - #endif // MULTIPLE_HEAPS #ifdef TRACE_GC @@ -2187,27 +2184,22 @@ void stomp_write_barrier_resize(bool is_runtime_suspended, bool requires_upper_b args.card_table = g_gc_card_table; args.lowest_address = g_gc_lowest_address; args.highest_address = g_gc_highest_address; +#ifdef FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP + if (SoftwareWriteWatch::IsEnabledForGCHeap()) + { + args.write_watch_table = g_gc_sw_ww_table; + } +#endif // FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP GCToEEInterface::StompWriteBarrier(&args); } -void stomp_write_barrier_ephemeral(bool is_runtime_suspended, uint8_t* ephemeral_lo, uint8_t* ephemeral_hi) +void stomp_write_barrier_ephemeral(uint8_t* ephemeral_low, uint8_t* ephemeral_high) { WriteBarrierParameters args = {}; args.operation = WriteBarrierOp::StompEphemeral; - args.is_runtime_suspended = is_runtime_suspended; - args.ephemeral_lo = g_gc_ephemeral_low; - args.ephemeral_hi = g_gc_ephemeral_high; -#ifdef MULTIPLE_HEAPS - // It is not correct to update the EE's g_ephemeral_low and g_ephemeral_high - // to anything other than their default values when using Server GC, since - // there is no single ephemeral generation across all of the heaps. - // Server GC write barriers do not reference these two globals, but ErectWriteBarrier does. - // - // When MULTIPLE_HEAPS is defined, g_gc_ephemeral_low and g_gc_ephemeral_high should - // always have their default values. - assert(args.ephemeral_lo == (uint8_t*)1); - assert(args.ephemeral_hi == (uint8_t*)~0); -#endif // MULTIPLE_HEAPS + args.is_runtime_suspended = true; + args.ephemeral_low = ephemeral_low; + args.ephemeral_high = ephemeral_high; GCToEEInterface::StompWriteBarrier(&args); } @@ -2220,6 +2212,8 @@ void stomp_write_barrier_initialize() args.card_table = g_gc_card_table; args.lowest_address = g_gc_lowest_address; args.highest_address = g_gc_highest_address; + args.ephemeral_low = reinterpret_cast<uint8_t*>(1); + args.ephemeral_high = reinterpret_cast<uint8_t*>(~0); GCToEEInterface::StompWriteBarrier(&args); } @@ -2430,6 +2424,10 @@ BOOL gc_heap::ro_segments_in_range; size_t gc_heap::gen0_big_free_spaces = 0; +uint8_t* gc_heap::ephemeral_low; + +uint8_t* gc_heap::ephemeral_high; + uint8_t* gc_heap::lowest_address; uint8_t* gc_heap::highest_address; @@ -7044,6 +7042,7 @@ int gc_heap::grow_brick_card_tables (uint8_t* start, uint8_t* ha = g_gc_highest_address; uint8_t* saved_g_lowest_address = min (start, g_gc_lowest_address); uint8_t* saved_g_highest_address = max (end, g_gc_highest_address); + seg_mapping* new_seg_mapping_table = nullptr; #ifdef BACKGROUND_GC // This value is only for logging purpose - it's not necessarily exactly what we // would commit for mark array but close enough for diagnostics purpose. @@ -7204,14 +7203,18 @@ int gc_heap::grow_brick_card_tables (uint8_t* start, #ifdef GROWABLE_SEG_MAPPING_TABLE { - seg_mapping* new_seg_mapping_table = (seg_mapping*)(mem + st_table_offset_aligned); + new_seg_mapping_table = (seg_mapping*)(mem + st_table_offset_aligned); new_seg_mapping_table = (seg_mapping*)((uint8_t*)new_seg_mapping_table - size_seg_mapping_table_of (0, (align_lower_segment (saved_g_lowest_address)))); memcpy(&new_seg_mapping_table[seg_mapping_word_of(g_gc_lowest_address)], &seg_mapping_table[seg_mapping_word_of(g_gc_lowest_address)], size_seg_mapping_table_of(g_gc_lowest_address, g_gc_highest_address)); - seg_mapping_table = new_seg_mapping_table; + // new_seg_mapping_table gets assigned to seg_mapping_table at the bottom of this function, + // not here. The reason for this is that, if we fail at mark array committing (OOM) and we've + // already switched seg_mapping_table to point to the new mapping table, we'll decommit it and + // run into trouble. By not assigning here, we're making sure that we will not change seg_mapping_table + // if an OOM occurs. } #endif //GROWABLE_SEG_MAPPING_TABLE @@ -7225,7 +7228,7 @@ int gc_heap::grow_brick_card_tables (uint8_t* start, translated_ct = translate_card_table (ct); dprintf (GC_TABLE_LOG, ("card table: %Ix(translated: %Ix), seg map: %Ix, mark array: %Ix", - (size_t)ct, (size_t)translated_ct, (size_t)seg_mapping_table, (size_t)card_table_mark_array (ct))); + (size_t)ct, (size_t)translated_ct, (size_t)new_seg_mapping_table, (size_t)card_table_mark_array (ct))); #ifdef BACKGROUND_GC if (hp->should_commit_mark_array()) @@ -7277,9 +7280,6 @@ int gc_heap::grow_brick_card_tables (uint8_t* start, } g_gc_card_table = translated_ct; - g_gc_lowest_address = saved_g_lowest_address; - g_gc_highest_address = saved_g_highest_address; - SoftwareWriteWatch::SetResizedUntranslatedTable( mem + sw_ww_table_offset, saved_g_lowest_address, @@ -7290,6 +7290,8 @@ int gc_heap::grow_brick_card_tables (uint8_t* start, // grow version of the write barrier. This test tells us if the new // segment was allocated at a lower address than the old, requiring // that we start doing an upper bounds check in the write barrier. + g_gc_lowest_address = saved_g_lowest_address; + g_gc_highest_address = saved_g_highest_address; stomp_write_barrier_resize(true, la != saved_g_lowest_address); write_barrier_updated = true; @@ -7304,6 +7306,9 @@ int gc_heap::grow_brick_card_tables (uint8_t* start, g_gc_card_table = translated_ct; } + seg_mapping_table = new_seg_mapping_table; + + GCToOSInterface::FlushProcessWriteBuffers(); g_gc_lowest_address = saved_g_lowest_address; g_gc_highest_address = saved_g_highest_address; @@ -9662,7 +9667,7 @@ void gc_heap::make_generation (generation& gen, heap_segment* seg, uint8_t* star #endif //FREE_USAGE_STATS } -void gc_heap::adjust_ephemeral_limits (bool is_runtime_suspended) +void gc_heap::adjust_ephemeral_limits () { ephemeral_low = generation_allocation_start (generation_of (max_generation - 1)); ephemeral_high = heap_segment_reserved (ephemeral_heap_segment); @@ -9670,8 +9675,10 @@ void gc_heap::adjust_ephemeral_limits (bool is_runtime_suspended) dprintf (3, ("new ephemeral low: %Ix new ephemeral high: %Ix", (size_t)ephemeral_low, (size_t)ephemeral_high)) +#ifndef MULTIPLE_HEAPS // This updates the write barrier helpers with the new info. - stomp_write_barrier_ephemeral(is_runtime_suspended, ephemeral_low, ephemeral_high); + stomp_write_barrier_ephemeral(ephemeral_low, ephemeral_high); +#endif // MULTIPLE_HEAPS } #if defined(TRACE_GC) || defined(GC_CONFIG_DRIVEN) @@ -10466,7 +10473,7 @@ gc_heap::init_gc_heap (int h_number) make_background_mark_stack (b_arr); #endif //BACKGROUND_GC - adjust_ephemeral_limits(true); + adjust_ephemeral_limits(); #ifdef MARK_ARRAY // why would we clear the mark array for this page? it should be cleared.. @@ -15364,7 +15371,11 @@ void gc_heap::gc1() if (!settings.concurrent) #endif //BACKGROUND_GC { - adjust_ephemeral_limits(!!IsGCThread()); +#ifndef FEATURE_REDHAWK + // IsGCThread() always returns false on CoreRT, but this assert is useful in CoreCLR. + assert(!!IsGCThread()); +#endif // FEATURE_REDHAWK + adjust_ephemeral_limits(); } #ifdef BACKGROUND_GC @@ -16204,7 +16215,11 @@ BOOL gc_heap::expand_soh_with_minimal_gc() dd_gc_new_allocation (dynamic_data_of (max_generation)) -= ephemeral_size; dd_new_allocation (dynamic_data_of (max_generation)) = dd_gc_new_allocation (dynamic_data_of (max_generation)); - adjust_ephemeral_limits(!!IsGCThread()); +#ifndef FEATURE_REDHAWK + // IsGCThread() always returns false on CoreRT, but this assert is useful in CoreCLR. + assert(!!IsGCThread()); +#endif // FEATURE_REDHAWK + adjust_ephemeral_limits(); return TRUE; } else @@ -32778,8 +32793,8 @@ gc_heap::verify_heap (BOOL begin_gc_p) #endif //BACKGROUND_GC #ifndef MULTIPLE_HEAPS - if ((g_gc_ephemeral_low != generation_allocation_start (generation_of (max_generation - 1))) || - (g_gc_ephemeral_high != heap_segment_reserved (ephemeral_heap_segment))) + if ((ephemeral_low != generation_allocation_start (generation_of (max_generation - 1))) || + (ephemeral_high != heap_segment_reserved (ephemeral_heap_segment))) { FATAL_GC_ERROR(); } @@ -35140,11 +35155,7 @@ GCHeap::GarbageCollectGeneration (unsigned int gen, gc_reason reason) #endif //!MULTIPLE_HEAPS #ifdef FEATURE_PREMORTEM_FINALIZATION - if ((!pGenGCHeap->settings.concurrent && pGenGCHeap->settings.found_finalizers) || - FinalizerThread::HaveExtraWorkForFinalizer()) - { - FinalizerThread::EnableFinalization(); - } + GCToEEInterface::EnableFinalization(!pGenGCHeap->settings.concurrent && pGenGCHeap->settings.found_finalizers); #endif // FEATURE_PREMORTEM_FINALIZATION return dd_collection_count (dd); @@ -35681,85 +35692,6 @@ void GCHeap::SetFinalizationRun (Object* obj) #endif // FEATURE_PREMORTEM_FINALIZATION -//---------------------------------------------------------------------------- -// -// Write Barrier Support for bulk copy ("Clone") operations -// -// StartPoint is the target bulk copy start point -// len is the length of the bulk copy (in bytes) -// -// -// Performance Note: -// -// This is implemented somewhat "conservatively", that is we -// assume that all the contents of the bulk copy are object -// references. If they are not, and the value lies in the -// ephemeral range, we will set false positives in the card table. -// -// We could use the pointer maps and do this more accurately if necessary - -#if defined(_MSC_VER) && defined(_TARGET_X86_) -#pragma optimize("y", on) // Small critical routines, don't put in EBP frame -#endif //_MSC_VER && _TARGET_X86_ - -void -GCHeap::SetCardsAfterBulkCopy( Object **StartPoint, size_t len ) -{ - Object **rover; - Object **end; - - // Target should aligned - assert(Aligned ((size_t)StartPoint)); - - - // Don't optimize the Generation 0 case if we are checking for write barrier voilations - // since we need to update the shadow heap even in the generation 0 case. -#if defined (WRITE_BARRIER_CHECK) && !defined (SERVER_GC) - if (g_pConfig->GetHeapVerifyLevel() & EEConfig::HEAPVERIFY_BARRIERCHECK) - for(unsigned i=0; i < len / sizeof(Object*); i++) - updateGCShadow(&StartPoint[i], StartPoint[i]); -#endif //WRITE_BARRIER_CHECK && !SERVER_GC - -#ifdef FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP - if (SoftwareWriteWatch::IsEnabledForGCHeap()) - { - SoftwareWriteWatch::SetDirtyRegion(StartPoint, len); - } -#endif // FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP - - // If destination is in Gen 0 don't bother - if ( -#ifdef BACKGROUND_GC - (!gc_heap::settings.concurrent) && -#endif //BACKGROUND_GC - (g_theGCHeap->WhichGeneration( (Object*) StartPoint ) == 0)) - return; - - rover = StartPoint; - end = StartPoint + (len/sizeof(Object*)); - while (rover < end) - { - if ( (((uint8_t*)*rover) >= g_gc_ephemeral_low) && (((uint8_t*)*rover) < g_gc_ephemeral_high) ) - { - // Set Bit For Card and advance to next card - size_t card = gcard_of ((uint8_t*)rover); - - Interlocked::Or (&g_gc_card_table[card/card_word_width], (1U << (card % card_word_width))); - // Skip to next card for the object - rover = (Object**)align_on_card ((uint8_t*)(rover+1)); - } - else - { - rover++; - } - } -} - -#if defined(_MSC_VER) && defined(_TARGET_X86_) -#pragma optimize("", on) // Go back to command line default optimizations -#endif //_MSC_VER && _TARGET_X86_ - - #ifdef FEATURE_PREMORTEM_FINALIZATION //-------------------------------------------------------------------- @@ -36304,7 +36236,7 @@ CFinalize::ScanForFinalization (promote_func* pfn, int gen, BOOL mark_only_p, if (hp->settings.concurrent && hp->settings.found_finalizers) { if (!mark_only_p) - FinalizerThread::EnableFinalization(); + GCToEEInterface::EnableFinalization(true); } } @@ -36560,11 +36492,13 @@ void GCHeap::DiagScanFinalizeQueue (fq_scan_fn fn, ScanContext* sc) void GCHeap::DiagScanHandles (handle_scan_fn fn, int gen_number, ScanContext* context) { + UNREFERENCED_PARAMETER(gen_number); GCScan::GcScanHandlesForProfilerAndETW (max_generation, context, fn); } void GCHeap::DiagScanDependentHandles (handle_scan_fn fn, int gen_number, ScanContext* context) { + UNREFERENCED_PARAMETER(gen_number); GCScan::GcScanDependentHandlesForProfilerAndETW (max_generation, context, fn); } |