From c453cca0a6bda869468ce907c30067dd6b3eca8f Mon Sep 17 00:00:00 2001 From: ValKmjolnir Date: Wed, 22 Nov 2023 00:36:51 +0800 Subject: [PATCH] :sparkles: add gc mark function pointer in ghost --- module/fib.cpp | 36 ++++++++++++++++++---- module/libfib.nas | 9 ++++++ src/dylib_lib.cpp | 2 ++ src/io_lib.cpp | 8 ++--- src/nasal_gc.cpp | 8 +++++ src/nasal_gc.h | 1 + src/nasal_type.cpp | 3 ++ src/nasal_type.h | 11 ++++--- src/unix_lib.cpp | 2 +- test/module_test.nas | 72 +++++++++++++++++++++++--------------------- 10 files changed, 102 insertions(+), 50 deletions(-) diff --git a/module/fib.cpp b/module/fib.cpp index c54831a..f44b60e 100644 --- a/module/fib.cpp +++ b/module/fib.cpp @@ -42,18 +42,37 @@ var quick_fib(var* args, usize size, gc* ngc) { const auto ghost_for_test = "ghost_for_test"; +struct ghost_obj { + u32 number = 0; + var test_string = nil; +}; + void ghost_for_test_destructor(void* ptr) { std::cout << "ghost_for_test::destructor (0x"; std::cout << std::hex << reinterpret_cast(ptr) << std::dec << ") {\n"; - delete static_cast(ptr); + delete static_cast(ptr); std::cout << " delete 0x" << std::hex; std::cout << reinterpret_cast(ptr) << std::dec << ";\n"; std::cout << "}\n"; } +void ghost_for_test_gc_marker(void* ptr, std::vector* bfs_queue) { + std::cout << "ghost_for_test::mark (0x"; + std::cout << std::hex << reinterpret_cast(ptr) << std::dec << ") {\n"; + bfs_queue->push_back(static_cast(ptr)->test_string); + std::cout << " mark 0x" << std::hex; + std::cout << reinterpret_cast(ptr) << std::dec << "->test_string;\n"; + std::cout << "}\n"; +} + var create_new_ghost(var* args, usize size, gc* ngc) { var res = ngc->alloc(vm_obj); - res.ghost().set(ghost_for_test, ghost_for_test_destructor, new u32); + res.ghost().set( + ghost_for_test, + ghost_for_test_destructor, + ghost_for_test_gc_marker, + new ghost_obj + ); return res; } @@ -64,8 +83,10 @@ var set_new_ghost(var* args, usize size, gc* ngc) { return nil; } f64 num = args[1].num(); - *(reinterpret_cast(res.ghost().pointer)) = static_cast(num); - std::cout << "set_new_ghost: successfully set ghost = " << num << "\n"; + reinterpret_cast(res.ghost().pointer)->number = static_cast(num); + std::cout << "set_new_ghost: successfully set ghost.number = " << num << "\n"; + reinterpret_cast(res.ghost().pointer)->test_string = ngc->newstr("just for test"); + std::cout << "set_new_ghost: successfully set ghost.test_string = just for test\n"; return nil; } @@ -75,8 +96,11 @@ var print_new_ghost(var* args, usize size, gc* ngc) { std::cout << "print_new_ghost: not ghost for test type.\n"; return nil; } - std::cout << "print_new_ghost: " << res.ghost() << " result = " - << *((u32*)res.ghost().pointer) << "\n"; + std::cout << "print_new_ghost: " << res.ghost() << " number = " + << reinterpret_cast(res.ghost().pointer)->number + << " test_string = " + << reinterpret_cast(res.ghost().pointer)->test_string + << "\n"; return nil; } diff --git a/module/libfib.nas b/module/libfib.nas index 18819a7..078630f 100644 --- a/module/libfib.nas +++ b/module/libfib.nas @@ -47,8 +47,17 @@ var print_ghost = func(object) { var test_ghost = func() { var ghost = create_ghost(); print_ghost(nil); # err + print("\n"); print_ghost(ghost); # random + print("\n"); set_ghost(nil, 114); # err + print("\n"); set_ghost(ghost, 114); # success + print("\n"); + for(var i = 0; i<256; i+=1) { + var temp = []; # try to trigger gc + } + print("\n"); print_ghost(ghost); # 114 + print("\n"); } diff --git a/src/dylib_lib.cpp b/src/dylib_lib.cpp index a3402cc..7eaf1f6 100644 --- a/src/dylib_lib.cpp +++ b/src/dylib_lib.cpp @@ -47,6 +47,7 @@ var builtin_dlopen(context* ctx, gc* ngc) { library_object.ghost().set( dynamic_library_type_name, dynamic_library_destructor, + nullptr, dynamic_library_pointer ); return_hash.hash().elems["lib"] = library_object; @@ -76,6 +77,7 @@ var builtin_dlopen(context* ctx, gc* ngc) { function_object.ghost().set( function_address_type_name, nullptr, + nullptr, function_pointer ); return_hash.hash().elems[table[i].name] = function_object; diff --git a/src/io_lib.cpp b/src/io_lib.cpp index 5af223a..4acb79a 100644 --- a/src/io_lib.cpp +++ b/src/io_lib.cpp @@ -60,7 +60,7 @@ var builtin_open(context* ctx, gc* ngc) { } var return_object = ngc->alloc(vm_obj); return_object.ghost().set( - file_type_name, filehandle_destructor, file_descriptor + file_type_name, filehandle_destructor, nullptr, file_descriptor ); return return_object; } @@ -206,19 +206,19 @@ var builtin_eof(context* ctx, gc* ngc) { var builtin_stdin(context* ctx, gc* ngc) { auto file_descriptor = ngc->alloc(vm_obj); - file_descriptor.ghost().set(file_type_name, nullptr, stdin); + file_descriptor.ghost().set(file_type_name, nullptr, nullptr, stdin); return file_descriptor; } var builtin_stdout(context* ctx, gc* ngc) { auto file_descriptor = ngc->alloc(vm_obj); - file_descriptor.ghost().set(file_type_name, nullptr, stdout); + file_descriptor.ghost().set(file_type_name, nullptr, nullptr, stdout); return file_descriptor; } var builtin_stderr(context* ctx, gc* ngc) { auto file_descriptor = ngc->alloc(vm_obj); - file_descriptor.ghost().set(file_type_name, nullptr, stderr); + file_descriptor.ghost().set(file_type_name, nullptr, nullptr, stderr); return file_descriptor; } diff --git a/src/nasal_gc.cpp b/src/nasal_gc.cpp index d0bdda3..2303279 100644 --- a/src/nasal_gc.cpp +++ b/src/nasal_gc.cpp @@ -106,6 +106,7 @@ void gc::mark_var(std::vector& bfs_queue, var& value) { case vm_hash: mark_hash(bfs_queue, value.hash()); break; case vm_func: mark_func(bfs_queue, value.func()); break; case vm_upval: mark_upval(bfs_queue, value.upval()); break; + case vm_obj: mark_ghost(bfs_queue, value.ghost()); break; case vm_co: mark_co(bfs_queue, value.co()); break; case vm_map: mark_map(bfs_queue, value.map()); break; default: break; @@ -147,6 +148,13 @@ void gc::mark_upval(std::vector& bfs_queue, nas_upval& upval) { } } +void gc::mark_ghost(std::vector& bfs_queue, nas_ghost& ghost) { + if (!ghost.gc_mark_function) { + return; + } + ghost.gc_mark_function(ghost.pointer, &bfs_queue); +} + void gc::mark_co(std::vector& bfs_queue, nas_co& co) { bfs_queue.push_back(co.ctx.funcr); bfs_queue.push_back(co.ctx.upvalr); diff --git a/src/nasal_gc.h b/src/nasal_gc.h index 4ce39e7..1bc9010 100644 --- a/src/nasal_gc.h +++ b/src/nasal_gc.h @@ -78,6 +78,7 @@ private: void mark_hash(std::vector&, nas_hash&); void mark_func(std::vector&, nas_func&); void mark_upval(std::vector&, nas_upval&); + void mark_ghost(std::vector&, nas_ghost&); void mark_co(std::vector&, nas_co&); void mark_map(std::vector&, nas_map&); void sweep(); diff --git a/src/nasal_type.cpp b/src/nasal_type.cpp index 410300d..86df0c5 100644 --- a/src/nasal_type.cpp +++ b/src/nasal_type.cpp @@ -105,9 +105,11 @@ void nas_func::clear() { void nas_ghost::set( const std::string& ghost_type_name, destructor destructor_pointer, + marker gc_marker_pointer, void* ghost_pointer) { type_name = ghost_type_name; destructor_function = destructor_pointer; + gc_mark_function = gc_marker_pointer; pointer = ghost_pointer; } @@ -129,6 +131,7 @@ void nas_ghost::clear() { type_name = ""; pointer = nullptr; destructor_function = nullptr; + gc_mark_function = nullptr; } std::ostream& operator<<(std::ostream& out, const nas_ghost& ghost) { diff --git a/src/nasal_type.h b/src/nasal_type.h index 8bb589b..f9880c4 100644 --- a/src/nasal_type.h +++ b/src/nasal_type.h @@ -166,21 +166,24 @@ public: struct nas_ghost { private: using destructor = void (*)(void*); + using marker = void (*)(void*, std::vector*); public: std::string type_name; destructor destructor_function; + marker gc_mark_function; void* pointer; public: nas_ghost(): - type_name(""), destructor_function(nullptr), pointer(nullptr) {} - ~nas_ghost() {clear();} - void set(const std::string&, destructor, void*); + type_name(""), destructor_function(nullptr), + gc_mark_function(nullptr), pointer(nullptr) {} + ~nas_ghost() { clear(); } + void set(const std::string&, destructor, marker, void*); void clear(); public: - const auto& get_ghost_name() const {return type_name;} + const auto& get_ghost_name() const { return type_name; } }; struct context { diff --git a/src/unix_lib.cpp b/src/unix_lib.cpp index eb37b4d..faaea82 100644 --- a/src/unix_lib.cpp +++ b/src/unix_lib.cpp @@ -73,7 +73,7 @@ var builtin_opendir(context* ctx, gc* ngc) { } #endif var ret = ngc->alloc(vm_obj); - ret.ghost().set(dir_type_name, dir_entry_destructor, p); + ret.ghost().set(dir_type_name, dir_entry_destructor, nullptr, p); return ret; } diff --git a/test/module_test.nas b/test/module_test.nas index 58773c7..de7228f 100644 --- a/test/module_test.nas +++ b/test/module_test.nas @@ -5,75 +5,77 @@ println(keys(libfib)); libfib.test_ghost(); var libfib = func() { - var (dd,fib,qfib)=(nil,nil,nil); - var invoke=dylib.limitcall(1); + var (dd, fib, qfib) = (nil, nil, nil); + var invoke = dylib.limitcall(1); return { - open:func() { + open: func() { if (dd==nil) { - dd=dylib.dlopen("libfib."~(os.platform()=="windows"?"dll":"so")); - fib=dd.fib; - qfib=dd.quick_fib; + dd = dylib.dlopen("libfib."~(os.platform()=="windows"?"dll":"so")); + fib = dd.fib; + qfib = dd.quick_fib; } else { println("[info ] already loaded."); } }, - close:func() { + close: func() { if (dd==nil) { println("[error ] already closed."); return; } dylib.dlclose(dd.lib); - (dd,fib,qfib)=(nil,nil,nil); + (dd, fib, qfib) = (nil, nil, nil); }, - fib:func(x) { - if (fib!=nil) - return invoke(fib,x); + fib: func(x) { + if (fib!=nil) { + return invoke(fib, x); + } println("[error ] cannot call fib."); return nil; }, - qfib:func(x) { - if (qfib!=nil) - return invoke(qfib,x); + qfib: func(x) { + if (qfib!=nil) { + return invoke(qfib, x); + } println("[error ] cannot call qfib."); return nil; } } }(); -println("[keys ] ",keys(libfib)); +println("[keys ] ", keys(libfib)); libfib.open(); libfib.open(); -var tm=maketimestamp(); +var tm = maketimestamp(); tm.stamp(); -println("[result] ",libfib.fib(35)); -println("[time ] ",tm.elapsedMSec()," ms"); +println("[result] ", libfib.fib(35)); +println("[time ] ", tm.elapsedMSec()," ms"); tm.stamp(); -println("[result] ",libfib.qfib(35)); -println("[time ] ",tm.elapsedMSec()," ms"); +println("[result] ", libfib.qfib(35)); +println("[time ] ", tm.elapsedMSec()," ms"); libfib.close(); -println("[result] ",libfib.fib(35)); -println("[result] ",libfib.qfib(35)); +println("[result] ", libfib.fib(35)); +println("[result] ", libfib.qfib(35)); libfib.close(); var speed_test = func() { - var d=dylib.dlopen("libfib."~(os.platform()=="windows"?"dll":"so")); - println("[dylib ] ",d); - var fd=d.quick_fib; - var vec_call=dylib.dlcall; - var invoke=dylib.limitcall(1); - var tm=maketimestamp(); + var d = dylib.dlopen("libfib."~(os.platform()=="windows"? "dll":"so")); + println("[dylib ] ", d); + var fd = d.quick_fib; + var vec_call = dylib.dlcall; + var invoke = dylib.limitcall(1); + var tm = maketimestamp(); - for(var t=0;t<10;t+=1) { + for(var t=0; t<10; t+=1) { tm.stamp(); - for(var i=0;i<5e5;i+=1) { - invoke(fd,40); + for(var i=0; i<5e5; i+=1) { + invoke(fd, 40); } - println("[time ] limited call: ",int(5e5/tm.elapsedMSec())," call/ms"); + println("[time ] limited call: ", int(5e5/tm.elapsedMSec()), " call/ms"); tm.stamp(); - for(var i=0;i<5e5;i+=1) { - vec_call(fd,40); + for(var i=0; i<5e5; i+=1) { + vec_call(fd, 40); } - println("[time ] dynamic call: ",int(5e5/tm.elapsedMSec())," call/ms"); + println("[time ] dynamic call: ", int(5e5/tm.elapsedMSec()), " call/ms"); } }