From ce0b369958b357dd87464d0d6fb261bf92808556 Mon Sep 17 00:00:00 2001 From: danyaberezun Date: Mon, 3 Jul 2023 17:58:55 +0200 Subject: [PATCH] fix: do not fix extra root if it points to lama stack; uncomment extra roots registration; rise error if binary operation is done over pointers --- runtime/gc.c | 128 ++++++++++++++++++++++++++++++++-------------- runtime/runtime.c | 18 +++++-- src/X86.ml | 31 ++++++++++- 3 files changed, 134 insertions(+), 43 deletions(-) diff --git a/runtime/gc.c b/runtime/gc.c index cb7ae795e..992889544 100644 --- a/runtime/gc.c +++ b/runtime/gc.c @@ -54,12 +54,14 @@ void *alloc (size_t size) { #endif size_t bytes_sz = size; size = BYTES_TO_WORDS(size); - fprintf(stderr, "allocation of size %zu words (%zu bytes)\n", size, bytes_sz); + fprintf(stderr, "allocation of size %zu words (%zu bytes): ", size, bytes_sz); void *p = gc_alloc_on_existing_heap(size); if (!p) { // not enough place in heap, need to perform GC cycle - return gc_alloc(size); + p = gc_alloc(size); + // return gc_alloc(size); } + // fprintf(stderr, "%p, tag=%zu\n", p, tag); return p; } @@ -181,7 +183,7 @@ void *gc_alloc_on_existing_heap (size_t size) { } void *gc_alloc (size_t size) { - fprintf(stderr, "GC cycle has started\n"); + fprintf(stderr, "===============================GC cycle has started\n"); // #ifdef FULL_INVARIANT_CHECKS FILE *stack_before = print_stack_content("stack-dump-before-compaction"); FILE *heap_before = print_objects_traversal("before-mark", 0); @@ -212,17 +214,26 @@ void *gc_alloc (size_t size) { fclose(heap_before_compaction); fclose(heap_after_compaction); // #endif - fprintf(stderr, "GC cycle has finished\n"); + fprintf(stderr, "===============================GC cycle has finished\n"); return gc_alloc_on_existing_heap(size); } void mark_phase (void) { fprintf(stderr, "marking has started\n"); + fprintf(stderr, + "__gc_root_scan_stack started: gc_top=%p bot=%p\n", + __gc_stack_top, + __gc_stack_bottom); __gc_root_scan_stack(); + fprintf(stderr, "__gc_root_scan_stack finished\n"); + fprintf(stderr, "scan_extra_roots started\n"); scan_extra_roots(); -#ifndef DEBUG_VERSION + fprintf(stderr, "scan_extra_roots finished\n"); + // #ifndef DEBUG_VERSION + fprintf(stderr, "scan_global_area started\n"); scan_global_area(); -#endif + fprintf(stderr, "scan_global_area finished\n"); + // #endif fprintf(stderr, "marking has finished\n"); } @@ -309,10 +320,38 @@ void scan_and_fix_region (memory_chunk *old_heap, void *start, void *end) { } void scan_and_fix_region_roots (memory_chunk *old_heap) { - fprintf(stderr, "extra roots started %i\n", extra_roots.current_free); + fprintf(stderr, "extra roots started: number os extra roots %i\n", extra_roots.current_free); for (int i = 0; i < extra_roots.current_free; i++) { size_t *ptr = extra_roots.roots[i]; size_t ptr_value = *ptr; + if (extra_roots.roots[i] > __gc_stack_top && extra_roots.roots[i] <= __gc_stack_bottom) { + if (is_valid_heap_pointer(ptr_value)) { + fprintf(stderr, + "|\tskip extra root: %p (%p), since it points to Lama's stack top=%p bot=%p\n", + extra_roots.roots[i], + ptr_value, + __gc_stack_top, + __gc_stack_bottom); + } else if ((extra_roots.roots[i] <= (void *)&__stop_custom_data + && extra_roots.roots[i] >= (void *)&__start_custom_data) + || (extra_roots.roots[i] <= (void *)&__stop_custom_data + && extra_roots.roots[i] >= (void *)&__start_custom_data)) { + fprintf( + stderr, + "|\tskip extra root: %p (%p), since it points to Lama's static area stop=%p start=%p\n", + extra_roots.roots[i], + ptr_value, + (void *)&__stop_custom_data, + (void *)&__start_custom_data); + exit(1); + } else { + fprintf(stderr, + "|\tskip extra root: %p (%p): not a valid Lama pointer \n", + extra_roots.roots[i], + ptr_value); + } + continue; + } if (is_valid_pointer((size_t *)ptr_value) && (size_t)old_heap->begin <= ptr_value && ptr_value <= (size_t)old_heap->current) { void *obj_ptr = (void *)heap.begin + ((void *)ptr_value - (void *)old_heap->begin); @@ -320,10 +359,10 @@ void scan_and_fix_region_roots (memory_chunk *old_heap) { (void *)heap.begin + ((void *)get_forward_address(obj_ptr) - (void *)old_heap->begin); size_t content_offset = get_header_size(get_type_row_ptr(obj_ptr)); *(void **)ptr = new_addr + content_offset; - fprintf(stderr, "extra root %p -> %p\n", ptr_value, *ptr); + fprintf(stderr, "|\textra root (%p) %p -> %p\n", extra_roots.roots[i], ptr_value, *ptr); } } - fprintf(stderr, "extra roots finished\n"); + fprintf(stderr, "|\textra roots finished\n"); } void update_references (memory_chunk *old_heap) { @@ -362,15 +401,16 @@ void update_references (memory_chunk *old_heap) { heap_next_obj_iterator(&it); } // fix pointers from stack - scan_and_fix_region(old_heap, (void *)__gc_stack_top + 4, (void *)__gc_stack_bottom); + scan_and_fix_region(old_heap, (void *)__gc_stack_top + 4, (void *)__gc_stack_bottom + 4); // fix pointers from extra_roots scan_and_fix_region_roots(old_heap); -#ifndef DEBUG_VERSION + // #ifndef DEBUG_VERSION // fix pointers from static area + assert((void *)&__stop_custom_data >= (void *)&__start_custom_data); scan_and_fix_region(old_heap, (void *)&__start_custom_data, (void *)&__stop_custom_data); -#endif + // #endif fprintf(stderr, "GC update_references finished\n"); } @@ -467,26 +507,30 @@ void scan_global_area (void) { #endif extern void gc_test_and_mark_root (size_t **root) { - fprintf( - stderr, "stack addresses: [%p, %p)\n", (void *)__gc_stack_top + 4, (void *)__gc_stack_bottom); - if (is_valid_pointer(*root) && !is_valid_heap_pointer(*root)) { - fprintf(stderr, - "Found weird pointer on the stack by address %p, value is %p (stack starts at %p, ends " - "at %p)\n", - root, - *root, - (void *)__gc_stack_top + 4, - (void *)__gc_stack_bottom); - } else { - if (is_valid_pointer(*root)) { - fprintf(stderr, - "Object that is supposed to be on the heap on the stack by address %p, value is %p\n", - root, - *root); - } else { - fprintf(stderr, "Value on the stack by address %p, value is %d\n", root, UNBOX(*root)); - } - } + fprintf(stderr, + "\troot = %p (%p), stack addresses: [%p, %p)\n", + root, + *root, + (void *)__gc_stack_top + 4, + (void *)__gc_stack_bottom); + // if (is_valid_pointer(*root) && !is_valid_heap_pointer(*root)) { + // fprintf(stderr, + // "Found weird pointer on the stack by address %p, value is %p (stack starts at %p, ends " + // "at %p)\n", + // root, + // *root, + // (void *)__gc_stack_top + 4, + // (void *)__gc_stack_bottom); + // } else { + // if (is_valid_pointer(*root)) { + // // fprintf(stderr, + // // "Object that is supposed to be on the heap on the stack by address %p, value is %p\n", + // // root, + // // *root); + // } else { + // fprintf(stderr, "Value on the stack by address %p, value is %d\n", root, UNBOX(*root)); + // } + // } mark((void *)*root); } @@ -528,6 +572,7 @@ void push_extra_root (void **p) { perror("ERROR: push_extra_roots: extra_roots_pool overflow\n"); exit(1); } + assert(p >= __gc_stack_top || p < __gc_stack_bottom); extra_roots.roots[extra_roots.current_free] = p; extra_roots.current_free++; } @@ -669,12 +714,15 @@ lama_type get_type_header_ptr (void *ptr) { fprintf(stderr, "ERROR: get_type_header_ptr: unknown object header, cur_id=%d", cur_id); raise(SIGINT); // only for debug purposes #else - fprintf( - stderr, - "ERROR: get_type_header_ptr: unknown object header, ptr is %p, tag %i, heap size is %d\n", - ptr, - TAG(*header), - heap.size); + fprintf(stderr, + "ERROR: get_type_header_ptr: unknown object header, ptr is %p, tag %i, heap size is " + "%d cur_id=%d stack_top=%p stack_bot=%p ", + ptr, + TAG(*header), + heap.size, + cur_id, + __gc_stack_top, + __gc_stack_bottom); FILE *heap_before_compaction = print_objects_traversal("dump_kill", 1); close(heap_before_compaction); kill(getpid(), SIGSEGV); @@ -780,6 +828,7 @@ size_t get_header_size (lama_type type) { void *alloc_string (int len) { data *obj = alloc(string_size(len)); obj->data_header = STRING_TAG | (len << 3); + fprintf(stderr, "%p, [STRING] tag=%zu\n", obj, TAG(obj->data_header)); #ifdef DEBUG_VERSION obj->id = cur_id; #endif @@ -790,6 +839,7 @@ void *alloc_string (int len) { void *alloc_array (int len) { data *obj = alloc(array_size(len)); obj->data_header = ARRAY_TAG | (len << 3); + fprintf(stderr, "%p, [ARRAY] tag=%zu\n", obj, TAG(obj->data_header)); #ifdef FULL_INVARIANT_CHECKS obj->id = cur_id; #endif @@ -800,6 +850,7 @@ void *alloc_array (int len) { void *alloc_sexp (int members) { sexp *obj = alloc(sexp_size(members)); obj->sexp_header = obj->contents.data_header = SEXP_TAG | (members << 3); + fprintf(stderr, "%p, SEXP tag=%zu\n", obj, TAG(obj->contents.data_header)); #ifdef FULL_INVARIANT_CHECKS obj->contents.id = cur_id; #endif @@ -812,6 +863,7 @@ void *alloc_closure (int captured) { data *obj = alloc(closure_size(captured)); obj->data_header = CLOSURE_TAG | (captured << 3); + fprintf(stderr, "%p, [CLOSURE] tag=%zu\n", obj, TAG(obj->data_header)); #ifdef FULL_INVARIANT_CHECKS obj->id = cur_id; #endif diff --git a/runtime/runtime.c b/runtime/runtime.c index 55b6df42b..46f36393d 100644 --- a/runtime/runtime.c +++ b/runtime/runtime.c @@ -890,10 +890,10 @@ extern void *Bclosure (int bn, void *entry, ...) { fflush(stdout); #endif argss = (ebp + 12); - // for (i = 0; i < n; i++, argss++) { push_extra_root((void **)argss); } + for (i = 0; i < n; i++, argss++) { push_extra_root((void **)argss); } r = (data *)alloc_closure(n + 1); - // push_extra_root(&r); + push_extra_root(&r); ((void **)r->contents)[0] = entry; va_start(args, entry); @@ -907,9 +907,9 @@ extern void *Bclosure (int bn, void *entry, ...) { __post_gc(); - // pop_extra_root(&r); + pop_extra_root(&r); argss--; - //for (i = 0; i < n; i++, argss--) { pop_extra_root((void **)argss); } + for (i = 0; i < n; i++, argss--) { pop_extra_root((void **)argss); } #ifdef DEBUG_PRINT print_indent(); @@ -1346,6 +1346,16 @@ extern int Lread () { return BOX(result); } +extern int Lbinoperror (void) { + fprintf(stderr, "ERROR: POINTER ARITHMETICS is forbidden; EXIT\n"); + exit(1); +} + +extern int Lbinoperror2 (void) { + fprintf(stderr, "ERROR: Comparing BOXED and UNBOXED value ; EXIT\n"); + exit(1); +} + /* Lwrite is an implementation of the "write" construct */ extern int Lwrite (int n) { printf("%d\n", UNBOX(n)); diff --git a/src/X86.ml b/src/X86.ml index 2b5418cd0..4728fae2b 100644 --- a/src/X86.ml +++ b/src/X86.ml @@ -306,9 +306,32 @@ let compile cmd env imports code = | _ -> [Mov (v, eax); Mov (eax, I (0, x)); Mov (eax, x)] ) - | BINOP op -> + | BINOP op -> let x, y, env' = env#pop2 in env'#push y, + (match op with + |"<" | "<=" | "==" | "!=" | ">=" | ">" -> + [Push (eax); + Push (edx); + Mov (y, eax); + Binop("&&", L(1), eax); + Mov (x, edx); + Binop("&&", L(1), edx); + Binop("cmp", eax, edx); + CJmp ("nz", "_ERROR2"); + Pop (edx); + Pop (eax)] + (* | "+" | "-" | "*" | "/" -> *) + | _ -> + [Mov (y, eax); + Binop("&&", L(1), eax); + Binop("cmp", L(0), eax); + CJmp ("z", "_ERROR"); + Mov (x, eax); + Binop("&&", L(1), eax); + Binop("cmp", L(0), eax); + CJmp ("z", "_ERROR")] + | _ -> []) @ (match op with | "/" -> [Mov (y, eax); @@ -443,6 +466,12 @@ let compile cmd env imports code = Binop ("test", eax, eax); CJmp ("z", "_continue"); Ret; + Label ("_ERROR"); + Call "Lbinoperror"; + Ret; + Label ("_ERROR2"); + Call "Lbinoperror2"; + Ret; Label "_continue"; Mov (L 1, M "_init"); ]