✨ 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";
|
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) {
|
void ghost_for_test_destructor(void* ptr) {
|
||||||
std::cout << "ghost_for_test::destructor (0x";
|
std::cout << "ghost_for_test::destructor (0x";
|
||||||
std::cout << std::hex << reinterpret_cast<u64>(ptr) << std::dec << ") {\n";
|
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 << " delete 0x" << std::hex;
|
||||||
std::cout << reinterpret_cast<u64>(ptr) << std::dec << ";\n";
|
std::cout << reinterpret_cast<u64>(ptr) << std::dec << ";\n";
|
||||||
std::cout << "}\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 create_new_ghost(var* args, usize size, gc* ngc) {
|
||||||
var res = ngc->alloc(vm_obj);
|
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;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,8 +83,10 @@ var set_new_ghost(var* args, usize size, gc* ngc) {
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
f64 num = args[1].num();
|
f64 num = args[1].num();
|
||||||
*(reinterpret_cast<u32*>(res.ghost().pointer)) = static_cast<u32>(num);
|
reinterpret_cast<ghost_obj*>(res.ghost().pointer)->number = static_cast<u32>(num);
|
||||||
std::cout << "set_new_ghost: successfully set ghost = " << num << "\n";
|
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;
|
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";
|
std::cout << "print_new_ghost: not ghost for test type.\n";
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
std::cout << "print_new_ghost: " << res.ghost() << " result = "
|
std::cout << "print_new_ghost: " << res.ghost() << " number = "
|
||||||
<< *((u32*)res.ghost().pointer) << "\n";
|
<< reinterpret_cast<ghost_obj*>(res.ghost().pointer)->number
|
||||||
|
<< " test_string = "
|
||||||
|
<< reinterpret_cast<ghost_obj*>(res.ghost().pointer)->test_string
|
||||||
|
<< "\n";
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -47,8 +47,17 @@ var print_ghost = func(object) {
|
||||||
var test_ghost = func() {
|
var test_ghost = func() {
|
||||||
var ghost = create_ghost();
|
var ghost = create_ghost();
|
||||||
print_ghost(nil); # err
|
print_ghost(nil); # err
|
||||||
|
print("\n");
|
||||||
print_ghost(ghost); # random
|
print_ghost(ghost); # random
|
||||||
|
print("\n");
|
||||||
set_ghost(nil, 114); # err
|
set_ghost(nil, 114); # err
|
||||||
|
print("\n");
|
||||||
set_ghost(ghost, 114); # success
|
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_ghost(ghost); # 114
|
||||||
|
print("\n");
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,6 +47,7 @@ var builtin_dlopen(context* ctx, gc* ngc) {
|
||||||
library_object.ghost().set(
|
library_object.ghost().set(
|
||||||
dynamic_library_type_name,
|
dynamic_library_type_name,
|
||||||
dynamic_library_destructor,
|
dynamic_library_destructor,
|
||||||
|
nullptr,
|
||||||
dynamic_library_pointer
|
dynamic_library_pointer
|
||||||
);
|
);
|
||||||
return_hash.hash().elems["lib"] = library_object;
|
return_hash.hash().elems["lib"] = library_object;
|
||||||
|
@ -76,6 +77,7 @@ var builtin_dlopen(context* ctx, gc* ngc) {
|
||||||
function_object.ghost().set(
|
function_object.ghost().set(
|
||||||
function_address_type_name,
|
function_address_type_name,
|
||||||
nullptr,
|
nullptr,
|
||||||
|
nullptr,
|
||||||
function_pointer
|
function_pointer
|
||||||
);
|
);
|
||||||
return_hash.hash().elems[table[i].name] = function_object;
|
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);
|
var return_object = ngc->alloc(vm_obj);
|
||||||
return_object.ghost().set(
|
return_object.ghost().set(
|
||||||
file_type_name, filehandle_destructor, file_descriptor
|
file_type_name, filehandle_destructor, nullptr, file_descriptor
|
||||||
);
|
);
|
||||||
return return_object;
|
return return_object;
|
||||||
}
|
}
|
||||||
|
@ -206,19 +206,19 @@ var builtin_eof(context* ctx, gc* ngc) {
|
||||||
|
|
||||||
var builtin_stdin(context* ctx, gc* ngc) {
|
var builtin_stdin(context* ctx, gc* ngc) {
|
||||||
auto file_descriptor = ngc->alloc(vm_obj);
|
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;
|
return file_descriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
var builtin_stdout(context* ctx, gc* ngc) {
|
var builtin_stdout(context* ctx, gc* ngc) {
|
||||||
auto file_descriptor = ngc->alloc(vm_obj);
|
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;
|
return file_descriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
var builtin_stderr(context* ctx, gc* ngc) {
|
var builtin_stderr(context* ctx, gc* ngc) {
|
||||||
auto file_descriptor = ngc->alloc(vm_obj);
|
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;
|
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_hash: mark_hash(bfs_queue, value.hash()); break;
|
||||||
case vm_func: mark_func(bfs_queue, value.func()); break;
|
case vm_func: mark_func(bfs_queue, value.func()); break;
|
||||||
case vm_upval: mark_upval(bfs_queue, value.upval()); 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_co: mark_co(bfs_queue, value.co()); break;
|
||||||
case vm_map: mark_map(bfs_queue, value.map()); break;
|
case vm_map: mark_map(bfs_queue, value.map()); break;
|
||||||
default: 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) {
|
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.funcr);
|
||||||
bfs_queue.push_back(co.ctx.upvalr);
|
bfs_queue.push_back(co.ctx.upvalr);
|
||||||
|
|
|
@ -78,6 +78,7 @@ private:
|
||||||
void mark_hash(std::vector<var>&, nas_hash&);
|
void mark_hash(std::vector<var>&, nas_hash&);
|
||||||
void mark_func(std::vector<var>&, nas_func&);
|
void mark_func(std::vector<var>&, nas_func&);
|
||||||
void mark_upval(std::vector<var>&, nas_upval&);
|
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_co(std::vector<var>&, nas_co&);
|
||||||
void mark_map(std::vector<var>&, nas_map&);
|
void mark_map(std::vector<var>&, nas_map&);
|
||||||
void sweep();
|
void sweep();
|
||||||
|
|
|
@ -105,9 +105,11 @@ void nas_func::clear() {
|
||||||
void nas_ghost::set(
|
void nas_ghost::set(
|
||||||
const std::string& ghost_type_name,
|
const std::string& ghost_type_name,
|
||||||
destructor destructor_pointer,
|
destructor destructor_pointer,
|
||||||
|
marker gc_marker_pointer,
|
||||||
void* ghost_pointer) {
|
void* ghost_pointer) {
|
||||||
type_name = ghost_type_name;
|
type_name = ghost_type_name;
|
||||||
destructor_function = destructor_pointer;
|
destructor_function = destructor_pointer;
|
||||||
|
gc_mark_function = gc_marker_pointer;
|
||||||
pointer = ghost_pointer;
|
pointer = ghost_pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,6 +131,7 @@ void nas_ghost::clear() {
|
||||||
type_name = "";
|
type_name = "";
|
||||||
pointer = nullptr;
|
pointer = nullptr;
|
||||||
destructor_function = nullptr;
|
destructor_function = nullptr;
|
||||||
|
gc_mark_function = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ostream& operator<<(std::ostream& out, const nas_ghost& ghost) {
|
std::ostream& operator<<(std::ostream& out, const nas_ghost& ghost) {
|
||||||
|
|
|
@ -166,21 +166,24 @@ public:
|
||||||
struct nas_ghost {
|
struct nas_ghost {
|
||||||
private:
|
private:
|
||||||
using destructor = void (*)(void*);
|
using destructor = void (*)(void*);
|
||||||
|
using marker = void (*)(void*, std::vector<var>*);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
std::string type_name;
|
std::string type_name;
|
||||||
destructor destructor_function;
|
destructor destructor_function;
|
||||||
|
marker gc_mark_function;
|
||||||
void* pointer;
|
void* pointer;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
nas_ghost():
|
nas_ghost():
|
||||||
type_name(""), destructor_function(nullptr), pointer(nullptr) {}
|
type_name(""), destructor_function(nullptr),
|
||||||
~nas_ghost() {clear();}
|
gc_mark_function(nullptr), pointer(nullptr) {}
|
||||||
void set(const std::string&, destructor, void*);
|
~nas_ghost() { clear(); }
|
||||||
|
void set(const std::string&, destructor, marker, void*);
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
const auto& get_ghost_name() const {return type_name;}
|
const auto& get_ghost_name() const { return type_name; }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct context {
|
struct context {
|
||||||
|
|
|
@ -73,7 +73,7 @@ var builtin_opendir(context* ctx, gc* ngc) {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
var ret = ngc->alloc(vm_obj);
|
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;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,75 +5,77 @@ println(keys(libfib));
|
||||||
libfib.test_ghost();
|
libfib.test_ghost();
|
||||||
|
|
||||||
var libfib = func() {
|
var libfib = func() {
|
||||||
var (dd,fib,qfib)=(nil,nil,nil);
|
var (dd, fib, qfib) = (nil, nil, nil);
|
||||||
var invoke=dylib.limitcall(1);
|
var invoke = dylib.limitcall(1);
|
||||||
return {
|
return {
|
||||||
open:func() {
|
open: func() {
|
||||||
if (dd==nil) {
|
if (dd==nil) {
|
||||||
dd=dylib.dlopen("libfib."~(os.platform()=="windows"?"dll":"so"));
|
dd = dylib.dlopen("libfib."~(os.platform()=="windows"?"dll":"so"));
|
||||||
fib=dd.fib;
|
fib = dd.fib;
|
||||||
qfib=dd.quick_fib;
|
qfib = dd.quick_fib;
|
||||||
} else {
|
} else {
|
||||||
println("[info ] already loaded.");
|
println("[info ] already loaded.");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
close:func() {
|
close: func() {
|
||||||
if (dd==nil) {
|
if (dd==nil) {
|
||||||
println("[error ] already closed.");
|
println("[error ] already closed.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
dylib.dlclose(dd.lib);
|
dylib.dlclose(dd.lib);
|
||||||
(dd,fib,qfib)=(nil,nil,nil);
|
(dd, fib, qfib) = (nil, nil, nil);
|
||||||
},
|
},
|
||||||
fib:func(x) {
|
fib: func(x) {
|
||||||
if (fib!=nil)
|
if (fib!=nil) {
|
||||||
return invoke(fib,x);
|
return invoke(fib, x);
|
||||||
|
}
|
||||||
println("[error ] cannot call fib.");
|
println("[error ] cannot call fib.");
|
||||||
return nil;
|
return nil;
|
||||||
},
|
},
|
||||||
qfib:func(x) {
|
qfib: func(x) {
|
||||||
if (qfib!=nil)
|
if (qfib!=nil) {
|
||||||
return invoke(qfib,x);
|
return invoke(qfib, x);
|
||||||
|
}
|
||||||
println("[error ] cannot call qfib.");
|
println("[error ] cannot call qfib.");
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}();
|
}();
|
||||||
|
|
||||||
println("[keys ] ",keys(libfib));
|
println("[keys ] ", keys(libfib));
|
||||||
libfib.open();
|
libfib.open();
|
||||||
libfib.open();
|
libfib.open();
|
||||||
var tm=maketimestamp();
|
var tm = maketimestamp();
|
||||||
tm.stamp();
|
tm.stamp();
|
||||||
println("[result] ",libfib.fib(35));
|
println("[result] ", libfib.fib(35));
|
||||||
println("[time ] ",tm.elapsedMSec()," ms");
|
println("[time ] ", tm.elapsedMSec()," ms");
|
||||||
tm.stamp();
|
tm.stamp();
|
||||||
println("[result] ",libfib.qfib(35));
|
println("[result] ", libfib.qfib(35));
|
||||||
println("[time ] ",tm.elapsedMSec()," ms");
|
println("[time ] ", tm.elapsedMSec()," ms");
|
||||||
libfib.close();
|
libfib.close();
|
||||||
println("[result] ",libfib.fib(35));
|
println("[result] ", libfib.fib(35));
|
||||||
println("[result] ",libfib.qfib(35));
|
println("[result] ", libfib.qfib(35));
|
||||||
libfib.close();
|
libfib.close();
|
||||||
|
|
||||||
var speed_test = func() {
|
var speed_test = func() {
|
||||||
var d=dylib.dlopen("libfib."~(os.platform()=="windows"?"dll":"so"));
|
var d = dylib.dlopen("libfib."~(os.platform()=="windows"? "dll":"so"));
|
||||||
println("[dylib ] ",d);
|
println("[dylib ] ", d);
|
||||||
var fd=d.quick_fib;
|
var fd = d.quick_fib;
|
||||||
var vec_call=dylib.dlcall;
|
var vec_call = dylib.dlcall;
|
||||||
var invoke=dylib.limitcall(1);
|
var invoke = dylib.limitcall(1);
|
||||||
var tm=maketimestamp();
|
var tm = maketimestamp();
|
||||||
|
|
||||||
for(var t=0;t<10;t+=1) {
|
for(var t=0; t<10; t+=1) {
|
||||||
tm.stamp();
|
tm.stamp();
|
||||||
for(var i=0;i<5e5;i+=1) {
|
for(var i=0; i<5e5; i+=1) {
|
||||||
invoke(fd,40);
|
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();
|
tm.stamp();
|
||||||
for(var i=0;i<5e5;i+=1) {
|
for(var i=0; i<5e5; i+=1) {
|
||||||
vec_call(fd,40);
|
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