/* LOCKING: assumes the GC lock is held */ static void rehash_dislink (DisappearingLinkHashTable *hash_table) { DisappearingLink **disappearing_link_hash = hash_table->table; int disappearing_link_hash_size = hash_table->size; int i; unsigned int hash; DisappearingLink **new_hash; DisappearingLink *entry, *next; int new_size = g_spaced_primes_closest (hash_table->num_links); new_hash = mono_sgen_alloc_internal_dynamic (new_size * sizeof (DisappearingLink*), INTERNAL_MEM_DISLINK_TABLE); for (i = 0; i < disappearing_link_hash_size; ++i) { for (entry = disappearing_link_hash [i]; entry; entry = next) { hash = mono_aligned_addr_hash (entry->link) % new_size; next = entry->next; entry->next = new_hash [hash]; new_hash [hash] = entry; } } mono_sgen_free_internal_dynamic (disappearing_link_hash, disappearing_link_hash_size * sizeof (DisappearingLink*), INTERNAL_MEM_DISLINK_TABLE); hash_table->table = new_hash; hash_table->size = new_size; }
/* * Clear the info in the remembered sets: we're doing a major collection, so * the per-thread ones are not needed and the global ones will be reconstructed * during the copy. */ static void mono_sgen_ssb_prepare_for_major_collection (void) { SgenThreadInfo *info; RememberedSet *remset, *next; mono_sgen_ssb_prepare_for_minor_collection (); /* the global list */ for (remset = global_remset; remset; remset = next) { remset->store_next = remset->data; next = remset->next; remset->next = NULL; if (remset != global_remset) { DEBUG (4, fprintf (gc_debug_file, "Freed remset at %p\n", remset->data)); mono_sgen_free_internal_dynamic (remset, remset_byte_size (remset), INTERNAL_MEM_REMSET); } } /* the generic store ones */ while (generic_store_remsets) { GenericStoreRememberedSet *gs_next = generic_store_remsets->next; mono_sgen_free_internal (generic_store_remsets, INTERNAL_MEM_STORE_REMSET); generic_store_remsets = gs_next; } /* the per-thread ones */ FOREACH_THREAD (info) { for (remset = info->remset; remset; remset = next) { remset->store_next = remset->data; next = remset->next; remset->next = NULL; if (remset != info->remset) { DEBUG (3, fprintf (gc_debug_file, "Freed remset at %p\n", remset->data)); mono_sgen_free_internal_dynamic (remset, remset_byte_size (remset), INTERNAL_MEM_REMSET); } } clear_thread_store_remset_buffer (info); } END_FOREACH_THREAD /* the freed thread ones */ while (freed_thread_remsets) { next = freed_thread_remsets->next; DEBUG (4, fprintf (gc_debug_file, "Freed remset at %p\n", freed_thread_remsets->data)); mono_sgen_free_internal_dynamic (freed_thread_remsets, remset_byte_size (freed_thread_remsets), INTERNAL_MEM_REMSET); freed_thread_remsets = next; } }
static void free_major_section (GCMemSection *section) { DEBUG (3, fprintf (gc_debug_file, "Freed major section %p (%p-%p)\n", section, section->data, section->end_data)); mono_sgen_free_internal_dynamic (section->scan_starts, (section->size + SGEN_SCAN_START_SIZE - 1) / SGEN_SCAN_START_SIZE * sizeof (char*), INTERNAL_MEM_SCAN_STARTS); mono_sgen_free_os_memory (section, MAJOR_SECTION_SIZE); --num_major_sections; }
static void realloc_pin_queue (void) { int new_size = pin_queue_size? pin_queue_size + pin_queue_size/2: 1024; void **new_pin = mono_sgen_alloc_internal_dynamic (sizeof (void*) * new_size, INTERNAL_MEM_PIN_QUEUE); memcpy (new_pin, pin_queue, sizeof (void*) * next_pin_slot); mono_sgen_free_internal_dynamic (pin_queue, sizeof (void*) * pin_queue_size, INTERNAL_MEM_PIN_QUEUE); pin_queue = new_pin; pin_queue_size = new_size; DEBUG (4, fprintf (gc_debug_file, "Reallocated pin queue to size: %d\n", new_size)); }
static void remset_stats (void) { RememberedSet *remset; int size = 0; SgenThreadInfo *info; mword *addresses, *bumper, *p, *r; FOREACH_THREAD (info) { for (remset = info->remset; remset; remset = remset->next) size += remset->store_next - remset->data; } END_FOREACH_THREAD for (remset = freed_thread_remsets; remset; remset = remset->next) size += remset->store_next - remset->data; for (remset = global_remset; remset; remset = remset->next) size += remset->store_next - remset->data; bumper = addresses = mono_sgen_alloc_internal_dynamic (sizeof (mword) * size, INTERNAL_MEM_STATISTICS); FOREACH_THREAD (info) { for (remset = info->remset; remset; remset = remset->next) bumper = collect_store_remsets (remset, bumper); } END_FOREACH_THREAD for (remset = global_remset; remset; remset = remset->next) bumper = collect_store_remsets (remset, bumper); for (remset = freed_thread_remsets; remset; remset = remset->next) bumper = collect_store_remsets (remset, bumper); g_assert (bumper <= addresses + size); stat_store_remsets += bumper - addresses; mono_sgen_sort_addresses ((void**)addresses, bumper - addresses); p = addresses; r = addresses + 1; while (r < bumper) { if (*r != *p) *++p = *r; ++r; } stat_store_remsets_unique += p - addresses; mono_sgen_free_internal_dynamic (addresses, sizeof (mword) * size, INTERNAL_MEM_STATISTICS); }
/* LOCKING: requires that the GC lock is held */ static void rehash_fin_table (FinalizeEntryHashTable *hash_table) { FinalizeEntry **finalizable_hash = hash_table->table; mword finalizable_hash_size = hash_table->size; int i; unsigned int hash; FinalizeEntry **new_hash; FinalizeEntry *entry, *next; int new_size = g_spaced_primes_closest (hash_table->num_registered); new_hash = mono_sgen_alloc_internal_dynamic (new_size * sizeof (FinalizeEntry*), INTERNAL_MEM_FIN_TABLE); for (i = 0; i < finalizable_hash_size; ++i) { for (entry = finalizable_hash [i]; entry; entry = next) { hash = mono_object_hash (entry->object) % new_size; next = entry->next; entry->next = new_hash [hash]; new_hash [hash] = entry; } } mono_sgen_free_internal_dynamic (finalizable_hash, finalizable_hash_size * sizeof (FinalizeEntry*), INTERNAL_MEM_FIN_TABLE); hash_table->table = new_hash; hash_table->size = new_size; }
static void mono_sgen_ssb_finish_scan_remsets (void *start_nursery, void *end_nursery, SgenGrayQueue *queue) { int i; SgenThreadInfo *info; RememberedSet *remset; GenericStoreRememberedSet *store_remset; mword *p; #ifdef HEAVY_STATISTICS remset_stats (); #endif /* the generic store ones */ store_remset = generic_store_remsets; while (store_remset) { GenericStoreRememberedSet *next = store_remset->next; for (i = 0; i < STORE_REMSET_BUFFER_SIZE - 1; ++i) { gpointer addr = store_remset->data [i]; if (addr) handle_remset ((mword*)&addr, start_nursery, end_nursery, FALSE, queue); } mono_sgen_free_internal (store_remset, INTERNAL_MEM_STORE_REMSET); store_remset = next; } generic_store_remsets = NULL; /* the per-thread ones */ FOREACH_THREAD (info) { RememberedSet *next; int j; for (remset = info->remset; remset; remset = next) { DEBUG (4, fprintf (gc_debug_file, "Scanning remset for thread %p, range: %p-%p, size: %td\n", info, remset->data, remset->store_next, remset->store_next - remset->data)); for (p = remset->data; p < remset->store_next;) p = handle_remset (p, start_nursery, end_nursery, FALSE, queue); remset->store_next = remset->data; next = remset->next; remset->next = NULL; if (remset != info->remset) { DEBUG (4, fprintf (gc_debug_file, "Freed remset at %p\n", remset->data)); mono_sgen_free_internal_dynamic (remset, remset_byte_size (remset), INTERNAL_MEM_REMSET); } } for (j = 0; j < *info->store_remset_buffer_index_addr; ++j) handle_remset ((mword*)*info->store_remset_buffer_addr + j + 1, start_nursery, end_nursery, FALSE, queue); clear_thread_store_remset_buffer (info); } END_FOREACH_THREAD /* the freed thread ones */ while (freed_thread_remsets) { RememberedSet *next; remset = freed_thread_remsets; DEBUG (4, fprintf (gc_debug_file, "Scanning remset for freed thread, range: %p-%p, size: %td\n", remset->data, remset->store_next, remset->store_next - remset->data)); for (p = remset->data; p < remset->store_next;) p = handle_remset (p, start_nursery, end_nursery, FALSE, queue); next = remset->next; DEBUG (4, fprintf (gc_debug_file, "Freed remset at %p\n", remset->data)); mono_sgen_free_internal_dynamic (remset, remset_byte_size (remset), INTERNAL_MEM_REMSET); freed_thread_remsets = next; } }