#include "gencgc.c"
#define MAX_PAGES_FOR_TEST 20
* - Allocate a large object that is a smidgen smaller or larger
* than an integral number of pages (for varying values of "smidgen").
* - Capture the page table entries so we know what they would
* contain if the object were initially allocated as such.
* - Clean up the page tables (as though the allocation never happened).
* - Allocate an arbitrarily sized larger object, then shrink it down
* to the reference size, asserting that:
* - the page table entries look exactly as if the object
* had been created at the smaller size.
* - trailing pages are empty.
* - the number of bytes freed is correct.
*/
void test_adjust_obj_ptes()
{
void shrink_obj_test(int ending_size, int created_type,
struct page *expected_result);
struct page expected_result[1+MAX_PAGES_FOR_TEST];
page_table_pages = MAX_PAGES_FOR_TEST;
posix_memalign((void**)&DYNAMIC_SPACE_START, GENCGC_CARD_BYTES,
MAX_PAGES_FOR_TEST * GENCGC_CARD_BYTES);
struct alloc_region test_region;
int npages, fuzz;
for (npages = 1 ; npages <= 8; ++npages)
for (fuzz = -3; fuzz <= 3; ++fuzz) {
int request = npages * GENCGC_CARD_BYTES + (N_WORD_BYTES*2)*fuzz;
gc_init_region(&test_region);
RESET_ALLOC_START_PAGES();
test_region.last_page = -1;
gc_alloc_generation = SCRATCH_GENERATION;
page_table = calloc(1+page_table_pages, sizeof(struct page));
generation_index_t gen;
for (gen=0; gen < NUM_GENERATIONS; ++gen)
generations[gen].bytes_allocated = 0;
bytes_allocated = 0;
void *result = gc_alloc_large(request, UNBOXED_PAGE_FLAG, &test_region);
gc_assert(result == (void*)DYNAMIC_SPACE_START);
gc_assert((int)bytes_allocated == request);
gc_assert((int)generations[gc_alloc_generation].bytes_allocated == request);
memcpy(expected_result, page_table,
page_table_pages * sizeof (struct page));
free(page_table);
shrink_obj_test(request, BOXED_PAGE_FLAG, expected_result);
shrink_obj_test(request, UNBOXED_PAGE_FLAG, expected_result);
}
}
void shrink_obj_test(int ending_size, int initial_type,
struct page *expected_result)
{
int npages, fuzz, page;
struct alloc_region test_region;
for (npages = 1 ; npages <= 10; ++npages)
for (fuzz = -4; fuzz <= 4; ++fuzz) {
int initial_size = npages * GENCGC_CARD_BYTES + (N_WORD_BYTES*2)*fuzz;
if (initial_size >= ending_size) {
gc_init_region(&test_region);
RESET_ALLOC_START_PAGES();
test_region.last_page = -1;
page_table = calloc(1+page_table_pages, sizeof(struct page));
from_space = gc_alloc_generation = 2;
void *result = gc_alloc_large(initial_size, initial_type, &test_region);
gc_assert(result == (void*)DYNAMIC_SPACE_START);
sword_t freed = adjust_obj_ptes(find_page_index(result),
ending_size/N_WORD_BYTES,
SCRATCH_GENERATION,
SINGLE_OBJECT_FLAG | UNBOXED_PAGE_FLAG);
gc_assert(freed == (initial_size - ending_size));
for (page=0; page<MAX_PAGES_FOR_TEST; ++page) {
gc_assert(page_table[page].bytes_used_ ==
expected_result[page].bytes_used_);
gc_assert(page_table[page].scan_start_offset_ ==
expected_result[page].scan_start_offset_);
gc_assert(page_table[page].type ==
expected_result[page].type);
if (!page_free_p(page))
gc_assert(page_table[page].gen ==
expected_result[page].gen);
}
}
}
}
void run_gencgc_tests()
{
test_adjust_obj_ptes();
}
int main()
{
void run_gencgc_tests();
printf(";;; Running GC tests\n");
run_gencgc_tests();
printf(";;; Success\n");
}