sgen-gray.c \
sgen-pinning.c \
sgen-pinning-stats.c \
- sgen-los.c \
sgen-protocol.c \
sgen-workers.c
sgen-marksweep-par.c \
sgen-marksweep-fixed-par.c \
sgen-major-copying.c \
+ sgen-los.c \
sgen-gc.h \
sgen-archdep.h \
sgen-cardtable.h \
#endif
}
-
-void los_scan_card_table (GrayQueue *queue);
-void los_iterate_live_block_ranges (sgen_cardtable_block_callback callback);
-
-
-
#ifdef SGEN_HAVE_OVERLAPPING_CARDS
static void
/*XXX we could do this in 2 ways. using mincore or iterating over all sections/los objects */
if (use_cardtable) {
major_collector.iterate_live_block_ranges (clear_cards);
- los_iterate_live_block_ranges (clear_cards);
+ mono_sgen_los_iterate_live_block_ranges (clear_cards);
}
}
static void
/*FIXME we should have a bit on each block/los object telling if the object have marked cards.*/
/*First we copy*/
major_collector.iterate_live_block_ranges (move_cards_to_shadow_table);
- los_iterate_live_block_ranges (move_cards_to_shadow_table);
+ mono_sgen_los_iterate_live_block_ranges (move_cards_to_shadow_table);
/*Then we clear*/
card_table_clear ();
#endif
major_collector.scan_card_table (queue);
- los_scan_card_table (queue);
+ mono_sgen_los_scan_card_table (queue);
}
}
void sgen_card_table_mark_range (mword address, mword size) MONO_INTERNAL;
void sgen_cardtable_scan_object (char *obj, mword obj_size, guint8 *cards, SgenGrayQueue *queue) MONO_INTERNAL;
gboolean sgen_card_table_get_card_data (guint8 *dest, mword address, mword cards) MONO_INTERNAL;
-typedef void (*sgen_cardtable_block_callback) (mword start, mword size);
/*How many bytes a single card covers*/
#define CARD_BITS 9
#include "sgen-pinning-stats.c"
#include "sgen-gray.c"
#include "sgen-workers.c"
-#include "sgen-los.c"
#include "sgen-cardtable.c"
/* Root bitmap descriptors are simpler: the lower three bits describe the type
void
mono_gc_scan_for_specific_ref (MonoObject *key)
{
- LOSObject *bigobj;
RootRecord *root;
int i;
major_collector.iterate_objects (TRUE, TRUE, (IterateObjectCallbackFunc)scan_object_for_specific_ref_callback, key);
- for (bigobj = los_object_list; bigobj; bigobj = bigobj->next)
- scan_object_for_specific_ref (bigobj->data, key);
+ mono_sgen_los_iterate_objects ((IterateObjectCallbackFunc)scan_object_for_specific_ref_callback, key);
scan_roots_for_specific_ref (key, ROOT_TYPE_NORMAL);
scan_roots_for_specific_ref (key, ROOT_TYPE_WBARRIER);
bigobj = bigobj->next;
DEBUG (4, fprintf (gc_debug_file, "Freeing large object %p\n",
bigobj->data));
- free_large_object (to_free);
+ mono_sgen_los_free_object (to_free);
continue;
}
prev = bigobj;
minor_collection_sections_alloced * major_collector.section_size + los_alloced > minor_collection_allowance;
}
+gboolean
+mono_sgen_need_major_collection (mword space_needed)
+{
+ return need_major_collection (space_needed);
+}
+
/*
* Collect objects in the nursery. Returns whether to trigger a major
* collection.
los_object_list = bigobj->next;
to_free = bigobj;
bigobj = bigobj->next;
- free_large_object (to_free);
+ mono_sgen_los_free_object (to_free);
continue;
}
prevbo = bigobj;
TV_GETTIME (btv);
time_major_free_bigobjs += TV_ELAPSED_MS (atv, btv);
- los_sweep ();
+ mono_sgen_los_sweep ();
TV_GETTIME (atv);
time_major_los_sweep += TV_ELAPSED_MS (btv, atv);
*/
if (size > MAX_SMALL_OBJ_SIZE) {
- p = alloc_large_inner (vtable, size);
+ p = mono_sgen_los_alloc_large_inner (vtable, size);
} else {
/* tlab_next and tlab_temp_end are TLS vars so accessing them might be expensive */
if (size > MAX_SMALL_OBJ_SIZE) {
/* large objects are always pinned anyway */
- p = alloc_large_inner (vtable, size);
+ p = mono_sgen_los_alloc_large_inner (vtable, size);
} else {
DEBUG (9, g_assert (vtable->klass->inited));
p = major_collector.alloc_small_pinned_obj (size, vtable->klass->has_references);
static char *found_obj;
static void
-find_object_for_ptr_callback (char *obj, size_t size, char *ptr)
+find_object_for_ptr_callback (char *obj, size_t size, void *user_data)
{
+ char *ptr = user_data;
+
if (ptr >= obj && ptr < obj + size) {
g_assert (!found_obj);
found_obj = obj;
char*
find_object_for_ptr (char *ptr)
{
- LOSObject *bigobj;
-
if (ptr >= nursery_section->data && ptr < nursery_section->end_data) {
found_obj = NULL;
mono_sgen_scan_area_with_callback (nursery_section->data, nursery_section->end_data,
- (IterateObjectCallbackFunc)find_object_for_ptr_callback, ptr);
+ find_object_for_ptr_callback, ptr);
if (found_obj)
return found_obj;
}
- for (bigobj = los_object_list; bigobj; bigobj = bigobj->next) {
- if (ptr >= bigobj->data && ptr < bigobj->data + bigobj->size)
- return bigobj->data;
- }
+ found_obj = NULL;
+ mono_sgen_los_iterate_objects (find_object_for_ptr_callback, ptr);
+ if (found_obj)
+ return found_obj;
/*
* Very inefficient, but this is debugging code, supposed to
* be called from gdb, so we don't care.
*/
found_obj = NULL;
- major_collector.iterate_objects (TRUE, TRUE, (IterateObjectCallbackFunc)find_object_for_ptr_callback, ptr);
+ major_collector.iterate_objects (TRUE, TRUE, find_object_for_ptr_callback, ptr);
return found_obj;
}
static void
check_consistency (void)
{
- LOSObject *bigobj;
-
// Need to add more checks
missing_remsets = FALSE;
// Check that oldspace->newspace pointers are registered with the collector
major_collector.iterate_objects (TRUE, TRUE, (IterateObjectCallbackFunc)check_consistency_callback, NULL);
- for (bigobj = los_object_list; bigobj; bigobj = bigobj->next)
- check_consistency_callback (bigobj->data, bigobj->size, NULL);
+ mono_sgen_los_iterate_objects ((IterateObjectCallbackFunc)check_consistency_callback, NULL);
DEBUG (1, fprintf (gc_debug_file, "Heap consistency check done.\n"));
static void
check_major_refs (void)
{
- LOSObject *bigobj;
-
major_collector.iterate_objects (TRUE, TRUE, (IterateObjectCallbackFunc)check_major_refs_callback, NULL);
-
- for (bigobj = los_object_list; bigobj; bigobj = bigobj->next)
- check_major_refs_callback (bigobj->data, bigobj->size, NULL);
+ mono_sgen_los_iterate_objects ((IterateObjectCallbackFunc)check_major_refs_callback, NULL);
}
/* Check that the reference is valid */
mono_gc_walk_heap (int flags, MonoGCReferences callback, void *data)
{
HeapWalkInfo hwi;
- LOSObject *bigobj;
hwi.flags = flags;
hwi.callback = callback;
mono_sgen_scan_area_with_callback (nursery_section->data, nursery_section->end_data, walk_references, &hwi);
major_collector.iterate_objects (TRUE, TRUE, walk_references, &hwi);
+ mono_sgen_los_iterate_objects (walk_references, &hwi);
- for (bigobj = los_object_list; bigobj; bigobj = bigobj->next)
- walk_references (bigobj->data, bigobj->size, &hwi);
return 0;
}
int mono_sgen_get_current_collection_generation (void) MONO_INTERNAL;
+typedef void (*sgen_cardtable_block_callback) (mword start, mword size);
+
typedef struct _SgenMajorCollector SgenMajorCollector;
struct _SgenMajorCollector {
size_t section_size;
void (*find_pin_queue_start_ends) (SgenGrayQueue *queue);
void (*pin_objects) (SgenGrayQueue *queue);
void (*scan_card_table) (SgenGrayQueue *queue);
- void (*iterate_live_block_ranges) (void *callback);
+ void (*iterate_live_block_ranges) (sgen_cardtable_block_callback callback);
void (*init_to_space) (void);
void (*sweep) (void);
void (*check_scan_starts) (void);
gboolean mono_sgen_try_alloc_space (mword size, int space) MONO_INTERNAL;
void mono_sgen_release_space (mword size, int space) MONO_INTERNAL;
void mono_sgen_pin_object (void *object, SgenGrayQueue *queue) MONO_INTERNAL;
-void sgen_collect_major_no_lock (const char *reason) MONO_INTERNAL;;
+void sgen_collect_major_no_lock (const char *reason) MONO_INTERNAL;
+gboolean mono_sgen_need_major_collection (mword space_needed) MONO_INTERNAL;
+
+/* LOS */
+
+typedef struct _LOSObject LOSObject;
+struct _LOSObject {
+ LOSObject *next;
+ mword size; /* this is the object size */
+ guint16 huge_object;
+ int dummy; /* to have a sizeof (LOSObject) a multiple of ALLOC_ALIGN and data starting at same alignment */
+ char data [MONO_ZERO_LEN_ARRAY];
+};
+
+#define ARRAY_OBJ_INDEX(ptr,array,elem_size) (((char*)(ptr) - ((char*)(array) + G_STRUCT_OFFSET (MonoArray, vector))) / (elem_size))
+
+extern LOSObject *los_object_list;
+extern mword los_memory_usage;
+extern mword last_los_memory_usage;
+
+void mono_sgen_los_free_object (LOSObject *obj) MONO_INTERNAL;
+void* mono_sgen_los_alloc_large_inner (MonoVTable *vtable, size_t size) MONO_INTERNAL;
+void mono_sgen_los_sweep (void) MONO_INTERNAL;
+gboolean mono_sgen_ptr_is_in_los (char *ptr, char **start) MONO_INTERNAL;
+void mono_sgen_los_iterate_objects (IterateObjectCallbackFunc cb, void *user_data) MONO_INTERNAL;
+void mono_sgen_los_iterate_live_block_ranges (sgen_cardtable_block_callback callback) MONO_INTERNAL;
+void mono_sgen_los_scan_card_table (SgenGrayQueue *queue) MONO_INTERNAL;
+
#endif /* __MONO_SGENGC_H__ */
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
+#ifdef HAVE_SGEN_GC
+
+#include "metadata/sgen-gc.h"
+#include "metadata/sgen-protocol.h"
+#include "metadata/sgen-cardtable.h"
+#include "utils/mono-mmap.h"
+
#define LOS_SECTION_SIZE (1024 * 1024)
/*
#define LOS_NUM_FAST_SIZES 32
-typedef struct _LOSObject LOSObject;
-struct _LOSObject {
- LOSObject *next;
- mword size; /* this is the object size */
- guint16 huge_object;
- int dummy; /* to have a sizeof (LOSObject) a multiple of ALLOC_ALIGN and data starting at same alignment */
- char data [MONO_ZERO_LEN_ARRAY];
-};
-
typedef struct _LOSFreeChunks LOSFreeChunks;
struct _LOSFreeChunks {
LOSFreeChunks *next_size;
unsigned char *free_chunk_map;
};
+LOSObject *los_object_list = NULL;
+mword los_memory_usage = 0;
+mword last_los_memory_usage = 0;
+
static LOSSection *los_sections = NULL;
-static LOSObject *los_object_list = NULL;
static LOSFreeChunks *los_fast_free_lists [LOS_NUM_FAST_SIZES]; /* 0 is for larger sizes */
-static mword los_memory_usage = 0;
-static mword last_los_memory_usage = 0;
static mword los_num_objects = 0;
static int los_num_sections = 0;
static mword next_los_collection = 2*1024*1024; /* 2 MB, need to tune */
add_free_chunk ((LOSFreeChunks*)obj, size);
}
-static void
-free_large_object (LOSObject *obj)
+static int pagesize;
+
+void
+mono_sgen_los_free_object (LOSObject *obj)
{
#ifndef LOS_DUMMY
size_t size = obj->size;
free (obj);
#else
if (size > LOS_SECTION_OBJECT_LIMIT) {
+ if (!pagesize)
+ pagesize = mono_pagesize ();
size += sizeof (LOSObject);
size += pagesize - 1;
size &= ~(pagesize - 1);
* They don't move, so there is no need to pin them during collection
* and we avoid the memcpy overhead.
*/
-static void* __attribute__((noinline))
-alloc_large_inner (MonoVTable *vtable, size_t size)
+void*
+mono_sgen_los_alloc_large_inner (MonoVTable *vtable, size_t size)
{
LOSObject *obj = NULL;
void **vtslot;
- g_assert (size > MAX_SMALL_OBJ_SIZE);
+ g_assert (size > SGEN_MAX_SMALL_OBJ_SIZE);
#ifdef LOS_DUMMY
if (!los_segment)
los_segment_index += size + sizeof (LOSObject);
g_assert (los_segment_index <= LOS_SEGMENT_SIZE);
#else
- if (need_major_collection (size)) {
+ if (mono_sgen_need_major_collection (size)) {
DEBUG (4, fprintf (gc_debug_file, "Should trigger major collection: req size %zd (los already: %lu, limit: %lu)\n", size, (unsigned long)los_memory_usage, (unsigned long)next_los_collection));
- mono_profiler_gc_event (MONO_GC_EVENT_START, 1);
- stop_world (1);
- major_collection ("LOS overflow");
- restart_world (1);
- mono_profiler_gc_event (MONO_GC_EVENT_END, 1);
+ sgen_collect_major_no_lock ("LOS overflow");
}
#ifdef USE_MALLOC
#else
if (size > LOS_SECTION_OBJECT_LIMIT) {
size_t alloc_size = size;
+ if (!pagesize)
+ pagesize = mono_pagesize ();
alloc_size += sizeof (LOSObject);
alloc_size += pagesize - 1;
alloc_size &= ~(pagesize - 1);
#endif
if (!obj)
return NULL;
- g_assert (!((mword)obj->data & (ALLOC_ALIGN - 1)));
+ g_assert (!((mword)obj->data & (SGEN_ALLOC_ALIGN - 1)));
obj->size = size;
vtslot = (void**)obj->data;
*vtslot = vtable;
return obj->data;
}
-static void
-los_sweep (void)
+void
+mono_sgen_los_sweep (void)
{
LOSSection *section, *prev;
int i;
g_assert (los_num_sections == num_sections);
}
-static gboolean
+gboolean
mono_sgen_ptr_is_in_los (char *ptr, char **start)
{
LOSObject *obj;
return FALSE;
}
-#ifdef SGEN_HAVE_CARDTABLE
+void
+mono_sgen_los_iterate_objects (IterateObjectCallbackFunc cb, void *user_data)
+{
+ LOSObject *obj;
-static void
-los_iterate_live_block_ranges (sgen_cardtable_block_callback callback)
+ for (obj = los_object_list; obj; obj = obj->next)
+ cb (obj->data, obj->size, user_data);
+}
+
+void
+mono_sgen_los_iterate_live_block_ranges (sgen_cardtable_block_callback callback)
{
LOSObject *obj;
for (obj = los_object_list; obj; obj = obj->next) {
- MonoVTable *vt = (MonoVTable*)LOAD_VTABLE (obj->data);
+ MonoVTable *vt = (MonoVTable*)SGEN_LOAD_VTABLE (obj->data);
if (vt->klass->has_references)
callback ((mword)obj->data, (mword)obj->size);
}
}
-#define ARRAY_OBJ_INDEX(ptr,array,elem_size) (((char*)(ptr) - ((char*)(array) + G_STRUCT_OFFSET (MonoArray, vector))) / (elem_size))
-
-static void __attribute__((noinline))
-los_scan_card_table (GrayQueue *queue)
+void
+mono_sgen_los_scan_card_table (SgenGrayQueue *queue)
{
LOSObject *obj;
}
}
-#endif
+#endif /* HAVE_SGEN_GC */