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_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_region(void *start) { char *cur = start; DBG(("%p - %p", start, sml_heap_to_space.free)); while (cur < sml_heap_to_space.free) { forward_children(cur); cur += HEAP_ROUND_SIZE(OBJ_TOTAL_SIZE(cur)); } }
static size_t heap_filled(struct heap_space *heap, size_t *ret_bytes) { char *p = HEAP_START(*heap); size_t filled = 0, count = 0; while (p < heap->free) { count++; filled += OBJ_TOTAL_SIZE(p); p += HEAP_ROUND_SIZE(OBJ_TOTAL_SIZE(p)); } if (ret_bytes) *ret_bytes = filled; return count; }
/* for debug */ void sml_heap_dump() { char *cur; unsigned int size, allocsize; sml_debug("from space : %p - %p\n", HEAP_START(sml_heap_from_space), sml_heap_from_space.limit); cur = HEAP_START(sml_heap_from_space); while (cur < sml_heap_from_space.free) { size = OBJ_TOTAL_SIZE(cur); allocsize = HEAP_ROUND_SIZE(size); sml_debug("%p : type=%08x, size=%u, total=%u, alloc=%u\n", cur, OBJ_TYPE(cur), OBJ_SIZE(cur), size, allocsize); cur += allocsize; } }
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; }
static void mark(void **slot) { struct bitmap_info_space *b_info; unsigned int obj_size, alloc_size; unsigned int tmp,tmp_index; unsigned int *tmp_bitmap; void *obj = *slot; #ifdef PRINT_ALLOC_TIME count_call_mark++; #endif /* PRINT_ALLOC_TIME */ #define OUTSIDE(obj) do{trace_outside(obj); return;}while(0) MAPPING_HEAP_MARK(obj,b_info,slot,OUTSIDE); #undef OUTSIDE //marked check and mark tmp = FROM_HEAP_TO_BITMAP(b_info,obj); tmp_index = tmp >> 5; tmp_bitmap = (unsigned int *)b_info->base + tmp_index; tmp = (unsigned int)0x01 << (tmp & 0x0000001f); #ifdef GCSTAT gcstat.last.trace_count++; #endif /* GCSTAT */ if(*tmp_bitmap & tmp) { DBG(("%p at %p already marked", obj, slot)); #ifdef PRINT_ALLOC_TIME count_not_mark++; #endif /* PRINT_ALLOC_TIME */ return; } *tmp_bitmap |= tmp; //mark //tree check unsigned int i; for(i=0; (*tmp_bitmap == 0xffffffff)&&(i < b_info->rank); i++) { tmp = ((unsigned int)0x01 << (tmp_index & 0x0000001f)); tmp_index >>= 5; tmp_bitmap = (unsigned int *)b_info->tree[i] + tmp_index; *tmp_bitmap |= tmp; } DBG(("%p at %p mark (%"PRIuMAX", %"PRIuMAX")", obj, slot, (intmax_t)obj_size, (intmax_t)alloc_size)); #ifdef PRINT_ALLOC_TIME print_info[b_info - bitmap_info].count_mark++; live_tmp += HEAP_ROUND_SIZE(OBJ_TOTAL_SIZE(obj)); #endif /* PRINT_ALLOC_TIME */ /* STACK_PUSH */ (*(marking_stack.top)) = obj; marking_stack.top++; #ifdef GCSTAT gcstat.last.push_count++; #endif /* GCSTAT */ }
SML_PRIMITIVE void sml_write(void *objaddr, void **writeaddr, void *new_value) { *writeaddr = new_value; #ifndef NOT_CLEAR_BITMAP if (IS_IN_HEAP_SPACE(writeaddr)) return; /* remember the writeaddr as a root pointer which is outside * of the heap. */ sml_global_barrier(writeaddr, objaddr); #else /* NOT_CLEAR_BITMAP */ struct bitmap_info_space *b_info; unsigned int obj_size, alloc_size; unsigned int tmp,tmp_index; unsigned int *tmp_bitmap; void *obj = *writeaddr; if (!(IS_IN_HEAP_SPACE(writeaddr))) sml_global_barrier(writeaddr, objaddr); #ifdef PRINT_ALLOC_TIME count_call_mark++; #endif /* PRINT_ALLOC_TIME */ #define OUTSIDE(obj) do{trace_outside(obj); return;}while(0) MAPPING_HEAP_MARK(obj,b_info,NULL,OUTSIDE); #undef OUTSIDE //marked check and mark tmp = FROM_HEAP_TO_BITMAP(b_info,obj); tmp_index = tmp >> 5; tmp_bitmap = (unsigned int *)b_info->base + tmp_index; tmp = (unsigned int)0x01 << (tmp & 0x0000001f); if(*tmp_bitmap & tmp) { DBG(("%p at %p already marked", obj, NULL)); #ifdef PRINT_ALLOC_TIME count_not_mark++; #endif /* PRINT_ALLOC_TIME */ return; } *tmp_bitmap |= tmp; //mark //tree check unsigned int i; for(i=0; (*tmp_bitmap == 0xffffffff)&&(i < b_info->rank); i++) { tmp = ((unsigned int)0x01 << (tmp_index & 0x0000001f)); tmp_index >>= 5; tmp_bitmap = (unsigned int *)b_info->tree[i] + tmp_index; *tmp_bitmap |= tmp; } DBG(("%p at %p mark (%"PRIuMAX", %"PRIuMAX")", obj, NULL, (intmax_t)obj_size, (intmax_t)alloc_size)); #ifdef PRINT_ALLOC_TIME print_info[b_info - bitmap_info].count_mark++; live_tmp += HEAP_ROUND_SIZE(OBJ_TOTAL_SIZE(obj)); #endif /* PRINT_ALLOC_TIME */ /* STACK_PUSH */ (*(marking_stack.top)) = obj; marking_stack.top++; #endif /* NOT_CLEAR_BITMAP */ }