[sgen] Put major_scan_object() into the major collectors.
authorMark Probst <mark.probst@gmail.com>
Tue, 27 Jul 2010 21:20:54 +0000 (23:20 +0200)
committerMark Probst <mark.probst@gmail.com>
Wed, 4 Aug 2010 01:56:09 +0000 (03:56 +0200)
Make the major collectors define their own versions of
major_scan_object() by including a small header file.  This
avoids indirect calls to major_copy_or_mark_object() and
allows inlining.

mono/metadata/sgen-gc.c
mono/metadata/sgen-gc.h
mono/metadata/sgen-major-copying.c
mono/metadata/sgen-major-scan-object.h [new file with mode: 0644]
mono/metadata/sgen-marksweep.c
mono/metadata/sgen-scan-object.h

index 587c2237be2851be2117b24d1c09fe6eb76487e9..a2a10c71baaa7ae150070c93da3543b1bb7b3993 100644 (file)
@@ -266,7 +266,7 @@ static long long stat_copy_object_called_major = 0;
 static long long stat_objects_copied_major = 0;
 
 static long long stat_scan_object_called_nursery = 0;
-static long long stat_scan_object_called_major = 0;
+long long stat_scan_object_called_major = 0;
 
 static long long stat_nursery_copy_object_failed_from_space = 0;
 static long long stat_nursery_copy_object_failed_forwarded = 0;
@@ -344,8 +344,6 @@ mono_gc_flush_info (void)
 
 #define ALIGN_TO(val,align) ((((guint64)val) + ((align) - 1)) & ~((align) - 1))
 
-#define GC_BITS_PER_WORD (sizeof (mword) * 8)
-
 /* The method used to clear the nursery */
 /* Clearing at nursery collections is the safest, but has bad interactions with caches.
  * Clearing at TLAB creation is much faster, but more complex and it might expose hard
@@ -435,14 +433,6 @@ static gpointer global_remset_cache [2];
 #define DEFAULT_REMSET_SIZE 1024
 static RememberedSet* alloc_remset (int size, gpointer id);
 
-/* Structure that corresponds to a MonoVTable: desc is a mword so requires
- * no cast from a pointer to an integer
- */
-typedef struct {
-       MonoClass *klass;
-       mword desc;
-} GCVTable;
-
 #define object_is_forwarded    SGEN_OBJECT_IS_FORWARDED
 /* set the forwarded address fw_addr for object obj */
 #define forward_object(obj,fw_addr) do {                               \
@@ -770,7 +760,6 @@ typedef char* (*ScanObjectFunc) (char*, GrayQueue*);
 /* forward declarations */
 static int stop_world (void);
 static int restart_world (void);
-static void add_to_global_remset (gpointer ptr);
 static void scan_thread_data (void *start_nursery, void *end_nursery, gboolean precise);
 static void scan_from_remsets (void *start_nursery, void *end_nursery, GrayQueue *queue);
 static void scan_from_registered_roots (CopyOrMarkObjectFunc copy_func, char *addr_start, char *addr_end, int root_type, GrayQueue *queue);
@@ -790,7 +779,6 @@ static void optimize_pin_queue (int start_slot);
 static void clear_remsets (void);
 static void clear_tlabs (void);
 static void scan_object (char *start, GrayQueue *queue);
-static void major_scan_object (char *start, GrayQueue *queue);
 static void copy_object (void **obj_slot, GrayQueue *queue);
 static void sort_addresses (void **array, int size);
 static void drain_gray_stack (GrayQueue *queue);
@@ -825,27 +813,6 @@ SgenMajorCollector major;
 #include "sgen-gray.c"
 #include "sgen-los.c"
 
-/*
- * ######################################################################
- * ########  GC descriptors
- * ######################################################################
- * Used to quickly get the info the GC needs about an object: size and
- * where the references are held.
- */
-#define OBJECT_HEADER_WORDS (sizeof(MonoObject)/sizeof(gpointer))
-#define LOW_TYPE_BITS 3
-#define SMALL_BITMAP_SHIFT 16
-#define SMALL_BITMAP_SIZE (GC_BITS_PER_WORD - SMALL_BITMAP_SHIFT)
-#define VECTOR_INFO_SHIFT 14
-#define VECTOR_ELSIZE_SHIFT 3
-#define LARGE_BITMAP_SIZE (GC_BITS_PER_WORD - LOW_TYPE_BITS)
-#define MAX_ELEMENT_SIZE 0x3ff
-#define VECTOR_SUBTYPE_PTRFREE (DESC_TYPE_V_PTRFREE << VECTOR_INFO_SHIFT)
-#define VECTOR_SUBTYPE_REFS    (DESC_TYPE_V_REFS << VECTOR_INFO_SHIFT)
-#define VECTOR_SUBTYPE_RUN_LEN (DESC_TYPE_V_RUN_LEN << VECTOR_INFO_SHIFT)
-#define VECTOR_SUBTYPE_BITMAP  (DESC_TYPE_V_BITMAP << VECTOR_INFO_SHIFT)
-
-
 /* Root bitmap descriptors are simpler: the lower three bits describe the type
  * and we either have 30/62 bitmap bits or nibble-based run-length,
  * or a complex descriptor, or a user defined marker function.
@@ -916,6 +883,12 @@ alloc_complex_descriptor (gsize *bitmap, int numbits)
        return res;
 }
 
+gsize*
+mono_sgen_get_complex_descriptor (GCVTable *vt)
+{
+       return complex_descriptors + (vt->desc >> LOW_TYPE_BITS);
+}
+
 /*
  * Descriptor builders.
  */
@@ -1056,169 +1029,6 @@ mono_gc_get_bitmap_for_descr (void *descr, int *numbits)
        }
 }
 
-/* helper macros to scan and traverse objects, macros because we resue them in many functions */
-#define OBJ_RUN_LEN_SIZE(size,desc,obj) do { \
-               (size) = ((desc) & 0xfff8) >> 1;        \
-    } while (0)
-
-#define OBJ_BITMAP_SIZE(size,desc,obj) do { \
-               (size) = ((desc) & 0xfff8) >> 1;        \
-    } while (0)
-
-//#define PREFETCH(addr) __asm__ __volatile__ ("     prefetchnta     %0": : "m"(*(char *)(addr)))
-#define PREFETCH(addr)
-
-/* code using these macros must define a HANDLE_PTR(ptr) macro that does the work */
-#define OBJ_RUN_LEN_FOREACH_PTR(desc,obj)      do {    \
-               if ((desc) & 0xffff0000) {      \
-                       /* there are pointers */        \
-                       void **_objptr_end;     \
-                       void **_objptr = (void**)(obj); \
-                       _objptr += ((desc) >> 16) & 0xff;       \
-                       _objptr_end = _objptr + (((desc) >> 24) & 0xff);        \
-                       while (_objptr < _objptr_end) { \
-                               HANDLE_PTR (_objptr, (obj));    \
-                               _objptr++;      \
-                       }       \
-               }       \
-       } while (0)
-
-/* a bitmap desc means that there are pointer references or we'd have
- * choosen run-length, instead: add an assert to check.
- */
-#define OBJ_BITMAP_FOREACH_PTR(desc,obj)       do {    \
-               /* there are pointers */        \
-               void **_objptr = (void**)(obj); \
-               gsize _bmap = (desc) >> 16;     \
-               _objptr += OBJECT_HEADER_WORDS; \
-               while (_bmap) { \
-                       if ((_bmap & 1)) {      \
-                               HANDLE_PTR (_objptr, (obj));    \
-                       }       \
-                       _bmap >>= 1;    \
-                       ++_objptr;      \
-               }       \
-       } while (0)
-
-#define OBJ_LARGE_BITMAP_FOREACH_PTR(vt,obj)   do {    \
-               /* there are pointers */        \
-               void **_objptr = (void**)(obj); \
-               gsize _bmap = (vt)->desc >> LOW_TYPE_BITS;      \
-               _objptr += OBJECT_HEADER_WORDS; \
-               while (_bmap) { \
-                       if ((_bmap & 1)) {      \
-                               HANDLE_PTR (_objptr, (obj));    \
-                       }       \
-                       _bmap >>= 1;    \
-                       ++_objptr;      \
-               }       \
-       } while (0)
-
-#define OBJ_COMPLEX_FOREACH_PTR(vt,obj)        do {    \
-               /* there are pointers */        \
-               void **_objptr = (void**)(obj); \
-               gsize *bitmap_data = complex_descriptors + ((vt)->desc >> LOW_TYPE_BITS);       \
-               int bwords = (*bitmap_data) - 1;        \
-               void **start_run = _objptr;     \
-               bitmap_data++;  \
-               if (0) {        \
-                       MonoObject *myobj = (MonoObject*)obj;   \
-                       g_print ("found %d at %p (0x%zx): %s.%s\n", bwords, (obj), (vt)->desc, myobj->vtable->klass->name_space, myobj->vtable->klass->name);   \
-               }       \
-               while (bwords-- > 0) {  \
-                       gsize _bmap = *bitmap_data++;   \
-                       _objptr = start_run;    \
-                       /*g_print ("bitmap: 0x%x/%d at %p\n", _bmap, bwords, _objptr);*/        \
-                       while (_bmap) { \
-                               if ((_bmap & 1)) {      \
-                                       HANDLE_PTR (_objptr, (obj));    \
-                               }       \
-                               _bmap >>= 1;    \
-                               ++_objptr;      \
-                       }       \
-                       start_run += GC_BITS_PER_WORD;  \
-               }       \
-       } while (0)
-
-/* this one is untested */
-#define OBJ_COMPLEX_ARR_FOREACH_PTR(vt,obj)    do {    \
-               /* there are pointers */        \
-               gsize *mbitmap_data = complex_descriptors + ((vt)->desc >> LOW_TYPE_BITS);      \
-               int mbwords = (*mbitmap_data++) - 1;    \
-               int el_size = mono_array_element_size (vt->klass);      \
-               char *e_start = (char*)(obj) +  G_STRUCT_OFFSET (MonoArray, vector);    \
-               char *e_end = e_start + el_size * mono_array_length_fast ((MonoArray*)(obj));   \
-               if (0)                                                  \
-                        g_print ("found %d at %p (0x%zx): %s.%s\n", mbwords, (obj), (vt)->desc, vt->klass->name_space, vt->klass->name); \
-               while (e_start < e_end) {       \
-                       void **_objptr = (void**)e_start;       \
-                       gsize *bitmap_data = mbitmap_data;      \
-                       unsigned int bwords = mbwords;  \
-                       while (bwords-- > 0) {  \
-                               gsize _bmap = *bitmap_data++;   \
-                               void **start_run = _objptr;     \
-                               /*g_print ("bitmap: 0x%x\n", _bmap);*/  \
-                               while (_bmap) { \
-                                       if ((_bmap & 1)) {      \
-                                               HANDLE_PTR (_objptr, (obj));    \
-                                       }       \
-                                       _bmap >>= 1;    \
-                                       ++_objptr;      \
-                               }       \
-                               _objptr = start_run + GC_BITS_PER_WORD; \
-                       }       \
-                       e_start += el_size;     \
-               }       \
-       } while (0)
-
-#define OBJ_VECTOR_FOREACH_PTR(vt,obj) do {    \
-               /* note: 0xffffc000 excludes DESC_TYPE_V_PTRFREE */     \
-               if ((vt)->desc & 0xffffc000) {  \
-                       int el_size = ((vt)->desc >> 3) & MAX_ELEMENT_SIZE;     \
-                       /* there are pointers */        \
-                       int etype = (vt)->desc & 0xc000;        \
-                       if (etype == (DESC_TYPE_V_REFS << 14)) {        \
-                               void **p = (void**)((char*)(obj) + G_STRUCT_OFFSET (MonoArray, vector));        \
-                               void **end_refs = (void**)((char*)p + el_size * mono_array_length_fast ((MonoArray*)(obj)));    \
-                               /* Note: this code can handle also arrays of struct with only references in them */     \
-                               while (p < end_refs) {  \
-                                       HANDLE_PTR (p, (obj));  \
-                                       ++p;    \
-                               }       \
-                       } else if (etype == DESC_TYPE_V_RUN_LEN << 14) {        \
-                               int offset = ((vt)->desc >> 16) & 0xff; \
-                               int num_refs = ((vt)->desc >> 24) & 0xff;       \
-                               char *e_start = (char*)(obj) + G_STRUCT_OFFSET (MonoArray, vector);     \
-                               char *e_end = e_start + el_size * mono_array_length_fast ((MonoArray*)(obj));   \
-                               while (e_start < e_end) {       \
-                                       void **p = (void**)e_start;     \
-                                       int i;  \
-                                       p += offset;    \
-                                       for (i = 0; i < num_refs; ++i) {        \
-                                               HANDLE_PTR (p + i, (obj));      \
-                                       }       \
-                                       e_start += el_size;     \
-                               }       \
-                       } else if (etype == DESC_TYPE_V_BITMAP << 14) { \
-                               char *e_start = (char*)(obj) +  G_STRUCT_OFFSET (MonoArray, vector);    \
-                               char *e_end = e_start + el_size * mono_array_length_fast ((MonoArray*)(obj));   \
-                               while (e_start < e_end) {       \
-                                       void **p = (void**)e_start;     \
-                                       gsize _bmap = (vt)->desc >> 16; \
-                                       /* Note: there is no object header here to skip */      \
-                                       while (_bmap) { \
-                                               if ((_bmap & 1)) {      \
-                                                       HANDLE_PTR (p, (obj));  \
-                                               }       \
-                                               _bmap >>= 1;    \
-                                               ++p;    \
-                                       }       \
-                                       e_start += el_size;     \
-                               }       \
-                       }       \
-               }       \
-       } while (0)
-
 static gboolean
 is_xdomain_ref_allowed (gpointer *ptr, char *obj, MonoDomain *domain)
 {
@@ -1743,13 +1553,13 @@ global_remset_location_was_not_added (gpointer ptr)
 }
 
 /*
- * add_to_global_remset:
+ * mono_sgen_add_to_global_remset:
  *
  *   The global remset contains locations which point into newspace after
  * a minor collection. This can happen if the objects they point to are pinned.
  */
-static void
-add_to_global_remset (gpointer ptr)
+void
+mono_sgen_add_to_global_remset (gpointer ptr)
 {
        RememberedSet *rs;
 
@@ -1937,7 +1747,7 @@ copy_object (void **obj_slot, GrayQueue *queue)
                        __copy = *(ptr);        \
                        DEBUG (9, if (__old != __copy) fprintf (gc_debug_file, "Overwrote field at %p with %p (was: %p)\n", (ptr), *(ptr), __old));     \
                        if (G_UNLIKELY (ptr_in_nursery (__copy) && !ptr_in_nursery ((ptr)))) \
-                               add_to_global_remset ((ptr));           \
+                               mono_sgen_add_to_global_remset ((ptr)); \
                }       \
        } while (0)
 
@@ -1992,27 +1802,6 @@ scan_vtype (char *start, mword desc, char* from_start, char* from_end, GrayQueue
        return NULL;
 }
 
-#undef HANDLE_PTR
-#define HANDLE_PTR(ptr,obj)    do {    \
-               void *__old = *(ptr);   \
-               void *__copy;           \
-               if (__old) {    \
-                       major.copy_or_mark_object ((ptr), queue);       \
-                       __copy = *(ptr);        \
-                       DEBUG (9, if (__old != __copy) fprintf (gc_debug_file, "Overwrote field at %p with %p (was: %p)\n", (ptr), *(ptr), __old));     \
-                       if (G_UNLIKELY (ptr_in_nursery (__copy) && !ptr_in_nursery ((ptr)))) \
-                               add_to_global_remset ((ptr));           \
-               }       \
-       } while (0)
-
-static void
-major_scan_object (char *start, GrayQueue *queue)
-{
-#include "sgen-scan-object.h"
-
-       HEAVY_STAT (++stat_scan_object_called_major);
-}
-
 /*
  * drain_gray_stack:
  *
@@ -2039,7 +1828,7 @@ drain_gray_stack (GrayQueue *queue)
                        if (!obj)
                                break;
                        DEBUG (9, fprintf (gc_debug_file, "Precise gray object scan %p (%s)\n", obj, safe_name (obj)));
-                       major_scan_object (obj, queue);
+                       major.scan_object (obj, queue);
                }
        }
 }
@@ -4133,11 +3922,11 @@ clear_unreachable_ephemerons (CopyOrMarkObjectFunc copy_func, char *start, char
                        if (was_promoted) {
                                if (ptr_in_nursery (key)) {/*key was not promoted*/
                                        DEBUG (5, fprintf (gc_debug_file, "\tAdded remset to key %p\n", key));
-                                       add_to_global_remset (&cur->key);
+                                       mono_sgen_add_to_global_remset (&cur->key);
                                }
                                if (ptr_in_nursery (cur->value)) {/*value was not promoted*/
                                        DEBUG (5, fprintf (gc_debug_file, "\tAdded remset to value %p\n", cur->value));
-                                       add_to_global_remset (&cur->value);
+                                       mono_sgen_add_to_global_remset (&cur->value);
                                }
                        }
                }
@@ -5208,7 +4997,7 @@ handle_remset (mword *p, void *start_nursery, void *end_nursery, gboolean global
                                 * becomes part of the global remset, which can grow very large.
                                 */
                                DEBUG (9, fprintf (gc_debug_file, "Add to global remset because of pinning %p (%p %s)\n", ptr, *ptr, safe_name (*ptr)));
-                               add_to_global_remset (ptr);
+                               mono_sgen_add_to_global_remset (ptr);
                        }
                } else {
                        DEBUG (9, fprintf (gc_debug_file, "Skipping remset at %p holding %p\n", ptr, *ptr));
@@ -5223,7 +5012,7 @@ handle_remset (mword *p, void *start_nursery, void *end_nursery, gboolean global
                        copy_object (ptr, queue);
                        DEBUG (9, fprintf (gc_debug_file, "Overwrote remset at %p with %p (count: %d)\n", ptr, *ptr, (int)count));
                        if (!global && *ptr >= start_nursery && *ptr < end_nursery)
-                               add_to_global_remset (ptr);
+                               mono_sgen_add_to_global_remset (ptr);
                        ++ptr;
                }
                return p + 2;
index ab50364b6d0c8d48099db7605f609d268d087beb..ec9e69551ed7026b54ed09f9274e2b89a0d6101d 100644 (file)
@@ -54,6 +54,8 @@
 
 #define THREAD_HASH_SIZE 11
 
+#define GC_BITS_PER_WORD (sizeof (mword) * 8)
+
 #define ARCH_THREAD_TYPE pthread_t
 #define ARCH_GET_THREAD pthread_self
 #define ARCH_THREAD_EQUALS(a,b) pthread_equal (a, b)
@@ -225,6 +227,14 @@ const static int restart_signal_num = SIGXCPU;
 #define SGEN_PTR_IN_NURSERY(p,bits,start,end)  ((char*)(p) >= (start) && (char*)(p) < (end))
 #endif
 
+/* Structure that corresponds to a MonoVTable: desc is a mword so requires
+ * no cast from a pointer to an integer
+ */
+typedef struct {
+       MonoClass *klass;
+       mword desc;
+} GCVTable;
+
 /* these bits are set in the object vtable: we could merge them since an object can be
  * either pinned or forwarded but not both.
  * We store them in the vtable slot because the bits are used in the sync block for
@@ -255,6 +265,26 @@ const static int restart_signal_num = SIGXCPU;
  */
 #define SGEN_LOAD_VTABLE(addr) ((*(mword*)(addr)) & ~SGEN_VTABLE_BITS_MASK)
 
+/*
+ * ######################################################################
+ * ########  GC descriptors
+ * ######################################################################
+ * Used to quickly get the info the GC needs about an object: size and
+ * where the references are held.
+ */
+#define OBJECT_HEADER_WORDS (sizeof(MonoObject)/sizeof(gpointer))
+#define LOW_TYPE_BITS 3
+#define SMALL_BITMAP_SHIFT 16
+#define SMALL_BITMAP_SIZE (GC_BITS_PER_WORD - SMALL_BITMAP_SHIFT)
+#define VECTOR_INFO_SHIFT 14
+#define VECTOR_ELSIZE_SHIFT 3
+#define LARGE_BITMAP_SIZE (GC_BITS_PER_WORD - LOW_TYPE_BITS)
+#define MAX_ELEMENT_SIZE 0x3ff
+#define VECTOR_SUBTYPE_PTRFREE (DESC_TYPE_V_PTRFREE << VECTOR_INFO_SHIFT)
+#define VECTOR_SUBTYPE_REFS    (DESC_TYPE_V_REFS << VECTOR_INFO_SHIFT)
+#define VECTOR_SUBTYPE_RUN_LEN (DESC_TYPE_V_RUN_LEN << VECTOR_INFO_SHIFT)
+#define VECTOR_SUBTYPE_BITMAP  (DESC_TYPE_V_BITMAP << VECTOR_INFO_SHIFT)
+
 /* objects are aligned to 8 bytes boundaries
  * A descriptor is a pointer in MonoVTable, so 32 or 64 bits of size.
  * The low 3 bits define the type of the descriptor. The other bits
@@ -301,6 +331,171 @@ enum {
 
 #define SGEN_VTABLE_HAS_REFERENCES(vt) (((MonoVTable*)(vt))->gc_descr != (void*)DESC_TYPE_RUN_LENGTH)
 
+/* helper macros to scan and traverse objects, macros because we resue them in many functions */
+#define OBJ_RUN_LEN_SIZE(size,desc,obj) do { \
+               (size) = ((desc) & 0xfff8) >> 1;        \
+    } while (0)
+
+#define OBJ_BITMAP_SIZE(size,desc,obj) do { \
+               (size) = ((desc) & 0xfff8) >> 1;        \
+    } while (0)
+
+//#define PREFETCH(addr) __asm__ __volatile__ ("     prefetchnta     %0": : "m"(*(char *)(addr)))
+#define PREFETCH(addr)
+
+/* code using these macros must define a HANDLE_PTR(ptr) macro that does the work */
+#define OBJ_RUN_LEN_FOREACH_PTR(desc,obj)      do {    \
+               if ((desc) & 0xffff0000) {      \
+                       /* there are pointers */        \
+                       void **_objptr_end;     \
+                       void **_objptr = (void**)(obj); \
+                       _objptr += ((desc) >> 16) & 0xff;       \
+                       _objptr_end = _objptr + (((desc) >> 24) & 0xff);        \
+                       while (_objptr < _objptr_end) { \
+                               HANDLE_PTR (_objptr, (obj));    \
+                               _objptr++;      \
+                       }       \
+               }       \
+       } while (0)
+
+/* a bitmap desc means that there are pointer references or we'd have
+ * choosen run-length, instead: add an assert to check.
+ */
+#define OBJ_BITMAP_FOREACH_PTR(desc,obj)       do {    \
+               /* there are pointers */        \
+               void **_objptr = (void**)(obj); \
+               gsize _bmap = (desc) >> 16;     \
+               _objptr += OBJECT_HEADER_WORDS; \
+               while (_bmap) { \
+                       if ((_bmap & 1)) {      \
+                               HANDLE_PTR (_objptr, (obj));    \
+                       }       \
+                       _bmap >>= 1;    \
+                       ++_objptr;      \
+               }       \
+       } while (0)
+
+#define OBJ_LARGE_BITMAP_FOREACH_PTR(vt,obj)   do {    \
+               /* there are pointers */        \
+               void **_objptr = (void**)(obj); \
+               gsize _bmap = (vt)->desc >> LOW_TYPE_BITS;      \
+               _objptr += OBJECT_HEADER_WORDS; \
+               while (_bmap) { \
+                       if ((_bmap & 1)) {      \
+                               HANDLE_PTR (_objptr, (obj));    \
+                       }       \
+                       _bmap >>= 1;    \
+                       ++_objptr;      \
+               }       \
+       } while (0)
+
+gsize* mono_sgen_get_complex_descriptor (GCVTable *vt) MONO_INTERNAL;
+
+#define OBJ_COMPLEX_FOREACH_PTR(vt,obj)        do {    \
+               /* there are pointers */        \
+               void **_objptr = (void**)(obj); \
+               gsize *bitmap_data = mono_sgen_get_complex_descriptor ((vt)); \
+               int bwords = (*bitmap_data) - 1;        \
+               void **start_run = _objptr;     \
+               bitmap_data++;  \
+               if (0) {        \
+                       MonoObject *myobj = (MonoObject*)obj;   \
+                       g_print ("found %d at %p (0x%zx): %s.%s\n", bwords, (obj), (vt)->desc, myobj->vtable->klass->name_space, myobj->vtable->klass->name);   \
+               }       \
+               while (bwords-- > 0) {  \
+                       gsize _bmap = *bitmap_data++;   \
+                       _objptr = start_run;    \
+                       /*g_print ("bitmap: 0x%x/%d at %p\n", _bmap, bwords, _objptr);*/        \
+                       while (_bmap) { \
+                               if ((_bmap & 1)) {      \
+                                       HANDLE_PTR (_objptr, (obj));    \
+                               }       \
+                               _bmap >>= 1;    \
+                               ++_objptr;      \
+                       }       \
+                       start_run += GC_BITS_PER_WORD;  \
+               }       \
+       } while (0)
+
+/* this one is untested */
+#define OBJ_COMPLEX_ARR_FOREACH_PTR(vt,obj)    do {    \
+               /* there are pointers */        \
+               gsize *mbitmap_data = mono_sgen_get_complex_descriptor ((vt)); \
+               int mbwords = (*mbitmap_data++) - 1;    \
+               int el_size = mono_array_element_size (vt->klass);      \
+               char *e_start = (char*)(obj) +  G_STRUCT_OFFSET (MonoArray, vector);    \
+               char *e_end = e_start + el_size * mono_array_length_fast ((MonoArray*)(obj));   \
+               if (0)                                                  \
+                        g_print ("found %d at %p (0x%zx): %s.%s\n", mbwords, (obj), (vt)->desc, vt->klass->name_space, vt->klass->name); \
+               while (e_start < e_end) {       \
+                       void **_objptr = (void**)e_start;       \
+                       gsize *bitmap_data = mbitmap_data;      \
+                       unsigned int bwords = mbwords;  \
+                       while (bwords-- > 0) {  \
+                               gsize _bmap = *bitmap_data++;   \
+                               void **start_run = _objptr;     \
+                               /*g_print ("bitmap: 0x%x\n", _bmap);*/  \
+                               while (_bmap) { \
+                                       if ((_bmap & 1)) {      \
+                                               HANDLE_PTR (_objptr, (obj));    \
+                                       }       \
+                                       _bmap >>= 1;    \
+                                       ++_objptr;      \
+                               }       \
+                               _objptr = start_run + GC_BITS_PER_WORD; \
+                       }       \
+                       e_start += el_size;     \
+               }       \
+       } while (0)
+
+#define OBJ_VECTOR_FOREACH_PTR(vt,obj) do {    \
+               /* note: 0xffffc000 excludes DESC_TYPE_V_PTRFREE */     \
+               if ((vt)->desc & 0xffffc000) {  \
+                       int el_size = ((vt)->desc >> 3) & MAX_ELEMENT_SIZE;     \
+                       /* there are pointers */        \
+                       int etype = (vt)->desc & 0xc000;        \
+                       if (etype == (DESC_TYPE_V_REFS << 14)) {        \
+                               void **p = (void**)((char*)(obj) + G_STRUCT_OFFSET (MonoArray, vector));        \
+                               void **end_refs = (void**)((char*)p + el_size * mono_array_length_fast ((MonoArray*)(obj)));    \
+                               /* Note: this code can handle also arrays of struct with only references in them */     \
+                               while (p < end_refs) {  \
+                                       HANDLE_PTR (p, (obj));  \
+                                       ++p;    \
+                               }       \
+                       } else if (etype == DESC_TYPE_V_RUN_LEN << 14) {        \
+                               int offset = ((vt)->desc >> 16) & 0xff; \
+                               int num_refs = ((vt)->desc >> 24) & 0xff;       \
+                               char *e_start = (char*)(obj) + G_STRUCT_OFFSET (MonoArray, vector);     \
+                               char *e_end = e_start + el_size * mono_array_length_fast ((MonoArray*)(obj));   \
+                               while (e_start < e_end) {       \
+                                       void **p = (void**)e_start;     \
+                                       int i;  \
+                                       p += offset;    \
+                                       for (i = 0; i < num_refs; ++i) {        \
+                                               HANDLE_PTR (p + i, (obj));      \
+                                       }       \
+                                       e_start += el_size;     \
+                               }       \
+                       } else if (etype == DESC_TYPE_V_BITMAP << 14) { \
+                               char *e_start = (char*)(obj) +  G_STRUCT_OFFSET (MonoArray, vector);    \
+                               char *e_end = e_start + el_size * mono_array_length_fast ((MonoArray*)(obj));   \
+                               while (e_start < e_end) {       \
+                                       void **p = (void**)e_start;     \
+                                       gsize _bmap = (vt)->desc >> 16; \
+                                       /* Note: there is no object header here to skip */      \
+                                       while (_bmap) { \
+                                               if ((_bmap & 1)) {      \
+                                                       HANDLE_PTR (p, (obj));  \
+                                               }       \
+                                               _bmap >>= 1;    \
+                                               ++p;    \
+                                       }       \
+                                       e_start += el_size;     \
+                               }       \
+                       }       \
+               }       \
+       } while (0)
+
 #define SGEN_GRAY_QUEUE_SECTION_SIZE   (128 - 3)
 
 /*
@@ -431,6 +626,8 @@ void mono_sgen_pin_stats_register_object (char *obj, size_t size);
 void* mono_sgen_copy_object_no_checks (void *obj, SgenGrayQueue *queue) MONO_INTERNAL;
 void mono_sgen_par_copy_object_no_checks (char *destination, MonoVTable *vt, void *obj, mword objsize, SgenGrayQueue *queue) MONO_INTERNAL;
 
+void mono_sgen_add_to_global_remset (gpointer ptr) MONO_INTERNAL;
+
 /* FIXME: this should be inlined */
 guint mono_sgen_par_object_get_size (MonoVTable *vtable, MonoObject* o) MONO_INTERNAL;
 
@@ -443,7 +640,8 @@ struct _SgenMajorCollector {
        gboolean (*is_object_live) (char *obj);
        void* (*alloc_small_pinned_obj) (size_t size, gboolean has_references);
        void* (*alloc_degraded) (MonoVTable *vtable, size_t size);
-       void (*copy_or_mark_object) (void **obj_slot, SgenGrayQueue *queue); /* FIXME: don't call this indirectly - make a major_scan_object instead */
+       void (*copy_or_mark_object) (void **obj_slot, SgenGrayQueue *queue);
+       void (*scan_object) (char *start, SgenGrayQueue *queue);
        void* (*alloc_object) (int size, gboolean has_references); /* FIXME: don't call this indirectly, either */
        void (*free_pinned_object) (char *obj, size_t size);
        void (*iterate_objects) (gboolean non_pinned, gboolean pinned, IterateObjectCallbackFunc callback, void *data);
index c5ac1bcb52d6bc43f43b7e63232145e1c5520acd..896baee32275e4d47abb251785b191aaa4dd356b 100644 (file)
@@ -48,6 +48,7 @@
 #ifdef HAVE_SGEN_GC
 
 #include "utils/mono-counters.h"
+#include "metadata/object-internals.h"
 
 #include "metadata/sgen-gc.h"
 #include "metadata/sgen-protocol.h"
@@ -298,14 +299,14 @@ major_copy_or_mark_object (void **obj_slot, SgenGrayQueue *queue)
         */
 
        if ((forwarded = SGEN_OBJECT_IS_FORWARDED (obj))) {
-               DEBUG (9, g_assert (((MonoVTable*)LOAD_VTABLE(obj))->gc_descr));
+               DEBUG (9, g_assert (((MonoVTable*)SGEN_LOAD_VTABLE(obj))->gc_descr));
                DEBUG (9, fprintf (gc_debug_file, " (already forwarded to %p)\n", forwarded));
                HEAVY_STAT (++stat_major_copy_object_failed_forwarded);
                *obj_slot = forwarded;
                return;
        }
        if (SGEN_OBJECT_IS_PINNED (obj)) {
-               DEBUG (9, g_assert (((MonoVTable*)LOAD_VTABLE(obj))->gc_descr));
+               DEBUG (9, g_assert (((MonoVTable*)SGEN_LOAD_VTABLE(obj))->gc_descr));
                DEBUG (9, fprintf (gc_debug_file, " (pinned, no change)\n"));
                HEAVY_STAT (++stat_major_copy_object_failed_pinned);
                return;
@@ -336,7 +337,7 @@ major_copy_or_mark_object (void **obj_slot, SgenGrayQueue *queue)
                if (SGEN_OBJECT_IS_PINNED (obj))
                        return;
                DEBUG (9, fprintf (gc_debug_file, " (marked LOS/Pinned %p (%s), size: %zd)\n", obj, safe_name (obj), objsize));
-               binary_protocol_pin (obj, (gpointer)LOAD_VTABLE (obj), mono_sgen_safe_object_get_size ((MonoObject*)obj));
+               binary_protocol_pin (obj, (gpointer)SGEN_LOAD_VTABLE (obj), mono_sgen_safe_object_get_size ((MonoObject*)obj));
                SGEN_PIN_OBJECT (obj);
                GRAY_OBJECT_ENQUEUE (queue, obj);
                HEAVY_STAT (++stat_major_copy_object_failed_large_pinned);
@@ -361,6 +362,8 @@ major_copy_or_mark_object (void **obj_slot, SgenGrayQueue *queue)
        *obj_slot = mono_sgen_copy_object_no_checks (obj, queue);
 }
 
+#include "sgen-major-scan-object.h"
+
 /* FIXME: later reduce code duplication here with build_nursery_fragments().
  * We don't keep track of section fragments for non-nursery sections yet, so
  * just memset to 0.
@@ -441,7 +444,7 @@ major_free_non_pinned_object (char *obj, size_t size)
 static void
 pin_pinned_object_callback (void *addr, size_t slot_size, SgenGrayQueue *queue)
 {
-       binary_protocol_pin (addr, (gpointer)LOAD_VTABLE (addr), mono_sgen_safe_object_get_size ((MonoObject*)addr));
+       binary_protocol_pin (addr, (gpointer)SGEN_LOAD_VTABLE (addr), mono_sgen_safe_object_get_size ((MonoObject*)addr));
        if (!SGEN_OBJECT_IS_PINNED (addr))
                mono_sgen_pin_stats_register_object ((char*) addr, mono_sgen_safe_object_get_size ((MonoObject*) addr));
        SGEN_PIN_OBJECT (addr);
@@ -629,6 +632,7 @@ mono_sgen_copying_init (SgenMajorCollector *collector, int the_nursery_bits, cha
        collector->alloc_small_pinned_obj = major_alloc_small_pinned_obj;
        collector->alloc_degraded = major_alloc_degraded;
        collector->copy_or_mark_object = major_copy_or_mark_object;
+       collector->scan_object = major_scan_object;
        collector->alloc_object = alloc_object;
        collector->free_pinned_object = free_pinned_object;
        collector->iterate_objects = major_iterate_objects;
diff --git a/mono/metadata/sgen-major-scan-object.h b/mono/metadata/sgen-major-scan-object.h
new file mode 100644 (file)
index 0000000..884b48f
--- /dev/null
@@ -0,0 +1,22 @@
+extern long long stat_scan_object_called_major;
+
+#undef HANDLE_PTR
+#define HANDLE_PTR(ptr,obj)    do {                                    \
+               void *__old = *(ptr);                                   \
+               void *__copy;                                           \
+               if (__old) {                                            \
+                       major_copy_or_mark_object ((ptr), queue);       \
+                       __copy = *(ptr);                                \
+                       DEBUG (9, if (__old != __copy) mono_sgen_debug_printf (9, "Overwrote field at %p with %p (was: %p)\n", (ptr), *(ptr), __old)); \
+                       if (G_UNLIKELY (ptr_in_nursery (__copy) && !ptr_in_nursery ((ptr)))) \
+                               mono_sgen_add_to_global_remset ((ptr)); \
+               }                                                       \
+       } while (0)
+
+static void
+major_scan_object (char *start, SgenGrayQueue *queue)
+{
+#include "sgen-scan-object.h"
+
+       HEAVY_STAT (++stat_scan_object_called_major);
+}
index ca00e4022290afa9ef455ed4a11a4b908ceecc94..9c9eee6382f83bc2cf56ab5012a2b78529e4b73d 100644 (file)
@@ -31,6 +31,7 @@
 #include <math.h>
 
 #include "utils/mono-counters.h"
+#include "metadata/object-internals.h"
 
 #include "metadata/sgen-gc.h"
 #include "metadata/sgen-protocol.h"
@@ -681,6 +682,8 @@ major_copy_or_mark_object (void **ptr, SgenGrayQueue *queue)
        MS_MARK_OBJECT_AND_ENQUEUE (obj, block, queue);
 }
 
+#include "sgen-major-scan-object.h"
+
 static void
 mark_pinned_objects_in_block (MSBlockInfo *block, SgenGrayQueue *queue)
 {
@@ -995,6 +998,7 @@ mono_sgen_marksweep_init (SgenMajorCollector *collector, int the_nursery_bits, c
        collector->alloc_small_pinned_obj = major_alloc_small_pinned_obj;
        collector->alloc_degraded = major_alloc_degraded;
        collector->copy_or_mark_object = major_copy_or_mark_object;
+       collector->scan_object = major_scan_object;
        collector->alloc_object = ms_alloc_obj;
        collector->free_pinned_object = free_pinned_object;
        collector->iterate_objects = major_iterate_objects;
index 6f77d7a03534695beff8ce8c8e570baa0b2b9f9f..b10f5d6b92db5090b5927325d0a5290549303de9 100644 (file)
@@ -49,7 +49,7 @@
        size_t skip_size;
        mword desc;
 
-       vt = (GCVTable*)LOAD_VTABLE (start);
+       vt = (GCVTable*)SGEN_LOAD_VTABLE (start);
        //type = vt->desc & 0x7;
 
        /* gcc should be smart enough to remove the bounds check, but it isn't:( */
@@ -67,7 +67,7 @@
                break;
        case DESC_TYPE_ARRAY:
        case DESC_TYPE_VECTOR:
-               skip_size = ALIGN_UP (safe_object_get_size ((MonoObject*)start));
+               skip_size = SGEN_ALIGN_UP (mono_sgen_safe_object_get_size ((MonoObject*)start));
 #define SCAN OBJ_VECTOR_FOREACH_PTR (vt, start)
 #ifndef SCAN_OBJECT_NOSCAN
                SCAN;
@@ -88,7 +88,7 @@
                start += skip_size;
                break;
        case DESC_TYPE_LARGE_BITMAP:
-               skip_size = ALIGN_UP (safe_object_get_size ((MonoObject*)start));
+               skip_size = SGEN_ALIGN_UP (mono_sgen_safe_object_get_size ((MonoObject*)start));
 #define SCAN OBJ_LARGE_BITMAP_FOREACH_PTR (vt,start)
 #ifndef SCAN_OBJECT_NOSCAN
                SCAN;
@@ -99,7 +99,7 @@
                break;
        case DESC_TYPE_COMPLEX:
                /* this is a complex object */
-               skip_size = ALIGN_UP (safe_object_get_size ((MonoObject*)start));
+               skip_size = SGEN_ALIGN_UP (mono_sgen_safe_object_get_size ((MonoObject*)start));
 #define SCAN OBJ_COMPLEX_FOREACH_PTR (vt, start)
 #ifndef SCAN_OBJECT_NOSCAN
                SCAN;
                break;
        case DESC_TYPE_COMPLEX_ARR:
                /* this is an array of complex structs */
-               skip_size = ALIGN_UP (safe_object_get_size ((MonoObject*)start));
+               skip_size = SGEN_ALIGN_UP (mono_sgen_safe_object_get_size ((MonoObject*)start));
 #define SCAN OBJ_COMPLEX_ARR_FOREACH_PTR (vt, start)
 #ifndef SCAN_OBJECT_NOSCAN
                SCAN;