add gc mark function pointer in ghost

This commit is contained in:
ValKmjolnir 2023-11-22 00:36:51 +08:00
parent 56e93e703e
commit c453cca0a6
10 changed files with 102 additions and 50 deletions

View File

@ -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<u64>(ptr) << std::dec << ") {\n";
delete static_cast<u32*>(ptr);
delete static_cast<ghost_obj*>(ptr);
std::cout << " delete 0x" << std::hex;
std::cout << reinterpret_cast<u64>(ptr) << std::dec << ";\n";
std::cout << "}\n";
}
void ghost_for_test_gc_marker(void* ptr, std::vector<var>* bfs_queue) {
std::cout << "ghost_for_test::mark (0x";
std::cout << std::hex << reinterpret_cast<u64>(ptr) << std::dec << ") {\n";
bfs_queue->push_back(static_cast<ghost_obj*>(ptr)->test_string);
std::cout << " mark 0x" << std::hex;
std::cout << reinterpret_cast<u64>(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<u32*>(res.ghost().pointer)) = static_cast<u32>(num);
std::cout << "set_new_ghost: successfully set ghost = " << num << "\n";
reinterpret_cast<ghost_obj*>(res.ghost().pointer)->number = static_cast<u32>(num);
std::cout << "set_new_ghost: successfully set ghost.number = " << num << "\n";
reinterpret_cast<ghost_obj*>(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<ghost_obj*>(res.ghost().pointer)->number
<< " test_string = "
<< reinterpret_cast<ghost_obj*>(res.ghost().pointer)->test_string
<< "\n";
return nil;
}

View File

@ -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");
}

View File

@ -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;

View File

@ -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;
}

View File

@ -106,6 +106,7 @@ void gc::mark_var(std::vector<var>& 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<var>& bfs_queue, nas_upval& upval) {
}
}
void gc::mark_ghost(std::vector<var>& 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<var>& bfs_queue, nas_co& co) {
bfs_queue.push_back(co.ctx.funcr);
bfs_queue.push_back(co.ctx.upvalr);

View File

@ -78,6 +78,7 @@ private:
void mark_hash(std::vector<var>&, nas_hash&);
void mark_func(std::vector<var>&, nas_func&);
void mark_upval(std::vector<var>&, nas_upval&);
void mark_ghost(std::vector<var>&, nas_ghost&);
void mark_co(std::vector<var>&, nas_co&);
void mark_map(std::vector<var>&, nas_map&);
void sweep();

View File

@ -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) {

View File

@ -166,21 +166,24 @@ public:
struct nas_ghost {
private:
using destructor = void (*)(void*);
using marker = void (*)(void*, std::vector<var>*);
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 {

View File

@ -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;
}

View File

@ -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");
}
}