diff options
Diffstat (limited to 'src/coreclr/gc')
-rw-r--r-- | src/coreclr/gc/gc.cpp | 89 |
1 files changed, 63 insertions, 26 deletions
diff --git a/src/coreclr/gc/gc.cpp b/src/coreclr/gc/gc.cpp index c7f2b177f52..7db0faacc26 100644 --- a/src/coreclr/gc/gc.cpp +++ b/src/coreclr/gc/gc.cpp @@ -4165,7 +4165,16 @@ size_t gcard_of ( uint8_t*); // We only do this when we decide to compact. #define BGC_MARKED_BY_FGC (size_t)0x2 #define MAKE_FREE_OBJ_IN_COMPACT (size_t)0x4 -#endif //DOUBLY_LINKED_FL +#define ALLOWED_SPECIAL_HEADER_BITS (GC_MARKED|BGC_MARKED_BY_FGC|MAKE_FREE_OBJ_IN_COMPACT) +#else //DOUBLY_LINKED_FL +#define ALLOWED_SPECIAL_HEADER_BITS (GC_MARKED) +#endif //!DOUBLY_LINKED_FL + +#ifdef HOST_64BIT +#define SPECIAL_HEADER_BITS (0x7) +#else +#define SPECIAL_HEADER_BITS (0x3) +#endif #define slot(i, j) ((uint8_t**)(i))[(j)+1] @@ -4267,11 +4276,7 @@ public: MethodTable *GetMethodTable() const { - return( (MethodTable *) (((size_t) RawGetMethodTable()) & (~(GC_MARKED -#ifdef DOUBLY_LINKED_FL - | BGC_MARKED_BY_FGC | MAKE_FREE_OBJ_IN_COMPACT -#endif //DOUBLY_LINKED_FL - )))); + return( (MethodTable *) (((size_t) RawGetMethodTable()) & (~SPECIAL_HEADER_BITS))); } void SetMarked() @@ -4339,6 +4344,26 @@ public: } #endif //DOUBLY_LINKED_FL + size_t ClearSpecialBits() + { + size_t special_bits = ((size_t)RawGetMethodTable()) & SPECIAL_HEADER_BITS; + if (special_bits != 0) + { + assert ((special_bits & (~ALLOWED_SPECIAL_HEADER_BITS)) == 0); + RawSetMethodTable ((MethodTable*)(((size_t)RawGetMethodTable()) & ~(SPECIAL_HEADER_BITS))); + } + return special_bits; + } + + void SetSpecialBits (size_t special_bits) + { + assert ((special_bits & (~ALLOWED_SPECIAL_HEADER_BITS)) == 0); + if (special_bits != 0) + { + RawSetMethodTable ((MethodTable*)(((size_t)RawGetMethodTable()) | special_bits)); + } + } + CGCDesc *GetSlotMap () { assert (GetMethodTable()->ContainsPointers()); @@ -4506,6 +4531,17 @@ inline BOOL is_plug_padded (uint8_t* node){return FALSE;} #endif //SHORT_PLUGS +inline +size_t clear_special_bits (uint8_t* node) +{ + return header(node)->ClearSpecialBits(); +} + +inline +void set_special_bits (uint8_t* node, size_t special_bits) +{ + header(node)->SetSpecialBits (special_bits); +} inline size_t unused_array_size(uint8_t * p) { @@ -20978,16 +21014,16 @@ void gc_heap::enque_pinned_plug (uint8_t* plug, if (save_pre_plug_info_p) { -#ifdef SHORT_PLUGS - BOOL is_padded = is_plug_padded (last_object_in_last_plug); - if (is_padded) - clear_plug_padded (last_object_in_last_plug); -#endif //SHORT_PLUGS + // In the case of short plugs or doubly linked free lists, there may be extra bits + // set in the method table pointer. + // Clear these bits for the copy saved in saved_pre_plug, but not for the copy + // saved in saved_pre_plug_reloc. + // This is because we need these bits for compaction, but not for mark & sweep. + size_t special_bits = clear_special_bits (last_object_in_last_plug); + // now copy the bits over memcpy (&(m.saved_pre_plug), &(((plug_and_gap*)plug)[-1]), sizeof (gap_reloc_pair)); -#ifdef SHORT_PLUGS - if (is_padded) - set_plug_padded (last_object_in_last_plug); -#endif //SHORT_PLUGS + // restore the bits in the original + set_special_bits (last_object_in_last_plug, special_bits); memcpy (&(m.saved_pre_plug_reloc), &(((plug_and_gap*)plug)[-1]), sizeof (gap_reloc_pair)); @@ -20997,7 +21033,7 @@ void gc_heap::enque_pinned_plug (uint8_t* plug, { record_interesting_data_point (idp_pre_short); #ifdef SHORT_PLUGS - if (is_padded) + if (is_plug_padded (last_object_in_last_plug)) record_interesting_data_point (idp_pre_short_padded); #endif //SHORT_PLUGS dprintf (3, ("encountered a short object %Ix right before pinned plug %Ix!", @@ -21041,16 +21077,17 @@ void gc_heap::save_post_plug_info (uint8_t* last_pinned_plug, uint8_t* last_obje assert (last_pinned_plug == m.first); m.saved_post_plug_info_start = (uint8_t*)&(((plug_and_gap*)post_plug)[-1]); -#ifdef SHORT_PLUGS - BOOL is_padded = is_plug_padded (last_object_in_last_plug); - if (is_padded) - clear_plug_padded (last_object_in_last_plug); -#endif //SHORT_PLUGS + // In the case of short plugs or doubly linked free lists, there may be extra bits + // set in the method table pointer. + // Clear these bits for the copy saved in saved_post_plug, but not for the copy + // saved in saved_post_plug_reloc. + // This is because we need these bits for compaction, but not for mark & sweep. + // Note that currently none of these bits will ever be set in the object saved *after* + // a pinned plug - this object is currently pinned along with the pinned object before it + size_t special_bits = clear_special_bits (last_object_in_last_plug); memcpy (&(m.saved_post_plug), m.saved_post_plug_info_start, sizeof (gap_reloc_pair)); -#ifdef SHORT_PLUGS - if (is_padded) - set_plug_padded (last_object_in_last_plug); -#endif //SHORT_PLUGS + // restore the bits in the original + set_special_bits (last_object_in_last_plug, special_bits); memcpy (&(m.saved_post_plug_reloc), m.saved_post_plug_info_start, sizeof (gap_reloc_pair)); @@ -21069,7 +21106,7 @@ void gc_heap::save_post_plug_info (uint8_t* last_pinned_plug, uint8_t* last_obje dprintf (3, ("PP %Ix last obj %Ix is too short", last_pinned_plug, last_object_in_last_plug)); record_interesting_data_point (idp_post_short); #ifdef SHORT_PLUGS - if (is_padded) + if (is_plug_padded (last_object_in_last_plug)) record_interesting_data_point (idp_post_short_padded); #endif //SHORT_PLUGS m.set_post_short(); |