✨ add gc mark function pointer in ghost
This commit is contained in:
parent
56e93e703e
commit
c453cca0a6
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue