From: Michael D. Lowis Date: Tue, 21 Apr 2015 01:36:29 +0000 (-0400) Subject: finished testing heap.c X-Git-Url: https://git.mdlowis.com/?a=commitdiff_plain;h=98b97726b599023cf82c9a106fff517b1262c929;p=archive%2Fatc.git finished testing heap.c --- diff --git a/source/runtime/gc.c b/source/runtime/gc.c index 985f7f9..a21f909 100644 --- a/source/runtime/gc.c +++ b/source/runtime/gc.c @@ -4,10 +4,10 @@ #include #include -typedef struct { - uint64_t objmap; - uint8_t data[]; -} obj_t; +//typedef struct { +// uint64_t objmap; +// uint8_t data[]; +//} obj_t; typedef struct root_t { struct root_t* next; @@ -41,17 +41,20 @@ void gc_add_root(void* address, size_t size) void* gc_object(uint64_t objmap, size_t num_slots) { - obj_t* obj = heap_allocate(Heap, num_slots+1); - obj->objmap = objmap; - obj++; - return obj; + (void)objmap; + (void)num_slots; + return NULL; +// obj_t* obj = heap_allocate(Heap, num_slots+1); +// obj->objmap = objmap; +// obj++; +// return obj; } void* gc_allocate(size_t size) { size_t slot_sz = sizeof(uintptr_t); size_t num_slots = (size + slot_sz - 1) / slot_sz; - return heap_allocate(Heap, num_slots + 1); + return heap_allocate(Heap, UINT16_MAX, num_slots + 1); } static void gc_scan_object(void* object) { diff --git a/source/runtime/heap.c b/source/runtime/heap.c index 22e710f..cc72f5c 100644 --- a/source/runtime/heap.c +++ b/source/runtime/heap.c @@ -52,9 +52,8 @@ void heap_destroy(heap_t* heap) free(heap); } -static void* allocate_small_block(heap_t* heap, uintptr_t num_slots) +static void* allocate_small_block(heap_t* heap, uint64_t ptrmap, uintptr_t num_slots) { - void* object; uintptr_t index = (num_slots >= MIN_NUM_SLOTS) ? (num_slots - HEAP_INDEX_OFFSET) : 0; /* If we dont have any available segments, allocate a new one */ if (NULL == heap->heaps[index].available) { @@ -62,7 +61,8 @@ static void* allocate_small_block(heap_t* heap, uintptr_t num_slots) splaytree_insert(heap->segments, (uintptr_t)&(heap->heaps[index].available->start[0]), heap->heaps[index].available); } /* Allocate the object */ - object = segment_alloc(heap->heaps[index].available); + obj_t* obj = (obj_t*)segment_alloc(heap->heaps[index].available); + obj->objmap = ptrmap; /* If we filled it up then move it to the full list */ if (segment_full(heap->heaps[index].available)) { segment_t* current = heap->heaps[index].available; @@ -70,25 +70,27 @@ static void* allocate_small_block(heap_t* heap, uintptr_t num_slots) current->next = heap->heaps[index].full; heap->heaps[index].full = current; } - return object; + return (void*)(obj+1); } -static void* allocate_large_block(heap_t* heap, uintptr_t num_slots) +static void* allocate_large_block(heap_t* heap, uint64_t ptrmap, uintptr_t num_slots) { uintptr_t size = (num_slots * sizeof(uintptr_t)); block_t* blk = (block_t*)malloc(sizeof(block_t) + size); blk->size = size; splaytree_insert(heap->blocks, (uintptr_t)&blk->data[0], blk); - return (&blk->data[0]); + obj_t* obj = (obj_t*)(&blk->data[0]); + obj->objmap = ptrmap; + return (obj_t*)(obj+1); } -void* heap_allocate(heap_t* heap, uintptr_t num_slots) +void* heap_allocate(heap_t* heap, uint64_t ptrmap, uintptr_t num_slots) { void* obj = NULL; if (num_slots <= MAX_NUM_SLOTS) { - obj = allocate_small_block(heap, num_slots); + obj = allocate_small_block(heap, ptrmap, num_slots); } else { - obj = allocate_large_block(heap, num_slots); + obj = allocate_large_block(heap, ptrmap, num_slots); } return obj; } @@ -97,6 +99,10 @@ void heap_start_collection(heap_t* heap) { heap->greylist = heap->blocks; heap->blocks = splaytree_create((del_fn_t)free, (cmp_fn_t)block_compare); + for (unsigned int i = 0; i < NUM_HEAP_STACKS; i++) { + segment_clear_map(heap->heaps[i].available); + segment_clear_map(heap->heaps[i].full); + } } void heap_finish_collection(heap_t* heap) @@ -130,7 +136,7 @@ void heap_finish_collection(heap_t* heap) void* heap_find_and_mark(heap_t* heap, uintptr_t addr) { - void* obj = NULL; + obj_t* obj = NULL; segment_t* seg = splaytree_lookup(heap->segments, addr); if (NULL != seg) { obj = segment_find_and_mark(seg, addr); @@ -138,9 +144,9 @@ void* heap_find_and_mark(heap_t* heap, uintptr_t addr) block_t* block = splaytree_delete(heap->greylist, addr); if (NULL != block) { splaytree_insert(heap->blocks, addr, block); - obj = &block->data[0]; + obj = (obj_t*)&block->data[0]; } } - return obj; + return (obj == NULL) ? NULL : (void*)(obj+1); } diff --git a/source/runtime/heap.h b/source/runtime/heap.h index 7779c8d..db1eaa8 100644 --- a/source/runtime/heap.h +++ b/source/runtime/heap.h @@ -16,6 +16,11 @@ #define NUM_HEAP_STACKS (MAX_NUM_SLOTS) +typedef struct { + uint64_t objmap; + uint8_t data[]; +} obj_t; + typedef struct block_t { uintptr_t size; uintptr_t data[]; @@ -35,7 +40,7 @@ heap_t* heap_create(void); void heap_destroy(heap_t* heap); -void* heap_allocate(heap_t* heap, uintptr_t num_slots); +void* heap_allocate(heap_t* heap, uint64_t ptrmap, uintptr_t num_slots); void heap_start_collection(heap_t* heap); diff --git a/source/runtime/segment.c b/source/runtime/segment.c index 92e09f0..268f0f6 100644 --- a/source/runtime/segment.c +++ b/source/runtime/segment.c @@ -73,7 +73,10 @@ void* segment_alloc(segment_t* seg) { void segment_clear_map(segment_t* seg) { - memset(seg->blockmap, 0xFFu, sizeof(seg->blockmap)); + while (NULL != seg) { + memset(seg->blockmap, 0xFFu, sizeof(seg->blockmap)); + seg = seg->next; + } } void* segment_find_and_mark(segment_t* seg, uintptr_t addr) { diff --git a/tests/test_heap.c b/tests/test_heap.c index e1a9cde..b43fc46 100644 --- a/tests/test_heap.c +++ b/tests/test_heap.c @@ -1,15 +1,16 @@ #include "atf.h" #include "heap.h" - #include "gc.h" +#include + TEST_SUITE(Heap) { /* Verify: heap_create *************************************************************************/ TEST(Verify_Create_allocates_and_initializes_a_heap) { heap_t* heap = heap_create(); CHECK(heap != NULL); - CHECK(NULL != heap_allocate(heap, 64)); - CHECK(NULL != heap_allocate(heap, 65)); + CHECK(NULL != heap_allocate(heap, 0, 64)); + CHECK(NULL != heap_allocate(heap, 0, 65)); heap_destroy(heap); } @@ -17,17 +18,17 @@ TEST_SUITE(Heap) { *************************************************************************/ TEST(Verify_Allocate_should_allocate_a_new_segment_if_the_subheap_is_empty) { heap_t* heap = heap_create(); - CHECK(NULL != heap_allocate(heap, 1)); + CHECK(NULL != heap_allocate(heap, 0, 1)); CHECK(heap->heaps[0].available != NULL); heap_destroy(heap); } TEST(Verify_Allocate_should_allocate_a_new_segment_if_the_current_segment_is_full) { heap_t* heap = heap_create(); - CHECK(NULL != heap_allocate(heap, 1)); + CHECK(NULL != heap_allocate(heap, 0, 1)); heap->heaps[0].available->blockmap[0] = 1 << ((sizeof(uint16_t) * 8) - 1); heap->heaps[0].available->blockmap[16] = 1 << ((sizeof(uint16_t) * 8) - 1); - CHECK(NULL != heap_allocate(heap, 1)); + CHECK(NULL != heap_allocate(heap, 0, 1)); CHECK(heap->heaps[0].available == NULL); CHECK(heap->heaps[0].full != NULL); CHECK(heap->heaps[0].full->next == NULL); @@ -36,14 +37,14 @@ TEST_SUITE(Heap) { TEST(Verify_Allocate_should_allocate_the_minimum_size_if_num_slots_is_less_than_the_minimum) { heap_t* heap = heap_create(); - CHECK(NULL != heap_allocate(heap, 0)); + CHECK(NULL != heap_allocate(heap, 0, 0)); CHECK(heap->heaps[0].available != NULL); heap_destroy(heap); } TEST(Verify_Allocate_should_allocate_a_large_block_if_the_number_of_slots_is_greater_than_the_max) { heap_t* heap = heap_create(); - CHECK(NULL != heap_allocate(heap, 65)); + CHECK(NULL != heap_allocate(heap, 0, 65)); CHECK(NULL != heap->blocks->root->value); heap_destroy(heap); } @@ -73,10 +74,10 @@ TEST_SUITE(Heap) { TEST(Verify_finish_collection_moves_segments_from_the_full_list_to_the_available_list_when_some_blocks_are_reclaimed) { heap_t* heap = heap_create(); segment_t* seg = segment_create(2, NULL); - seg->blockmap[0] = 42; splaytree_t* blocks = heap->blocks; heap->heaps[1].full = seg; heap_start_collection(heap); + seg->blockmap[0] = 42; heap_finish_collection(heap); CHECK(blocks != heap->blocks); CHECK(heap->heaps[1].available == seg); @@ -88,11 +89,11 @@ TEST_SUITE(Heap) { heap_t* heap = heap_create(); segment_t* seg2 = segment_create(2, NULL); segment_t* seg1 = segment_create(2, seg2); - seg1->blockmap[0] = 0; - seg2->blockmap[0] = 42; splaytree_t* blocks = heap->blocks; heap->heaps[1].full = seg1; heap_start_collection(heap); + seg1->blockmap[0] = 0; + seg2->blockmap[0] = 42; heap_finish_collection(heap); CHECK(blocks != heap->blocks); CHECK(heap->heaps[1].available == seg2); @@ -117,10 +118,10 @@ TEST_SUITE(Heap) { heap_t* heap = heap_create(); segment_t* seg2 = segment_create(2, NULL); segment_t* seg1 = segment_create(2, seg2); - seg1->blockmap[0] = 0; splaytree_t* blocks = heap->blocks; heap->heaps[1].full = seg1; heap_start_collection(heap); + seg1->blockmap[0] = 0; heap_finish_collection(heap); CHECK(blocks != heap->blocks); CHECK(heap->heaps[1].available == NULL); @@ -131,14 +132,52 @@ TEST_SUITE(Heap) { TEST(Verify_finish_collection_does_nothing_when_full_list_contains_only_full_segments) { heap_t* heap = heap_create(); segment_t* seg = segment_create(2, NULL); - seg->blockmap[0] = 0; splaytree_t* blocks = heap->blocks; heap->heaps[1].full = seg; heap_start_collection(heap); + seg->blockmap[0] = 0; heap_finish_collection(heap); CHECK(blocks != heap->blocks); CHECK(heap->heaps[1].available == NULL); CHECK(heap->heaps[1].full == seg); heap_destroy(heap); } + + /* Verify: heap_find_and_mark + *************************************************************************/ + TEST(Verify_find_and_mark_should_find_and_return_the_indicated_small_block) { + heap_t* heap = heap_create(); + void* addr = heap_allocate(heap, 0, 2); + heap_start_collection(heap); + CHECK(addr == heap_find_and_mark(heap, (uintptr_t)addr)); + heap_finish_collection(heap); + heap_destroy(heap); + } + + TEST(Verify_find_and_mark_should_fail_to_find_the_indicated_small_block) { + heap_t* heap = heap_create(); + (void)heap_allocate(heap, 0, 2); + heap_start_collection(heap); + CHECK(NULL == heap_find_and_mark(heap, (uintptr_t)NULL)); + heap_finish_collection(heap); + heap_destroy(heap); + } + + TEST(Verify_find_and_mark_should_find_and_return_the_indicated_large_block) { + heap_t* heap = heap_create(); + void* addr = heap_allocate(heap, 0, 65); + heap_start_collection(heap); + CHECK(addr == heap_find_and_mark(heap, (uintptr_t)addr)); + heap_finish_collection(heap); + heap_destroy(heap); + } + + TEST(Verify_find_and_mark_should_fail_to_find_the_indicated_large_block) { + heap_t* heap = heap_create(); + (void)heap_allocate(heap, 0, 65); + heap_start_collection(heap); + CHECK(NULL == heap_find_and_mark(heap, (uintptr_t)NULL)); + heap_finish_collection(heap); + heap_destroy(heap); + } }