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

View File

@ -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_ghost(ghost); # 114 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( 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;

View File

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

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_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);

View File

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

View File

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

View File

@ -166,17 +166,20 @@ 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),
gc_mark_function(nullptr), pointer(nullptr) {}
~nas_ghost() { clear(); } ~nas_ghost() { clear(); }
void set(const std::string&, destructor, void*); void set(const std::string&, destructor, marker, void*);
void clear(); void clear();
public: public:

View File

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

View File

@ -26,14 +26,16 @@ var libfib = func() {
(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;
} }