Add heap size accounting.
authorRodrigo Kumpera <kumpera@gmail.com>
Fri, 5 Nov 2010 15:38:44 +0000 (13:38 -0200)
committerRodrigo Kumpera <kumpera@gmail.com>
Wed, 10 Nov 2010 19:35:49 +0000 (17:35 -0200)
* sgen-gc.c: Simple accounting with no los/major reserve.

* sgen-los.c:
* sgen-marksweep.c: Account for allocation and release of
memory. Fail to allocate if above alloc quota.

mono/metadata/sgen-gc.c
mono/metadata/sgen-gc.h
mono/metadata/sgen-los.c
mono/metadata/sgen-marksweep.c

index 33dcf6d3ae5d41e33e335babdc47e7b8c114fb62..7d0dd7823512568f73e3562cd04b5c9ce9702dd0 100644 (file)
@@ -712,6 +712,29 @@ static MonoVTable *array_fill_vtable;
  */
 /*heap limits*/
 static mword max_heap_size = ((mword)0)- ((mword)1);
+static mword allocated_heap;
+
+void
+mono_sgen_release_space (mword size, int space)
+{
+       allocated_heap -= size;
+}
+
+static size_t
+available_free_space (void)
+{
+       return max_heap_size - MIN (allocated_heap, max_heap_size);
+}
+
+gboolean
+mono_sgen_try_alloc_space (mword size, int space)
+{
+       if (available_free_space () < size)
+               return FALSE;
+
+       allocated_heap += size;
+       return TRUE;
+}
 
 static void
 init_heap_size_limits (glong max_heap)
index 57279da30b9d99bca2ae1ef263e1aba1c0698564..271ba7c654b0a53f0e141232c955ad799cdf24e8 100644 (file)
@@ -736,4 +736,13 @@ mono_sgen_par_object_get_size (MonoVTable *vtable, MonoObject* o)
 
 #define mono_sgen_safe_object_get_size(o)              mono_sgen_par_object_get_size ((MonoVTable*)SGEN_LOAD_VTABLE ((o)), (o))
 
+
+enum {
+       SPACE_MAJOR,
+       SPACE_LOS
+};
+
+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;
 #endif /* __MONO_SGENGC_H__ */
index 698c57dd5a312be8cf3483961ef5bc47cf892852..9d0b4f46086ca17e106b667fa196b5145771470b 100644 (file)
@@ -241,6 +241,9 @@ get_los_section_memory (size_t size)
        if (free_chunks)
                return (LOSObject*)free_chunks;
 
+       if (!mono_sgen_try_alloc_space (LOS_SECTION_SIZE, SPACE_LOS))
+               return NULL;
+
        section = mono_sgen_alloc_os_memory_aligned (LOS_SECTION_SIZE, LOS_SECTION_SIZE, TRUE);
 
        free_chunks = (LOSFreeChunks*)((char*)section + LOS_CHUNK_SIZE);
@@ -314,6 +317,7 @@ free_large_object (LOSObject *obj)
                size += pagesize - 1;
                size &= ~(pagesize - 1);
                mono_sgen_free_os_memory (obj, size);
+               mono_sgen_release_space (size, SPACE_LOS);
        } else {
                free_los_section_memory (obj, size + sizeof (LOSObject));
 #ifdef LOS_CONSISTENCY_CHECKS
@@ -333,7 +337,7 @@ free_large_object (LOSObject *obj)
 static void* __attribute__((noinline))
 alloc_large_inner (MonoVTable *vtable, size_t size)
 {
-       LOSObject *obj;
+       LOSObject *obj = NULL;
        void **vtslot;
 
        g_assert (size > MAX_SMALL_OBJ_SIZE);
@@ -365,16 +369,19 @@ alloc_large_inner (MonoVTable *vtable, size_t size)
                alloc_size += sizeof (LOSObject);
                alloc_size += pagesize - 1;
                alloc_size &= ~(pagesize - 1);
-               /* FIXME: handle OOM */
-               obj = mono_sgen_alloc_os_memory (alloc_size, TRUE);
-               obj->huge_object = TRUE;
+               if (mono_sgen_try_alloc_space (alloc_size, SPACE_LOS)) {
+                       obj = mono_sgen_alloc_os_memory (alloc_size, TRUE);
+                       obj->huge_object = TRUE;
+               }
        } else {
                obj = get_los_section_memory (size + sizeof (LOSObject));
-               memset (obj, 0, size + sizeof (LOSObject));
+               if (obj)
+                       memset (obj, 0, size + sizeof (LOSObject));
        }
 #endif
 #endif
-
+       if (!obj)
+               return NULL;
        g_assert (!((mword)obj->data & (ALLOC_ALIGN - 1)));
        obj->size = size;
        vtslot = (void**)obj->data;
@@ -414,6 +421,7 @@ los_sweep (void)
                        else
                                los_sections = next;
                        mono_sgen_free_os_memory (section, LOS_SECTION_SIZE);
+                       mono_sgen_release_space (LOS_SECTION_SIZE, SPACE_LOS);
                        section = next;
                        --los_num_sections;
                        continue;
index ae141a3b620abcb3b70a90526c183d04b6e6680f..161cd107fed4900db9ba4a984cca7b4a60cb3bed 100644 (file)
@@ -317,6 +317,7 @@ ms_free_block (MSBlockInfo *block)
        block->next_free = empty_blocks;
        empty_blocks = block;
        block->used = FALSE;
+       mono_sgen_release_space (MS_BLOCK_SIZE, SPACE_MAJOR);
 }
 #else
 static void*
@@ -373,6 +374,7 @@ ms_free_block (void *block)
 {
        void *empty;
 
+       mono_sgen_release_space (MS_BLOCK_SIZE, SPACE_MAJOR);
        memset (block, 0, MS_BLOCK_SIZE);
 
        do {
@@ -474,21 +476,28 @@ consistency_check (void)
 }
 #endif
 
-static void
+static gboolean
 ms_alloc_block (int size_index, gboolean pinned, gboolean has_references)
 {
        int size = block_obj_sizes [size_index];
        int count = MS_BLOCK_FREE / size;
-#ifdef FIXED_HEAP
-       MSBlockInfo *info = ms_get_empty_block ();
-#else
-       MSBlockInfo *info = mono_sgen_alloc_internal (INTERNAL_MEM_MS_BLOCK_INFO);
+       MSBlockInfo *info;
+#ifndef FIXED_HEAP
        MSBlockHeader *header;
 #endif
        MSBlockInfo **free_blocks = FREE_BLOCKS (pinned, has_references);
        char *obj_start;
        int i;
 
+       if (!mono_sgen_try_alloc_space (MS_BLOCK_SIZE, SPACE_MAJOR))
+               return FALSE;
+
+#ifdef FIXED_HEAP
+       info = ms_get_empty_block ();
+#else
+       info = mono_sgen_alloc_internal (INTERNAL_MEM_MS_BLOCK_INFO);
+#endif
+
        DEBUG (9, g_assert (count >= 2));
 
        info->obj_size = size;
@@ -527,6 +536,7 @@ ms_alloc_block (int size_index, gboolean pinned, gboolean has_references)
 #endif
 
        ++num_major_sections;
+       return TRUE;
 }
 
 static gboolean