static NOINLINE void * slow_alloc(size_t obj_size) { void *obj; GCSTAT_TRIGGER(obj_size); do_gc(); if (HEAP_REST(sml_heap_from_space) >= obj_size) { obj = sml_heap_from_space.free; sml_heap_from_space.free += obj_size; #ifdef GC_STAT sml_heap_alloced(obj_size); #endif /* GC_STAT */ } else { #ifdef GCSTAT stat_notice("---"); stat_notice("event: error"); stat_notice("heap exceeded: intented to allocate %lu bytes.", (unsigned long)obj_size); if (gcstat.file) fclose(gcstat.file); #endif /* GCSTAT */ sml_fatal(0, "heap exceeded: intended to allocate %lu bytes.", (unsigned long)obj_size); } GIANT_UNLOCK(); #ifndef FAIR_COMPARISON sml_run_finalizer(); #endif /* FAIR_COMPARISON */ return obj; }
SML_PRIMITIVE void * sml_alloc(unsigned int objsize, void *frame_pointer) { size_t alloc_size; unsigned int blocksize_log2; struct alloc_ptr *ptr; void *obj; /* ensure that alloc_size is at least BLOCKSIZE_MIN. */ alloc_size = ALIGNSIZE(OBJ_HEADER_SIZE + objsize, BLOCKSIZE_MIN); if (alloc_size > BLOCKSIZE_MAX) { GCSTAT_ALLOC_COUNT(malloc, 0, alloc_size); sml_save_frame_pointer(frame_pointer); return sml_obj_malloc(alloc_size); } blocksize_log2 = CEIL_LOG2(alloc_size); ASSERT(BLOCKSIZE_MIN_LOG2 <= blocksize_log2 && blocksize_log2 <= BLOCKSIZE_MAX_LOG2); ptr = &ALLOC_PTR_SET()->alloc_ptr[blocksize_log2]; if (!BITPTR_TEST(ptr->freebit)) { GCSTAT_ALLOC_COUNT(fast, blocksize_log2, alloc_size); BITPTR_INC(ptr->freebit); obj = ptr->free; ptr->free += ptr->blocksize_bytes; goto alloced; } sml_save_frame_pointer(frame_pointer); if (ptr->free != NULL) { obj = find_bitmap(ptr); if (obj) goto alloced; } obj = find_segment(ptr); if (obj) goto alloced; GCSTAT_TRIGGER(blocksize_log2); do_gc(MAJOR); obj = find_segment(ptr); if (obj) goto alloced_major; extend_heap(heap_space.extend_step); obj = find_segment(ptr); if (obj) goto alloced_major; sml_fatal(0, "heap exceeded: intended to allocate %u bytes.", ptr->blocksize_bytes); alloced_major: ASSERT(check_newobj(obj)); /* NOTE: sml_run_finalizer may cause garbage collection. */ obj = sml_run_finalizer(obj); goto finished; alloced: ASSERT(check_newobj(obj)); finished: OBJ_HEADER(obj) = 0; return obj; }