* 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.
*/
/*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)
#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__ */
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);
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
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);
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;
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;
block->next_free = empty_blocks;
empty_blocks = block;
block->used = FALSE;
+ mono_sgen_release_space (MS_BLOCK_SIZE, SPACE_MAJOR);
}
#else
static void*
{
void *empty;
+ mono_sgen_release_space (MS_BLOCK_SIZE, SPACE_MAJOR);
memset (block, 0, MS_BLOCK_SIZE);
do {
}
#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;
#endif
++num_major_sections;
+ return TRUE;
}
static gboolean