From 762d3215d96315ba9366134375a14e1cf3895111 Mon Sep 17 00:00:00 2001 From: "Mike D. Lowis" Date: Tue, 13 Oct 2015 13:05:19 -0400 Subject: [PATCH] Fixed valgrind errors for garbage collector and implemented proper destructor for AST nodes --- build.rb | 2 +- modules/libopts | 2 +- source/ast.c | 35 +++++++++++++++++++++++++++++ source/gc.c | 58 +++++++++++++++++++++++-------------------------- source/main.c | 4 ++-- source/parser.c | 6 ++--- 6 files changed, 68 insertions(+), 39 deletions(-) diff --git a/build.rb b/build.rb index 9f4095d..1863c86 100755 --- a/build.rb +++ b/build.rb @@ -14,7 +14,7 @@ base_env = BuildEnv.new do |env| env.build_dir('source','build/obj/source') env.build_dir('modules','build/obj/modules') # Compiler options - env["CFLAGS"] += ['-DLEAK_DETECT_LEVEL=1', '--std=c99', '-Wall', '-Wextra']#, '-Werror'] + env["CFLAGS"] += ['-g', '-DLEAK_DETECT_LEVEL=1', '--std=c99', '-Wall', '-Wextra']#, '-Werror'] env["CPPPATH"] += Dir['modules/libcds/source/**/'] + [ 'modules/libopts/source', 'source/', diff --git a/modules/libopts b/modules/libopts index 57c1fa4..f0ea1b6 160000 --- a/modules/libopts +++ b/modules/libopts @@ -1 +1 @@ -Subproject commit 57c1fa4035fadc76abcfb6b7cf4eadfae4db2b85 +Subproject commit f0ea1b6d1c01ef84a6eb12bd05829c57dd0bceb4 diff --git a/source/ast.c b/source/ast.c index 336a1a1..02edaa1 100644 --- a/source/ast.c +++ b/source/ast.c @@ -2,6 +2,41 @@ static void ast_free(void* ptr) { + AST* ast = (AST*)ptr; + switch(ast->type) { + case AST_IDENT: + case AST_STRING: + gc_delref(ast->value.text); + break; + + case AST_REQ: + gc_delref(ast->value.req.name); + break; + + case AST_DEF: + gc_delref(ast->value.def.name); + gc_delref(ast->value.def.value); + break; + + case AST_ANN: + gc_delref(ast->value.ann.name); + gc_delref(ast->value.ann.value); + break; + + case AST_IF: + gc_delref(ast->value.ifexpr.cond); + gc_delref(ast->value.ifexpr.bthen); + gc_delref(ast->value.ifexpr.belse); + break; + + case AST_FUNC: + gc_delref(ast->value.func.args); + gc_delref(ast->value.func.body); + break; + + default: + break; + } } static AST* ast(ASTType type) diff --git a/source/gc.c b/source/gc.c index 6a8eec2..a0d79ef 100644 --- a/source/gc.c +++ b/source/gc.c @@ -151,6 +151,7 @@ static hash_entry_t* hash_del(hash_t* hash, hash_entry_t* entry) /*****************************************************************************/ +static bool Shutdown; static void** Stack_Bottom; static hash_t Zero_Count_Table; static hash_t Multi_Ref_Table; @@ -191,22 +192,22 @@ static void gc_mark(void) { (noinline ? gc_mark_stack : NULL)(); } -static void gc_sweep(void) { +static void gc_sweep_table(hash_t* table) { unsigned int i; /* Delete all the entries in the hash */ - for (i = 0; i < num_buckets(Working_Table.bkt_count); i++) { - hash_entry_t* node = Working_Table.buckets[i]; - Working_Table.buckets[i] = NULL; + for (i = 0; i < num_buckets(table->bkt_count); i++) { + hash_entry_t* node = table->buckets[i]; + table->buckets[i] = NULL; while (node != NULL) { hash_entry_t* deadite = node; + node = node->next; obj_t* obj = ((obj_t*)(deadite->object)-1); if (obj->destructor != NULL) obj->destructor(deadite->object); free(deadite); - node = node->next; } } - free(Working_Table.buckets); + free(table->buckets); } void gc_init(void** stack_bottom) @@ -214,17 +215,34 @@ void gc_init(void** stack_bottom) Stack_Bottom = stack_bottom; hash_init(&Zero_Count_Table); hash_init(&Multi_Ref_Table); + atexit(gc_deinit); + Shutdown = false; } void gc_deinit(void) { + Shutdown = true; + gc_sweep_table(&Zero_Count_Table); + gc_sweep_table(&Multi_Ref_Table); } void gc_collect(void) { +#ifdef GC_DEBUG_MSGS + printf("BEFORE - ZCT: %ld MRT: %ld TOT: %ld\n", + hash_size(&Zero_Count_Table), + hash_size(&Multi_Ref_Table), + hash_size(&Zero_Count_Table) + hash_size(&Multi_Ref_Table)); +#endif Working_Table = Zero_Count_Table; hash_init(&Zero_Count_Table); gc_mark(); - gc_sweep(); + gc_sweep_table(&Working_Table); +#ifdef GC_DEBUG_MSGS + printf("AFTER - ZCT: %ld MRT: %ld TOT: %ld\n\n", + hash_size(&Zero_Count_Table), + hash_size(&Multi_Ref_Table), + hash_size(&Zero_Count_Table) + hash_size(&Multi_Ref_Table)); +#endif } void* gc_alloc(size_t size, destructor_t destructor) @@ -246,7 +264,7 @@ void* gc_addref(void* ptr) hash_entry_t lookup = {0, 0, 0}; hash_entry_t* entry; obj_t* obj = ((obj_t*)ptr-1); - if (ptr != NULL) { + if ((ptr != NULL) && !Shutdown) { obj->refs++; if (obj->refs == 1) { lookup.object = ptr; @@ -263,7 +281,7 @@ void gc_delref(void* ptr) hash_entry_t lookup = {0, 0, 0}; hash_entry_t* entry; obj_t* obj = ((obj_t*)ptr-1); - if (ptr != NULL) { + if ((ptr != NULL) && !Shutdown) { obj->refs--; if (obj->refs == 0) { lookup.object = ptr; @@ -287,28 +305,6 @@ int main(int argc, char** argv) { void* stack_bottom = NULL; gc_init(&stack_bottom); - atexit(gc_deinit); return user_main(argc, argv); } -///int user_main(int argc, char** argv) { -/// uint8_t* foo; -/// (void)argc; -/// (void)argv; -/// foo = (uint8_t*)gc_alloc(42,NULL); -/// printf("refs: %lu\n", hash_size(&Zero_Count_Table)); -/// gc_collect(); -/// *foo = 42; -/// printf("data: %d\n", (int)*foo); -/// (void)foo; -/// printf("refs: %lu\n", hash_size(&Zero_Count_Table)); -/// printf("ref: %p\n", foo); -/// foo = NULL; -/// gc_collect(); -/// printf("refs: %lu\n", hash_size(&Zero_Count_Table)); -/// printf("ref: %p\n", foo); -/// gc_collect(); -/// printf("refs: %lu\n", hash_size(&Zero_Count_Table)); -/// return 0; -///} - diff --git a/source/main.c b/source/main.c index 1f73bd7..19e945f 100644 --- a/source/main.c +++ b/source/main.c @@ -75,7 +75,8 @@ static int emit_program(void) { */ int user_main(int argc, char **argv) { - opts_parse( Options_Config, argc, argv ); + opts_parse( Options_Config, NULL, argc, argv ); + atexit(&opts_reset); if (!opts_is_set(NULL,"mode")) { print_usage(); } else if (opts_equal(NULL, "mode", "tokens")) { @@ -97,6 +98,5 @@ int user_main(int argc, char **argv) { } else { print_usage(); } - opts_reset(); return 1; } diff --git a/source/parser.c b/source/parser.c index 2f4572c..d252131 100644 --- a/source/parser.c +++ b/source/parser.c @@ -13,7 +13,8 @@ static void parser_free(void* obj) { if ((NULL != parser->tok) && (&tok_eof != parser->tok)) { gc_delref(parser->tok); } - //gc_delref(parser->stack); + if (parser->line != NULL) + free(parser->line); } Parser* parser_new(char* prompt, FILE* input) @@ -25,7 +26,6 @@ Parser* parser_new(char* prompt, FILE* input) parser->input = input; parser->prompt = prompt; parser->tok = NULL; - //parser->stack = vec_new(0); return parser; } @@ -52,7 +52,6 @@ void parser_resume(Parser* parser) { gc_delref(parser->tok); parser->tok = NULL; } - //vec_clear(parser->stack); /* We ignore the rest of the current line and attempt to start parsing * again on the next line */ fetchline(parser); @@ -60,7 +59,6 @@ void parser_resume(Parser* parser) { void error(Parser* parser, const char* text) { - (void)parser; Tok* tok = peek(parser); fprintf(stderr, ":%zu:%zu:Error: %s\n", tok->line, tok->col, text); exit(1); -- 2.52.0