summaryrefslogtreecommitdiff
path: root/src/gc/gcpriv.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/gc/gcpriv.h')
-rw-r--r--src/gc/gcpriv.h271
1 files changed, 130 insertions, 141 deletions
diff --git a/src/gc/gcpriv.h b/src/gc/gcpriv.h
index 1f97d7f2d5..108045cd37 100644
--- a/src/gc/gcpriv.h
+++ b/src/gc/gcpriv.h
@@ -28,7 +28,7 @@ inline void FATAL_GC_ERROR()
GCToOSInterface::DebugBreak();
#endif // DACCESS_COMPILE
_ASSERTE(!"Fatal Error in GC.");
- EEPOLICY_HANDLE_FATAL_ERROR(COR_E_EXECUTIONENGINE);
+ GCToEEInterface::HandleFatalError(COR_E_EXECUTIONENGINE);
}
#ifdef _MSC_VER
@@ -167,8 +167,6 @@ void GCLogConfig (const char *fmt, ... );
#define TRACE_GC
#endif
-#define NUMBERGENERATIONS 4 //Max number of generations
-
// For the bestfit algorithm when we relocate ephemeral generations into an
// existing gen2 segment.
// We recorded sizes from 2^6, 2^7, 2^8...up to 2^30 (1GB). So that's 25 sizes total.
@@ -759,10 +757,10 @@ public:
// Don't move these first two fields without adjusting the references
// from the __asm in jitinterface.cpp.
alloc_context allocation_context;
- heap_segment* allocation_segment;
PTR_heap_segment start_segment;
- uint8_t* allocation_context_start_region;
uint8_t* allocation_start;
+ heap_segment* allocation_segment;
+ uint8_t* allocation_context_start_region;
allocator free_list_allocator;
size_t free_list_allocated;
size_t end_seg_allocated;
@@ -792,6 +790,11 @@ public:
#endif //FREE_USAGE_STATS
};
+static_assert(offsetof(dac_generation, allocation_context) == offsetof(generation, allocation_context), "DAC generation offset mismatch");
+static_assert(offsetof(dac_generation, start_segment) == offsetof(generation, start_segment), "DAC generation offset mismatch");
+static_assert(offsetof(dac_generation, allocation_start) == offsetof(generation, allocation_start), "DAC generation offset mismatch");
+
+
// The dynamic data fields are grouped into 3 categories:
//
// calculated logical data (like desired_allocation)
@@ -1104,6 +1107,8 @@ class gc_heap
friend void initGCShadow();
#endif //defined (WRITE_BARRIER_CHECK) && !defined (SERVER_GC)
+ friend void PopulateDacVars(GcDacVars *gcDacVars);
+
#ifdef MULTIPLE_HEAPS
typedef void (gc_heap::* card_fn) (uint8_t**, int);
#define call_fn(fn) (this->*fn)
@@ -1293,19 +1298,19 @@ protected:
uint8_t* last_plug;
BOOL is_shortened;
mark* pinned_plug_entry;
- size_t profiling_context;
+ void* profiling_context;
record_surv_fn fn;
};
PER_HEAP
- void walk_survivors (record_surv_fn fn, size_t context, walk_surv_type type);
+ void walk_survivors (record_surv_fn fn, void* context, walk_surv_type type);
PER_HEAP
void walk_plug (uint8_t* plug, size_t size, BOOL check_last_object_p,
walk_relocate_args* args);
PER_HEAP
- void walk_relocation (size_t profiling_context, record_surv_fn fn);
+ void walk_relocation (void* profiling_context, record_surv_fn fn);
PER_HEAP
void walk_relocation_in_brick (uint8_t* tree, walk_relocate_args* args);
@@ -1315,14 +1320,14 @@ protected:
#if defined(BACKGROUND_GC) && defined(FEATURE_EVENT_TRACE)
PER_HEAP
- void walk_survivors_for_bgc (size_t profiling_context, record_surv_fn fn);
+ void walk_survivors_for_bgc (void* profiling_context, record_surv_fn fn);
#endif // defined(BACKGROUND_GC) && defined(FEATURE_EVENT_TRACE)
// used in blocking GCs after plan phase so this walks the plugs.
PER_HEAP
- void walk_survivors_relocation (size_t profiling_context, record_surv_fn fn);
+ void walk_survivors_relocation (void* profiling_context, record_surv_fn fn);
PER_HEAP
- void walk_survivors_for_loh (size_t profiling_context, record_surv_fn fn);
+ void walk_survivors_for_loh (void* profiling_context, record_surv_fn fn);
PER_HEAP
int generation_to_condemn (int n,
@@ -1390,6 +1395,9 @@ protected:
void thread_no_gc_loh_segments();
PER_HEAP
+ void check_and_set_no_gc_oom();
+
+ PER_HEAP
void allocate_for_no_gc_after_gc();
PER_HEAP
@@ -1550,13 +1558,6 @@ protected:
alloc_context* acontext,
int align_const);
- enum c_gc_state
- {
- c_gc_state_marking,
- c_gc_state_planning,
- c_gc_state_free
- };
-
#ifdef RECORD_LOH_STATE
#define max_saved_loh_states 12
PER_HEAP
@@ -1718,8 +1719,14 @@ protected:
PER_HEAP
void card_bundle_clear(size_t cardb);
PER_HEAP
+ void card_bundle_set (size_t cardb);
+ PER_HEAP
void card_bundles_set (size_t start_cardb, size_t end_cardb);
PER_HEAP
+ void verify_card_bundle_bits_set(size_t first_card_word, size_t last_card_word);
+ PER_HEAP
+ void verify_card_bundles();
+ PER_HEAP
BOOL card_bundle_set_p (size_t cardb);
PER_HEAP
BOOL find_card_dword (size_t& cardw, size_t cardw_end);
@@ -2161,7 +2168,7 @@ protected:
void relocate_in_loh_compact();
PER_HEAP
- void walk_relocation_for_loh (size_t profiling_context, record_surv_fn fn);
+ void walk_relocation_for_loh (void* profiling_context, record_surv_fn fn);
PER_HEAP
BOOL loh_enque_pinned_plug (uint8_t* plug, size_t len);
@@ -2753,9 +2760,6 @@ public:
PER_HEAP_ISOLATED
uint32_t cm_in_progress;
- PER_HEAP
- BOOL expanded_in_fgc;
-
// normally this is FALSE; we set it to TRUE at the end of the gen1 GC
// we do right before the bgc starts.
PER_HEAP_ISOLATED
@@ -2765,6 +2769,56 @@ public:
CLREvent bgc_start_event;
#endif //BACKGROUND_GC
+ // The variables in this block are known to the DAC and must come first
+ // in the gc_heap class.
+
+ // Keeps track of the highest address allocated by Alloc
+ PER_HEAP
+ uint8_t* alloc_allocated;
+
+ // The ephemeral heap segment
+ PER_HEAP
+ heap_segment* ephemeral_heap_segment;
+
+ // The finalize queue.
+ PER_HEAP
+ CFinalize* finalize_queue;
+
+ // OOM info.
+ PER_HEAP
+ oom_history oom_info;
+
+ // Interesting data, recorded per-heap.
+ PER_HEAP
+ size_t interesting_data_per_heap[max_idp_count];
+
+ PER_HEAP
+ size_t compact_reasons_per_heap[max_compact_reasons_count];
+
+ PER_HEAP
+ size_t expand_mechanisms_per_heap[max_expand_mechanisms_count];
+
+ PER_HEAP
+ size_t interesting_mechanism_bits_per_heap[max_gc_mechanism_bits_count];
+
+ PER_HEAP
+ uint8_t** internal_root_array;
+
+ PER_HEAP
+ size_t internal_root_array_index;
+
+ PER_HEAP
+ BOOL heap_analyze_success;
+
+ // The generation table. Must always be last.
+ PER_HEAP
+ generation generation_table [NUMBERGENERATIONS + 1];
+
+ // End DAC zone
+
+ PER_HEAP
+ BOOL expanded_in_fgc;
+
PER_HEAP_ISOLATED
uint32_t wait_for_gc_done(int32_t timeOut = INFINITE);
@@ -2815,12 +2869,8 @@ public:
short* brick_table;
#ifdef MARK_ARRAY
-#ifdef MULTIPLE_HEAPS
PER_HEAP
uint32_t* mark_array;
-#else
- SPTR_DECL(uint32_t, mark_array);
-#endif //MULTIPLE_HEAPS
#endif //MARK_ARRAY
#ifdef CARD_BUNDLE
@@ -2984,13 +3034,6 @@ protected:
#define heap_number (0)
#endif //MULTIPLE_HEAPS
-#ifndef MULTIPLE_HEAPS
- SPTR_DECL(heap_segment,ephemeral_heap_segment);
-#else
- PER_HEAP
- heap_segment* ephemeral_heap_segment;
-#endif // !MULTIPLE_HEAPS
-
PER_HEAP
size_t time_bgc_last;
@@ -3065,14 +3108,9 @@ protected:
uint8_t* background_written_addresses [array_size+2];
#endif //WRITE_WATCH
-#if defined (DACCESS_COMPILE) && !defined (MULTIPLE_HEAPS)
- // doesn't need to be volatile for DAC.
- SVAL_DECL(c_gc_state, current_c_gc_state);
-#else
PER_HEAP_ISOLATED
VOLATILE(c_gc_state) current_c_gc_state; //tells the large object allocator to
//mark the object as new since the start of gc.
-#endif //DACCESS_COMPILE && !MULTIPLE_HEAPS
PER_HEAP_ISOLATED
gc_mechanisms saved_bgc_settings;
@@ -3229,16 +3267,6 @@ protected:
PER_HEAP
heap_segment* saved_overflow_ephemeral_seg;
-#ifndef MULTIPLE_HEAPS
- SPTR_DECL(heap_segment, saved_sweep_ephemeral_seg);
-
- SPTR_DECL(uint8_t, saved_sweep_ephemeral_start);
-
- SPTR_DECL(uint8_t, background_saved_lowest_address);
-
- SPTR_DECL(uint8_t, background_saved_highest_address);
-#else
-
PER_HEAP
heap_segment* saved_sweep_ephemeral_seg;
@@ -3250,7 +3278,6 @@ protected:
PER_HEAP
uint8_t* background_saved_highest_address;
-#endif //!MULTIPLE_HEAPS
// This is used for synchronization between the bgc thread
// for this heap and the user threads allocating on this
@@ -3326,6 +3353,9 @@ protected:
size_t loh_allocation_no_gc;
PER_HEAP
+ bool no_gc_oom_p;
+
+ PER_HEAP
heap_segment* saved_loh_segment_no_gc;
PER_HEAP_ISOLATED
@@ -3334,14 +3364,6 @@ protected:
#define youngest_generation (generation_of (0))
#define large_object_generation (generation_of (max_generation+1))
-#ifndef MULTIPLE_HEAPS
- SPTR_DECL(uint8_t,alloc_allocated);
-#else
- PER_HEAP
- uint8_t* alloc_allocated; //keeps track of the highest
- //address allocated by alloc
-#endif // !MULTIPLE_HEAPS
-
// The more_space_lock and gc_lock is used for 3 purposes:
//
// 1) to coordinate threads that exceed their quantum (UP & MP) (more_space_lock)
@@ -3411,12 +3433,6 @@ protected:
#endif //SYNCHRONIZATION_STATS
-#ifdef MULTIPLE_HEAPS
- PER_HEAP
- generation generation_table [NUMBERGENERATIONS+1];
-#endif
-
-
#define NUM_LOH_ALIST (7)
#define BASE_LOH_ALIST (64*1024)
PER_HEAP
@@ -3493,34 +3509,14 @@ protected:
PER_HEAP_ISOLATED
BOOL alloc_wait_event_p;
-#ifndef MULTIPLE_HEAPS
- SPTR_DECL(uint8_t, next_sweep_obj);
-#else
PER_HEAP
uint8_t* next_sweep_obj;
-#endif //MULTIPLE_HEAPS
PER_HEAP
uint8_t* current_sweep_pos;
#endif //BACKGROUND_GC
-#ifndef MULTIPLE_HEAPS
- SVAL_DECL(oom_history, oom_info);
-#ifdef FEATURE_PREMORTEM_FINALIZATION
- SPTR_DECL(CFinalize,finalize_queue);
-#endif //FEATURE_PREMORTEM_FINALIZATION
-#else
-
- PER_HEAP
- oom_history oom_info;
-
-#ifdef FEATURE_PREMORTEM_FINALIZATION
- PER_HEAP
- PTR_CFinalize finalize_queue;
-#endif //FEATURE_PREMORTEM_FINALIZATION
-#endif // !MULTIPLE_HEAPS
-
PER_HEAP
fgm_history fgm_result;
@@ -3542,19 +3538,6 @@ protected:
PER_HEAP
size_t interesting_data_per_gc[max_idp_count];
-#ifdef MULTIPLE_HEAPS
- PER_HEAP
- size_t interesting_data_per_heap[max_idp_count];
-
- PER_HEAP
- size_t compact_reasons_per_heap[max_compact_reasons_count];
-
- PER_HEAP
- size_t expand_mechanisms_per_heap[max_expand_mechanisms_count];
-
- PER_HEAP
- size_t interesting_mechanism_bits_per_heap[max_gc_mechanism_bits_count];
-#endif //MULTIPLE_HEAPS
#endif //GC_CONFIG_DRIVEN
PER_HEAP
@@ -3635,21 +3618,6 @@ public:
PER_HEAP
size_t internal_root_array_length;
-#ifndef MULTIPLE_HEAPS
- SPTR_DECL(PTR_uint8_t, internal_root_array);
- SVAL_DECL(size_t, internal_root_array_index);
- SVAL_DECL(BOOL, heap_analyze_success);
-#else
- PER_HEAP
- uint8_t** internal_root_array;
-
- PER_HEAP
- size_t internal_root_array_index;
-
- PER_HEAP
- BOOL heap_analyze_success;
-#endif // !MULTIPLE_HEAPS
-
// next two fields are used to optimize the search for the object
// enclosing the current reference handled by ha_mark_object_simple.
PER_HEAP
@@ -3670,8 +3638,11 @@ public:
BOOL blocking_collection;
#ifdef MULTIPLE_HEAPS
- SVAL_DECL(int, n_heaps);
- SPTR_DECL(PTR_gc_heap, g_heaps);
+ static
+ int n_heaps;
+
+ static
+ gc_heap** g_heaps;
static
size_t* g_promoted;
@@ -3705,6 +3676,23 @@ protected:
}; // class gc_heap
+#define ASSERT_OFFSETS_MATCH(field) \
+ static_assert_no_msg(offsetof(dac_gc_heap, field) == offsetof(gc_heap, field))
+
+#ifdef MULTIPLE_HEAPS
+ASSERT_OFFSETS_MATCH(alloc_allocated);
+ASSERT_OFFSETS_MATCH(ephemeral_heap_segment);
+ASSERT_OFFSETS_MATCH(finalize_queue);
+ASSERT_OFFSETS_MATCH(oom_info);
+ASSERT_OFFSETS_MATCH(interesting_data_per_heap);
+ASSERT_OFFSETS_MATCH(compact_reasons_per_heap);
+ASSERT_OFFSETS_MATCH(expand_mechanisms_per_heap);
+ASSERT_OFFSETS_MATCH(interesting_mechanism_bits_per_heap);
+ASSERT_OFFSETS_MATCH(internal_root_array);
+ASSERT_OFFSETS_MATCH(internal_root_array_index);
+ASSERT_OFFSETS_MATCH(heap_analyze_success);
+ASSERT_OFFSETS_MATCH(generation_table);
+#endif // MULTIPLE_HEAPS
#ifdef FEATURE_PREMORTEM_FINALIZATION
class CFinalize
@@ -3712,6 +3700,9 @@ class CFinalize
#ifdef DACCESS_COMPILE
friend class ::ClrDataAccess;
#endif // DACCESS_COMPILE
+
+ friend class CFinalizeStaticAsserts;
+
private:
//adjust the count and add a constant to add a segment
@@ -3721,8 +3712,8 @@ private:
//Does not correspond to a segment
static const int FreeList = NUMBERGENERATIONS+ExtraSegCount;
- PTR_PTR_Object m_Array;
PTR_PTR_Object m_FillPointers[NUMBERGENERATIONS+ExtraSegCount];
+ PTR_PTR_Object m_Array;
PTR_PTR_Object m_EndArray;
size_t m_PromotedCount;
@@ -3776,10 +3767,18 @@ public:
void DiscardNonCriticalObjects();
//Methods used by the app domain unloading call to finalize objects in an app domain
- BOOL FinalizeAppDomain (AppDomain *pDomain, BOOL fRunFinalizers);
+ bool FinalizeAppDomain (AppDomain *pDomain, bool fRunFinalizers);
void CheckFinalizerObjects();
+
};
+
+class CFinalizeStaticAsserts {
+ static_assert(dac_finalize_queue::ExtraSegCount == CFinalize::ExtraSegCount, "ExtraSegCount mismatch");
+ static_assert(offsetof(dac_finalize_queue, m_FillPointers) == offsetof(CFinalize, m_FillPointers), "CFinalize layout mismatch");
+};
+
+
#endif // FEATURE_PREMORTEM_FINALIZATION
inline
@@ -4171,15 +4170,12 @@ public:
uint8_t* mem;
size_t flags;
PTR_heap_segment next;
- uint8_t* plan_allocated;
-#ifdef BACKGROUND_GC
uint8_t* background_allocated;
- uint8_t* saved_bg_allocated;
-#endif //BACKGROUND_GC
-
#ifdef MULTIPLE_HEAPS
gc_heap* heap;
#endif //MULTIPLE_HEAPS
+ uint8_t* plan_allocated;
+ uint8_t* saved_bg_allocated;
#ifdef _MSC_VER
// Disable this warning - we intentionally want __declspec(align()) to insert padding for us
@@ -4191,6 +4187,18 @@ public:
#endif
};
+static_assert(offsetof(dac_heap_segment, allocated) == offsetof(heap_segment, allocated), "DAC heap segment layout mismatch");
+static_assert(offsetof(dac_heap_segment, committed) == offsetof(heap_segment, committed), "DAC heap segment layout mismatch");
+static_assert(offsetof(dac_heap_segment, reserved) == offsetof(heap_segment, reserved), "DAC heap segment layout mismatch");
+static_assert(offsetof(dac_heap_segment, used) == offsetof(heap_segment, used), "DAC heap segment layout mismatch");
+static_assert(offsetof(dac_heap_segment, mem) == offsetof(heap_segment, mem), "DAC heap segment layout mismatch");
+static_assert(offsetof(dac_heap_segment, flags) == offsetof(heap_segment, flags), "DAC heap segment layout mismatch");
+static_assert(offsetof(dac_heap_segment, next) == offsetof(heap_segment, next), "DAC heap segment layout mismatch");
+static_assert(offsetof(dac_heap_segment, background_allocated) == offsetof(heap_segment, background_allocated), "DAC heap segment layout mismatch");
+#ifdef MULTIPLE_HEAPS
+static_assert(offsetof(dac_heap_segment, heap) == offsetof(heap_segment, heap), "DAC heap segment layout mismatch");
+#endif // MULTIPLE_HEAPS
+
inline
uint8_t*& heap_segment_reserved (heap_segment* inst)
{
@@ -4283,27 +4291,6 @@ gc_heap*& heap_segment_heap (heap_segment* inst)
}
#endif //MULTIPLE_HEAPS
-#ifndef MULTIPLE_HEAPS
-
-#ifndef DACCESS_COMPILE
-extern "C" {
-#endif //!DACCESS_COMPILE
-
-GARY_DECL(generation,generation_table,NUMBERGENERATIONS+1);
-
-#ifdef GC_CONFIG_DRIVEN
-GARY_DECL(size_t, interesting_data_per_heap, max_idp_count);
-GARY_DECL(size_t, compact_reasons_per_heap, max_compact_reasons_count);
-GARY_DECL(size_t, expand_mechanisms_per_heap, max_expand_mechanisms_count);
-GARY_DECL(size_t, interesting_mechanism_bits_per_heap, max_gc_mechanism_bits_count);
-#endif //GC_CONFIG_DRIVEN
-
-#ifndef DACCESS_COMPILE
-}
-#endif //!DACCESS_COMPILE
-
-#endif //MULTIPLE_HEAPS
-
inline
generation* gc_heap::generation_of (int n)
{
@@ -4329,12 +4316,14 @@ dynamic_data* gc_heap::dynamic_data_of (int gen_number)
#define card_size ((size_t)(OS_PAGE_SIZE/card_word_width))
#endif // BIT64
+// Returns the index of the card word a card is in
inline
size_t card_word (size_t card)
{
return card / card_word_width;
}
+// Returns the index of a card within its card word
inline
unsigned card_bit (size_t card)
{