SML_PRIMITIVE NOINLINE void * sml_alloc(unsigned int objsize) { /* objsize = payload_size + bitmap_size */ void *obj; size_t inc = HEAP_ROUND_SIZE(OBJ_HEADER_SIZE + objsize); #ifdef FAIR_COMPARISON if (inc > 4096) { SAVE_FP(); return sml_obj_malloc(inc); } #endif /* FAIR_COMPARISON */ GIANT_LOCK(); obj = sml_heap_from_space.free; if ((size_t)(sml_heap_from_space.limit - (char*)obj) >= inc) { sml_heap_from_space.free += inc; #ifdef GC_STAT sml_heap_alloced(inc); #endif /* GC_STAT */ GIANT_UNLOCK(); } else { SAVE_FP(); obj = slow_alloc(inc); } #ifndef FAIR_COMPARISON OBJ_HEADER(obj) = 0; #endif /* FAIR_COMPARISON */ return obj; }
sml_intinf_t * sml_intinf_new() { sml_intinf_t *obj; assert(sml_saved()); obj = sml_alloc(sizeof(sml_intinf_t)); OBJ_HEADER(obj) = OBJ_HEADER_WORD(OBJTYPE_INTINF, sizeof(sml_intinf_t)); sml_set_finalizer(obj, intinf_free); sml_intinf_init(obj); return obj; }
SML_PRIMITIVE void * sml_alloc(unsigned int objsize) { unsigned int headersize = ALIGNSIZE(OBJ_HEADER_SIZE, sizeof(void*)); char *m, *p; m = GC_MALLOC(objsize + headersize); p = m + headersize; #ifndef FAIR_COMPARISON OBJ_HEADER(p) = 0; #endif /* FAIR_COMPARISON */ return p; }
SML_PRIMITIVE void * sml_alloc(unsigned int objsize, void *frame_pointer) { /* objsize = payload_size + bitmap_size */ void *obj; size_t inc = HEAP_ROUND_SIZE(OBJ_HEADER_SIZE + objsize); HEAP_FAST_ALLOC(obj, inc, (sml_save_frame_pointer(frame_pointer), sml_heap_slow_alloc(inc))); OBJ_HEADER(obj) = 0; return obj; }
static void forward(void **slot) { void *obj = *slot; size_t obj_size, alloc_size; void *newobj; if (!IS_IN_HEAP_SPACE(sml_heap_from_space, obj)) { DBG(("%p at %p outside", obj, slot)); ASSERT(!IS_IN_HEAP_SPACE(sml_heap_to_space, obj)); if (obj != NULL) sml_trace_ptr(obj); return; } if (OBJ_FORWARDED(obj)) { *slot = OBJ_FORWARD_PTR(obj); GCSTAT_FORWARD_COUNT(); DBG(("%p at %p forward -> %p", obj, slot, *slot)); return; } obj_size = OBJ_TOTAL_SIZE(obj); alloc_size = HEAP_ROUND_SIZE(obj_size); ASSERT(HEAP_REST(sml_heap_to_space) >= alloc_size); newobj = sml_heap_to_space.free; sml_heap_to_space.free += alloc_size; memcpy(&OBJ_HEADER(newobj), &OBJ_HEADER(obj), obj_size); GCSTAT_COPY_COUNT(obj_size); DBG(("%p at %p copy -> %p (%lu/%lu)", obj, slot, newobj, (unsigned long)obj_size, (unsigned long)alloc_size)); OBJ_HEADER(obj) |= GC_FORWARDED_FLAG; OBJ_FORWARD_PTR(obj) = newobj; *slot = newobj; }
void * sml_record_alloc(size_t payload_size) { void *obj; size_t bitmap_size; ASSERT(((unsigned int)payload_size & OBJ_SIZE_MASK) == payload_size); payload_size = ALIGNSIZE(payload_size, sizeof(void*)); bitmap_size = OBJ_BITMAPS_LEN(payload_size) * SIZEOF_BITMAP; obj = sml_alloc(payload_size + bitmap_size, sml_load_frame_pointer()); OBJ_HEADER(obj) = OBJ_HEADER_WORD(OBJTYPE_RECORD, payload_size); ASSERT(OBJ_SIZE(obj) == payload_size); ASSERT(OBJ_TYPE(obj) == OBJTYPE_RECORD); ASSERT(OBJ_GC1(obj) == 0 && OBJ_GC2(obj) == 0); return obj; }
void * sml_obj_alloc(unsigned int objtype, size_t payload_size) { void *obj; ASSERT(((unsigned int)payload_size & OBJ_SIZE_MASK) == payload_size); obj = sml_alloc(payload_size, sml_load_frame_pointer()); OBJ_HEADER(obj) = OBJ_HEADER_WORD(objtype, payload_size); ASSERT(OBJ_SIZE(obj) == payload_size); ASSERT(OBJ_TYPE(obj) == OBJTYPE_UNBOXED_VECTOR || OBJ_TYPE(obj) == OBJTYPE_BOXED_VECTOR || OBJ_TYPE(obj) == OBJTYPE_UNBOXED_ARRAY || OBJ_TYPE(obj) == OBJTYPE_BOXED_ARRAY); ASSERT(OBJ_GC1(obj) == 0 && OBJ_GC2(obj) == 0); return obj; }
void * sml_obj_alloc(unsigned int objtype, size_t payload_size) { void *obj; assert(sml_saved()); assert(((unsigned int)payload_size & OBJ_SIZE_MASK) == payload_size); obj = sml_alloc(payload_size); OBJ_HEADER(obj) = OBJ_HEADER_WORD(objtype, payload_size); assert(OBJ_SIZE(obj) == payload_size); assert(OBJ_TYPE(obj) == OBJTYPE_UNBOXED_VECTOR || OBJ_TYPE(obj) == OBJTYPE_BOXED_VECTOR || OBJ_TYPE(obj) == OBJTYPE_UNBOXED_ARRAY || OBJ_TYPE(obj) == OBJTYPE_BOXED_ARRAY || OBJ_TYPE(obj) == OBJTYPE_INTINF); 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; }