Functions for allocing fixed-size blocks in internal allocator.
authorMark Probst <mark.probst@gmail.com>
Thu, 22 Jul 2010 19:53:41 +0000 (21:53 +0200)
committerMark Probst <mark.probst@gmail.com>
Sat, 24 Jul 2010 21:15:08 +0000 (23:15 +0200)
2010-07-24  Mark Probst  <mark.probst@gmail.com>

* sgen-internal.c, sgen-gc.c, sgen-gc.h, sgen-gray.c,
sgen-major-copying.c, sgen-marksweep.c, sgen-pinning-stats.c,
sgen-pinning.c: Allocate fixed-size structs without specifying the
size, instead registering it once with its type.
Dynamically-sized need their size specified when being freed.

mono/metadata/ChangeLog
mono/metadata/sgen-gc.c
mono/metadata/sgen-gc.h
mono/metadata/sgen-gray.c
mono/metadata/sgen-internal.c
mono/metadata/sgen-major-copying.c
mono/metadata/sgen-marksweep.c
mono/metadata/sgen-pinning-stats.c
mono/metadata/sgen-pinning.c

index f7ff00536e0a25e014f4a11293970df952428718..d0883da8cf5ffc0b384a8047911c82695acccab3 100644 (file)
@@ -1,3 +1,11 @@
+2010-07-24  Mark Probst  <mark.probst@gmail.com>
+
+       * sgen-internal.c, sgen-gc.c, sgen-gc.h, sgen-gray.c,
+       sgen-major-copying.c, sgen-marksweep.c, sgen-pinning-stats.c,
+       sgen-pinning.c: Allocate fixed-size structs without specifying the
+       size, instead registering it once with its type.
+       Dynamically-sized need their size specified when being freed.
+
 2010-07-24  Mark Probst  <mark.probst@gmail.com>
 
        * sgen-major-copying.c, sgen-internal.c, sgen-gc.c, sgen-gc.h,
index 69514d3288d9cfacfa70d86b72009734c6ef4506..0c94659fa7d120e9c6d46abdad6e29ecb075e988 100644 (file)
@@ -2540,7 +2540,7 @@ alloc_fragment (void)
                frag->next = NULL;
                return frag;
        }
-       frag = mono_sgen_alloc_internal (sizeof (Fragment), INTERNAL_MEM_FRAGMENT);
+       frag = mono_sgen_alloc_internal (INTERNAL_MEM_FRAGMENT);
        frag->next = NULL;
        return frag;
 }
@@ -2587,7 +2587,7 @@ alloc_nursery (void)
         * objects in the existing nursery.
         */
        /* FIXME: handle OOM */
-       section = mono_sgen_alloc_internal (SIZEOF_GC_MEM_SECTION, INTERNAL_MEM_SECTION);
+       section = mono_sgen_alloc_internal (INTERNAL_MEM_SECTION);
 
        g_assert (nursery_size == DEFAULT_NURSERY_SIZE);
        alloc_size = nursery_size;
@@ -2605,7 +2605,7 @@ alloc_nursery (void)
        section->size = alloc_size;
        section->end_data = nursery_real_end;
        scan_starts = (alloc_size + SCAN_START_SIZE - 1) / SCAN_START_SIZE;
-       section->scan_starts = mono_sgen_alloc_internal (sizeof (char*) * scan_starts, INTERNAL_MEM_SCAN_STARTS);
+       section->scan_starts = mono_sgen_alloc_internal_dynamic (sizeof (char*) * scan_starts, INTERNAL_MEM_SCAN_STARTS);
        section->num_scan_start = scan_starts;
        section->block.role = MEMORY_ROLE_GEN0;
        section->block.next = NULL;
@@ -4056,7 +4056,7 @@ rehash_fin_table (FinalizeEntryHashTable *hash_table)
        FinalizeEntry *entry, *next;
        int new_size = g_spaced_primes_closest (hash_table->num_registered);
 
-       new_hash = mono_sgen_alloc_internal (new_size * sizeof (FinalizeEntry*), INTERNAL_MEM_FIN_TABLE);
+       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;
@@ -4065,7 +4065,7 @@ rehash_fin_table (FinalizeEntryHashTable *hash_table)
                        new_hash [hash] = entry;
                }
        }
-       mono_sgen_free_internal (finalizable_hash, INTERNAL_MEM_FIN_TABLE);
+       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;
 }
@@ -4549,7 +4549,7 @@ register_for_finalization (MonoObject *obj, void *user_data, int generation)
                UNLOCK_GC;
                return;
        }
-       entry = mono_sgen_alloc_internal (sizeof (FinalizeEntry), INTERNAL_MEM_FINALIZE_ENTRY);
+       entry = mono_sgen_alloc_internal (INTERNAL_MEM_FINALIZE_ENTRY);
        entry->object = obj;
        entry->next = finalizable_hash [hash];
        finalizable_hash [hash] = entry;
@@ -4578,7 +4578,7 @@ rehash_dislink (DisappearingLinkHashTable *hash_table)
        DisappearingLink *entry, *next;
        int new_size = g_spaced_primes_closest (hash_table->num_links);
 
-       new_hash = mono_sgen_alloc_internal (new_size * sizeof (DisappearingLink*), INTERNAL_MEM_DISLINK_TABLE);
+       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;
@@ -4587,7 +4587,8 @@ rehash_dislink (DisappearingLinkHashTable *hash_table)
                        new_hash [hash] = entry;
                }
        }
-       mono_sgen_free_internal (disappearing_link_hash, INTERNAL_MEM_DISLINK_TABLE);
+       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;
 }
@@ -4633,7 +4634,7 @@ add_or_remove_disappearing_link (MonoObject *obj, void **link, gboolean track, i
        }
        if (obj == NULL)
                return;
-       entry = mono_sgen_alloc_internal (sizeof (DisappearingLink), INTERNAL_MEM_DISLINK);
+       entry = mono_sgen_alloc_internal (INTERNAL_MEM_DISLINK);
        *link = HIDE_POINTER (obj, track);
        entry->link = link;
        entry->next = disappearing_link_hash [hash];
@@ -4751,7 +4752,7 @@ rehash_roots (gboolean pinned)
        int new_size;
 
        new_size = g_spaced_primes_closest (num_roots_entries [pinned]);
-       new_hash = mono_sgen_alloc_internal (new_size * sizeof (RootRecord*), INTERNAL_MEM_ROOTS_TABLE);
+       new_hash = mono_sgen_alloc_internal_dynamic (new_size * sizeof (RootRecord*), INTERNAL_MEM_ROOTS_TABLE);
        for (i = 0; i < roots_hash_size [pinned]; ++i) {
                for (entry = roots_hash [pinned][i]; entry; entry = next) {
                        hash = mono_aligned_addr_hash (entry->start_root) % new_size;
@@ -4760,7 +4761,7 @@ rehash_roots (gboolean pinned)
                        new_hash [hash] = entry;
                }
        }
-       mono_sgen_free_internal (roots_hash [pinned], INTERNAL_MEM_ROOTS_TABLE);
+       mono_sgen_free_internal_dynamic (roots_hash [pinned], roots_hash_size [pinned] * sizeof (RootRecord*), INTERNAL_MEM_ROOTS_TABLE);
        roots_hash [pinned] = new_hash;
        roots_hash_size [pinned] = new_size;
 }
@@ -4810,7 +4811,7 @@ mono_gc_register_root_inner (char *start, size_t size, void *descr, int root_typ
                        return TRUE;
                }
        }
-       new_root = mono_sgen_alloc_internal (sizeof (RootRecord), INTERNAL_MEM_ROOT_RECORD);
+       new_root = mono_sgen_alloc_internal (INTERNAL_MEM_ROOT_RECORD);
        if (new_root) {
                new_root->start_root = start;
                new_root->end_root = new_root->start_root + size;
@@ -5415,7 +5416,7 @@ remset_stats (void)
        for (remset = global_remset; remset; remset = remset->next)
                size += remset->store_next - remset->data;
 
-       bumper = addresses = mono_sgen_alloc_internal (sizeof (mword) * size, INTERNAL_MEM_STATISTICS);
+       bumper = addresses = mono_sgen_alloc_internal_dynamic (sizeof (mword) * size, INTERNAL_MEM_STATISTICS);
 
        for (i = 0; i < THREAD_HASH_SIZE; ++i) {
                for (info = thread_table [i]; info; info = info->next) {
@@ -5443,7 +5444,7 @@ remset_stats (void)
 
        stat_store_remsets_unique += p - addresses;
 
-       mono_sgen_free_internal (addresses, INTERNAL_MEM_STATISTICS);
+       mono_sgen_free_internal_dynamic (addresses, sizeof (mword) * size, INTERNAL_MEM_STATISTICS);
 }
 #endif
 
@@ -5454,6 +5455,12 @@ clear_thread_store_remset_buffer (SgenThreadInfo *info)
        memset (*info->store_remset_buffer_addr, 0, sizeof (gpointer) * STORE_REMSET_BUFFER_SIZE);
 }
 
+static size_t
+remset_byte_size (RememberedSet *remset)
+{
+       return sizeof (RememberedSet) + (remset->end_set - remset->data) * sizeof (gpointer);
+}
+
 static void
 scan_from_remsets (void *start_nursery, void *end_nursery, GrayQueue *queue)
 {
@@ -5531,7 +5538,7 @@ scan_from_remsets (void *start_nursery, void *end_nursery, GrayQueue *queue)
                                remset->next = NULL;
                                if (remset != info->remset) {
                                        DEBUG (4, fprintf (gc_debug_file, "Freed remset at %p\n", remset->data));
-                                       mono_sgen_free_internal (remset, INTERNAL_MEM_REMSET);
+                                       mono_sgen_free_internal_dynamic (remset, remset_byte_size (remset), INTERNAL_MEM_REMSET);
                                }
                        }
                        for (j = 0; j < *info->store_remset_buffer_index_addr; ++j)
@@ -5550,7 +5557,7 @@ scan_from_remsets (void *start_nursery, void *end_nursery, GrayQueue *queue)
                }
                next = remset->next;
                DEBUG (4, fprintf (gc_debug_file, "Freed remset at %p\n", remset->data));
-               mono_sgen_free_internal (remset, INTERNAL_MEM_REMSET);
+               mono_sgen_free_internal_dynamic (remset, remset_byte_size (remset), INTERNAL_MEM_REMSET);
                freed_thread_remsets = next;
        }
 }
@@ -5574,7 +5581,7 @@ clear_remsets (void)
                remset->next = NULL;
                if (remset != global_remset) {
                        DEBUG (4, fprintf (gc_debug_file, "Freed remset at %p\n", remset->data));
-                       mono_sgen_free_internal (remset, INTERNAL_MEM_REMSET);
+                       mono_sgen_free_internal_dynamic (remset, remset_byte_size (remset), INTERNAL_MEM_REMSET);
                }
        }
        /* the generic store ones */
@@ -5592,7 +5599,7 @@ clear_remsets (void)
                                remset->next = NULL;
                                if (remset != info->remset) {
                                        DEBUG (3, fprintf (gc_debug_file, "Freed remset at %p\n", remset->data));
-                                       mono_sgen_free_internal (remset, INTERNAL_MEM_REMSET);
+                                       mono_sgen_free_internal_dynamic (remset, remset_byte_size (remset), INTERNAL_MEM_REMSET);
                                }
                        }
                        clear_thread_store_remset_buffer (info);
@@ -5603,7 +5610,7 @@ clear_remsets (void)
        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 (freed_thread_remsets, INTERNAL_MEM_REMSET);
+               mono_sgen_free_internal_dynamic (freed_thread_remsets, remset_byte_size (freed_thread_remsets), INTERNAL_MEM_REMSET);
                freed_thread_remsets = next;
        }
 }
@@ -5713,7 +5720,7 @@ gc_register_current_thread (void *addr)
        remembered_set = info->remset;
 #endif
 
-       STORE_REMSET_BUFFER = mono_sgen_alloc_internal (sizeof (gpointer) * STORE_REMSET_BUFFER_SIZE, INTERNAL_MEM_STORE_REMSET);
+       STORE_REMSET_BUFFER = mono_sgen_alloc_internal (INTERNAL_MEM_STORE_REMSET);
        STORE_REMSET_BUFFER_INDEX = 0;
 
        DEBUG (3, fprintf (gc_debug_file, "registered thread %p (%p) (hash: %d)\n", info, (gpointer)info->id, hash));
@@ -5727,7 +5734,7 @@ gc_register_current_thread (void *addr)
 static void
 add_generic_store_remset_from_buffer (gpointer *buffer)
 {
-       GenericStoreRememberedSet *remset = mono_sgen_alloc_internal (sizeof (GenericStoreRememberedSet), INTERNAL_MEM_STORE_REMSET);
+       GenericStoreRememberedSet *remset = mono_sgen_alloc_internal (INTERNAL_MEM_STORE_REMSET);
        memcpy (remset->data, buffer + 1, sizeof (gpointer) * (STORE_REMSET_BUFFER_SIZE - 1));
        remset->next = generic_store_remsets;
        generic_store_remsets = remset;
@@ -5878,7 +5885,7 @@ mono_gc_pthread_detach (pthread_t thread)
 
 static RememberedSet*
 alloc_remset (int size, gpointer id) {
-       RememberedSet* res = mono_sgen_alloc_internal (sizeof (RememberedSet) + (size * sizeof (gpointer)), INTERNAL_MEM_REMSET);
+       RememberedSet* res = mono_sgen_alloc_internal_dynamic (sizeof (RememberedSet) + (size * sizeof (gpointer)), INTERNAL_MEM_REMSET);
        res->store_next = res->data;
        res->end_set = res->data + size;
        res->next = NULL;
@@ -6621,7 +6628,7 @@ mono_gc_ephemeron_array_add (MonoObject *obj)
 
        LOCK_GC;
 
-       node = mono_sgen_alloc_internal (sizeof (EphemeronLinkNode), INTERNAL_MEM_EPHEMERON_LINK);
+       node = mono_sgen_alloc_internal (INTERNAL_MEM_EPHEMERON_LINK);
        if (!node) {
                UNLOCK_GC;
                return FALSE;
@@ -6803,6 +6810,16 @@ mono_gc_base_init (void)
        mono_sgen_init_internal_allocator ();
        major_init ();
 
+       mono_sgen_register_fixed_internal_mem_type (INTERNAL_MEM_FRAGMENT, sizeof (Fragment));
+       mono_sgen_register_fixed_internal_mem_type (INTERNAL_MEM_SECTION, SIZEOF_GC_MEM_SECTION);
+       mono_sgen_register_fixed_internal_mem_type (INTERNAL_MEM_FINALIZE_ENTRY, sizeof (FinalizeEntry));
+       mono_sgen_register_fixed_internal_mem_type (INTERNAL_MEM_DISLINK, sizeof (DisappearingLink));
+       mono_sgen_register_fixed_internal_mem_type (INTERNAL_MEM_ROOT_RECORD, sizeof (RootRecord));
+       mono_sgen_register_fixed_internal_mem_type (INTERNAL_MEM_GRAY_QUEUE, sizeof (GrayQueueSection));
+       g_assert (sizeof (GenericStoreRememberedSet) == sizeof (gpointer) * STORE_REMSET_BUFFER_SIZE);
+       mono_sgen_register_fixed_internal_mem_type (INTERNAL_MEM_STORE_REMSET, sizeof (GenericStoreRememberedSet));
+       mono_sgen_register_fixed_internal_mem_type (INTERNAL_MEM_EPHEMERON_LINK, sizeof (EphemeronLinkNode));
+
        if ((env = getenv ("MONO_GC_DEBUG"))) {
                opts = g_strsplit (env, ",", -1);
                for (ptr = opts; ptr && *ptr; ptr ++) {
index 0bb27b5208d17e212352a71a228b7b086736b381..15d69747ba2bcdd7332668a00a7a680b516723c9 100644 (file)
@@ -211,11 +211,16 @@ void mono_sgen_report_internal_mem_usage (void) MONO_INTERNAL;
 void mono_sgen_report_internal_mem_usage_full (SgenInternalAllocator *alc) MONO_INTERNAL;
 void mono_sgen_dump_internal_mem_usage (FILE *heap_dump_file) MONO_INTERNAL;
 
-void* mono_sgen_alloc_internal (size_t size, int type) MONO_INTERNAL;
+void mono_sgen_register_fixed_internal_mem_type (int type, size_t size) MONO_INTERNAL;
+
+void* mono_sgen_alloc_internal (int type) MONO_INTERNAL;
 void mono_sgen_free_internal (void *addr, int type) MONO_INTERNAL;
 
+void* mono_sgen_alloc_internal_dynamic (size_t size, int type) MONO_INTERNAL;
+void mono_sgen_free_internal_dynamic (void *addr, size_t size, int type) MONO_INTERNAL;
+
 void* mono_sgen_alloc_internal_full (SgenInternalAllocator *allocator, size_t size, int type) MONO_INTERNAL;
-void mono_sgen_free_internal_full (SgenInternalAllocator *allocator, void *addr, int type) MONO_INTERNAL;
+void mono_sgen_free_internal_full (SgenInternalAllocator *allocator, void *addr, size_t size, int type) MONO_INTERNAL;
 
 void mono_sgen_debug_printf (int level, const char *format, ...) MONO_INTERNAL;
 
index 04b908817764c9e9f9aa7f37d05eebcc9e29bc44..cccb996800c05eeeaec10055663b8f406d29e975 100644 (file)
@@ -54,7 +54,7 @@ gray_object_alloc_queue_section (GrayQueue *queue)
                queue->free_list = section->next;
        } else {
                /* Allocate a new section */
-               section = mono_sgen_alloc_internal (sizeof (GrayQueueSection), INTERNAL_MEM_GRAY_QUEUE);
+               section = mono_sgen_alloc_internal (INTERNAL_MEM_GRAY_QUEUE);
        }
 
        section->end = 0;
index 74dc4d1031af1ef60b44b30dac133a02cb61a240..11a90ce42be6489e0543d28ec07b1a5991da98d9 100644 (file)
@@ -102,6 +102,12 @@ static const int freelist_sizes [] = {
        2336, 2728, 3272, 4096, 5456, 8192 };
 #define FREELIST_NUM_SLOTS (sizeof (freelist_sizes) / sizeof (freelist_sizes [0]))
 
+/*
+ * Slot indexes for the fixed INTERNAL_MEM_XXX types.  -1 if that type
+ * is dynamic.
+ */
+static int fixed_type_freelist_slots [INTERNAL_MEM_MAX];
+
 static SgenInternalAllocator unmanaged_allocator;
 
 #define LARGE_INTERNAL_MEM_HEADER_MAGIC        0x7d289f3a
@@ -195,6 +201,20 @@ slot_for_size (size_t size)
        return -1;
 }
 
+void
+mono_sgen_register_fixed_internal_mem_type (int type, size_t size)
+{
+       int slot;
+
+       g_assert (type >= 0 && type < INTERNAL_MEM_MAX);
+       g_assert (fixed_type_freelist_slots [type] == -1);
+
+       slot = slot_for_size (size);
+       g_assert (slot >= 0);
+
+       fixed_type_freelist_slots [type] = slot;
+}
+
 /*
  * Build a free list for @size memory chunks from the memory area between
  * start_page and end_page.
@@ -290,13 +310,52 @@ get_chunk_freelist (SgenPinnedChunk *chunk, int slot)
        return NULL;
 }
 
+/* LOCKING: assumes the internal allocator lock is held */
+static void*
+alloc_from_slot (SgenInternalAllocator *alc, int slot, int type)
+{
+       SgenPinnedChunk *pchunk;
+       void *res;
+       size_t size = freelist_sizes [slot];
+
+       alc->small_internal_mem_bytes [type] += size;
+
+       for (pchunk = alc->chunk_list; pchunk; pchunk = pchunk->block.next) {
+               void **p = pchunk->free_list [slot];
+               HEAVY_STAT (++stat_internal_alloc_loop1);
+               if (p) {
+                       pchunk->free_list [slot] = *p;
+
+                       memset (p, 0, size);
+                       return p;
+               }
+       }
+       for (pchunk = alc->chunk_list; pchunk; pchunk = pchunk->block.next) {
+               HEAVY_STAT (++stat_internal_alloc_loop2);
+               res = get_chunk_freelist (pchunk, slot);
+               if (res) {
+                       memset (res, 0, size);
+                       return res;
+               }
+       }
+       pchunk = alloc_pinned_chunk (type == INTERNAL_MEM_MANAGED);
+       /* FIXME: handle OOM */
+       pchunk->block.next = alc->chunk_list;
+       alc->chunk_list = pchunk;
+       res = get_chunk_freelist (pchunk, slot);
+
+       memset (res, 0, size);
+       return res;
+}
+
 /* used for the GC-internal data structures */
 void*
 mono_sgen_alloc_internal_full (SgenInternalAllocator *alc, size_t size, int type)
 {
        int slot;
        void *res = NULL;
-       SgenPinnedChunk *pchunk;
+
+       g_assert (fixed_type_freelist_slots [type] == -1);
 
        LOCK_INTERNAL_ALLOCATOR;
 
@@ -318,56 +377,37 @@ mono_sgen_alloc_internal_full (SgenInternalAllocator *alc, size_t size, int type
 
        slot = slot_for_size (size);
        g_assert (size <= freelist_sizes [slot]);
+       res = alloc_from_slot (alc, slot, type);
 
-       alc->small_internal_mem_bytes [type] += freelist_sizes [slot];
-
-       for (pchunk = alc->chunk_list; pchunk; pchunk = pchunk->block.next) {
-               void **p = pchunk->free_list [slot];
-               HEAVY_STAT (++stat_internal_alloc_loop1);
-               if (p) {
-                       pchunk->free_list [slot] = *p;
-
-                       UNLOCK_INTERNAL_ALLOCATOR;
+       UNLOCK_INTERNAL_ALLOCATOR;
 
-                       memset (p, 0, size);
-                       return p;
-               }
-       }
-       for (pchunk = alc->chunk_list; pchunk; pchunk = pchunk->block.next) {
-               HEAVY_STAT (++stat_internal_alloc_loop2);
-               res = get_chunk_freelist (pchunk, slot);
-               if (res) {
-                       UNLOCK_INTERNAL_ALLOCATOR;
+       return res;
+}
 
-                       memset (res, 0, size);
-                       return res;
-               }
-       }
-       pchunk = alloc_pinned_chunk (type == INTERNAL_MEM_MANAGED);
-       /* FIXME: handle OOM */
-       pchunk->block.next = alc->chunk_list;
-       alc->chunk_list = pchunk;
-       res = get_chunk_freelist (pchunk, slot);
+void*
+mono_sgen_alloc_internal (int type)
+{
+       void *res;
+       int slot = fixed_type_freelist_slots [type];
+       g_assert (slot >= 0);
 
+       LOCK_INTERNAL_ALLOCATOR;
+       res = alloc_from_slot (&unmanaged_allocator, slot, type);
        UNLOCK_INTERNAL_ALLOCATOR;
 
-       memset (res, 0, size);
        return res;
 }
 
 void*
-mono_sgen_alloc_internal (size_t size, int type)
+mono_sgen_alloc_internal_dynamic (size_t size, int type)
 {
        return mono_sgen_alloc_internal_full (&unmanaged_allocator, size, type);
 }
 
-void
-mono_sgen_free_internal_full (SgenInternalAllocator *alc, void *addr, int type)
+static gboolean
+free_from_slot (SgenInternalAllocator *alc, void *addr, int slot, int type)
 {
        SgenPinnedChunk *pchunk;
-       LargeInternalMemHeader *mh;
-       if (!addr)
-               return;
 
        LOCK_INTERNAL_ALLOCATOR;
 
@@ -385,14 +425,34 @@ mono_sgen_free_internal_full (SgenInternalAllocator *alc, void *addr, int type)
 
                        UNLOCK_INTERNAL_ALLOCATOR;
 
-                       return;
+                       return TRUE;
                }
        }
 
        UNLOCK_INTERNAL_ALLOCATOR;
 
+       return FALSE;
+}
+
+void
+mono_sgen_free_internal_full (SgenInternalAllocator *alc, void *addr, size_t size, int type)
+{
+       LargeInternalMemHeader *mh;
+
+       g_assert (fixed_type_freelist_slots [type] == -1);
+
+       if (!addr)
+               return;
+
+       if (size <= freelist_sizes [FREELIST_NUM_SLOTS - 1]) {
+               int slot = slot_for_size (size);
+               if (free_from_slot (alc, addr, slot, type))
+                       return;
+       }
+
        mh = (LargeInternalMemHeader*)((char*)addr - G_STRUCT_OFFSET (LargeInternalMemHeader, data));
        g_assert (mh->magic == LARGE_INTERNAL_MEM_HEADER_MAGIC);
+       g_assert (mh->size == size + sizeof (LargeInternalMemHeader));
        /* FIXME: do a CAS */
        large_internal_bytes_alloced -= mh->size;
        mono_sgen_free_os_memory (mh, mh->size);
@@ -401,7 +461,18 @@ mono_sgen_free_internal_full (SgenInternalAllocator *alc, void *addr, int type)
 void
 mono_sgen_free_internal (void *addr, int type)
 {
-       mono_sgen_free_internal_full (&unmanaged_allocator, addr, type);
+       gboolean res;
+       int slot = fixed_type_freelist_slots [type];
+       g_assert (slot >= 0);
+
+       res = free_from_slot (&unmanaged_allocator, addr, slot, type);
+       g_assert (res);
+}
+
+void
+mono_sgen_free_internal_dynamic (void *addr, size_t size, int type)
+{
+       mono_sgen_free_internal_full (&unmanaged_allocator, addr, size, type);
 }
 
 void
@@ -426,6 +497,11 @@ mono_sgen_dump_internal_mem_usage (FILE *heap_dump_file)
 void
 mono_sgen_init_internal_allocator (void)
 {
+       int i;
+
+       for (i = 0; i < INTERNAL_MEM_MAX; ++i)
+               fixed_type_freelist_slots [i] = -1;
+
 #ifdef HEAVY_STATISTICS
        mono_counters_register ("Internal allocs", MONO_COUNTER_GC | MONO_COUNTER_LONG, &stat_internal_alloc);
        mono_counters_register ("Internal alloc loop1", MONO_COUNTER_GC | MONO_COUNTER_LONG, &stat_internal_alloc_loop1);
index fb628054de59bbd5328536f332f495b6c5372bbd..c9c60d71060182e23d611683f7cb27cc693c9ffd 100644 (file)
@@ -84,7 +84,7 @@ obj_is_from_pinned_alloc (char *p)
 static void
 free_pinned_object (char *obj, size_t size)
 {
-       mono_sgen_free_internal_full (&pinned_allocator, obj, INTERNAL_MEM_MANAGED);
+       mono_sgen_free_internal_full (&pinned_allocator, obj, size, INTERNAL_MEM_MANAGED);
 }
 
 /*
@@ -104,7 +104,7 @@ alloc_major_section (void)
        mono_sgen_update_heap_boundaries ((mword)section->data, (mword)section->end_data);
        DEBUG (3, fprintf (gc_debug_file, "New major heap section: (%p-%p), total: %zd\n", section->data, section->end_data, total_alloc));
        scan_starts = (section->size + SCAN_START_SIZE - 1) / SCAN_START_SIZE;
-       section->scan_starts = mono_sgen_alloc_internal (sizeof (char*) * scan_starts, INTERNAL_MEM_SCAN_STARTS);
+       section->scan_starts = mono_sgen_alloc_internal_dynamic (sizeof (char*) * scan_starts, INTERNAL_MEM_SCAN_STARTS);
        section->num_scan_start = scan_starts;
        section->block.role = MEMORY_ROLE_GEN1;
        section->is_to_space = TRUE;
@@ -122,7 +122,8 @@ 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 (section->scan_starts, INTERNAL_MEM_SCAN_STARTS);
+       mono_sgen_free_internal_dynamic (section->scan_starts,
+                       (section->size + SCAN_START_SIZE - 1) / SCAN_START_SIZE * sizeof (char*), INTERNAL_MEM_SCAN_STARTS);
        mono_sgen_free_os_memory (section, MAJOR_SECTION_SIZE);
 
        --num_major_sections;
index 6f18c84d2ca913fa9034206b82c87132a4a74dff..557a3c0a5c744f9ef7717083f7de8132048c8fd2 100644 (file)
@@ -284,7 +284,7 @@ ms_alloc_block (int size_index, gboolean pinned, gboolean has_references)
 {
        int size = block_obj_sizes [size_index];
        int count = MS_BLOCK_FREE / size;
-       MSBlockInfo *info = mono_sgen_alloc_internal (sizeof (MSBlockInfo), INTERNAL_MEM_MS_BLOCK_INFO);
+       MSBlockInfo *info = mono_sgen_alloc_internal (INTERNAL_MEM_MS_BLOCK_INFO);
        MSBlockHeader *header;
        MSBlockInfo **free_blocks = FREE_BLOCKS (pinned, has_references);
        char *obj_start;
@@ -810,8 +810,10 @@ major_init (void)
 {
        int i;
 
+       mono_sgen_register_fixed_internal_mem_type (INTERNAL_MEM_MS_BLOCK_INFO, sizeof (MSBlockInfo));
+
        num_block_obj_sizes = ms_calculate_block_obj_sizes (MS_BLOCK_OBJ_SIZE_FACTOR, NULL);
-       block_obj_sizes = mono_sgen_alloc_internal (sizeof (int) * num_block_obj_sizes, INTERNAL_MEM_MS_TABLES);
+       block_obj_sizes = mono_sgen_alloc_internal_dynamic (sizeof (int) * num_block_obj_sizes, INTERNAL_MEM_MS_TABLES);
        ms_calculate_block_obj_sizes (MS_BLOCK_OBJ_SIZE_FACTOR, block_obj_sizes);
 
        /*
@@ -824,7 +826,7 @@ major_init (void)
        */
 
        for (i = 0; i < MS_BLOCK_TYPE_MAX; ++i)
-               free_block_lists [i] = mono_sgen_alloc_internal (sizeof (MSBlockInfo*) * num_block_obj_sizes, INTERNAL_MEM_MS_TABLES);
+               free_block_lists [i] = mono_sgen_alloc_internal_dynamic (sizeof (MSBlockInfo*) * num_block_obj_sizes, INTERNAL_MEM_MS_TABLES);
 
        for (i = 0; i < MS_NUM_FAST_BLOCK_OBJ_SIZE_INDEXES; ++i)
                fast_block_obj_size_indexes [i] = ms_find_block_obj_size_index (i * 8);
index 589bd554bb3837e057fcf062c8466ce19f1f814c..166d1f93380baf3669a82bd34af1a78ce4cd5d26 100644 (file)
@@ -54,7 +54,7 @@ pin_stats_tree_free (PinStatAddress *node)
                return;
        pin_stats_tree_free (node->left);
        pin_stats_tree_free (node->right);
-       mono_sgen_free_internal (node, INTERNAL_MEM_STATISTICS);
+       mono_sgen_free_internal_dynamic (node, sizeof (PinStatAddress), INTERNAL_MEM_STATISTICS);
 }
 
 static void
@@ -67,7 +67,7 @@ pin_stats_reset (void)
                pinned_byte_counts [i] = 0;
        while (pinned_objects) {
                ObjectList *next = pinned_objects->next;
-               mono_sgen_free_internal (pinned_objects, INTERNAL_MEM_STATISTICS);
+               mono_sgen_free_internal_dynamic (pinned_objects, sizeof (ObjectList), INTERNAL_MEM_STATISTICS);
                pinned_objects = next;
        }
 }
@@ -91,7 +91,7 @@ pin_stats_register_address (char *addr, int pin_type)
                        node_ptr = &node->right;
        }
 
-       node = mono_sgen_alloc_internal (sizeof (PinStatAddress), INTERNAL_MEM_STATISTICS);
+       node = mono_sgen_alloc_internal_dynamic (sizeof (PinStatAddress), INTERNAL_MEM_STATISTICS);
        node->addr = addr;
        node->pin_types = pin_type_bit;
        node->left = node->right = NULL;
@@ -124,7 +124,7 @@ static void
 pin_stats_register_object (char *obj, size_t size)
 {
        int pin_types = 0;
-       ObjectList *list = mono_sgen_alloc_internal (sizeof (ObjectList), INTERNAL_MEM_STATISTICS);
+       ObjectList *list = mono_sgen_alloc_internal_dynamic (sizeof (ObjectList), INTERNAL_MEM_STATISTICS);
        pin_stats_count_object_from_tree (obj, size, pin_stat_addresses, &pin_types);
        list->obj = (MonoObject*)obj;
        list->next = pinned_objects;
index 760cfcc678d8300900cb3692a308fa17a0a91de8..cef6396d0f9e776e381a411e021a99b529913759 100644 (file)
@@ -40,9 +40,9 @@ 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 (sizeof (void*) * new_size, INTERNAL_MEM_PIN_QUEUE);
+       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 (pin_queue, INTERNAL_MEM_PIN_QUEUE);
+       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));