🐛 fix issue #80
Some checks failed
Nasal Interpreter Test / mac-aarch64 (push) Has been cancelled
Nasal Interpreter Test / linux-x86_64 (push) Has been cancelled

Signed-off-by: ValKmjolnir <lhk101lhk101@qq.com>
This commit is contained in:
ValKmjolnir
2026-04-15 00:27:34 +08:00
parent 01a51a78c5
commit 07eb5e2561
4 changed files with 26 additions and 17 deletions

View File

@@ -33,8 +33,11 @@ void gc::mark() {
while (!bfs.empty()) {
var value = bfs.front();
bfs.pop();
if (value.type <= vm_type::vm_num ||
value.val.gcobj->mark != nas_val::gc_status::uncollected) {
if (value.type <= vm_type::vm_num) {
continue;
}
if (value.val.gcobj->mark != nas_val::gc_status::uncollected &&
value.val.gcobj->mark != nas_val::gc_status::alloc_in_sweep_stage) {
continue;
}
mark_var(bfs, value);
@@ -170,7 +173,8 @@ void gc::sweep() {
if (i->mark == nas_val::gc_status::uncollected) {
unused[static_cast<u32>(i->type) - static_cast<u32>(vm_type::vm_str)].push_back(i);
i->mark = nas_val::gc_status::collected;
} else if (i->mark == nas_val::gc_status::found) {
} else if (i->mark == nas_val::gc_status::found ||
i->mark == nas_val::gc_status::alloc_in_sweep_stage) {
i->mark = nas_val::gc_status::uncollected;
}
}
@@ -297,10 +301,14 @@ var gc::alloc(const vm_type type) {
var ret = var::gcobj(unused[index].back());
ret.val.gcobj->clear();
// if incremental sweep stage, mark it as found
// but be aware that it may be collected in next gc cycle
// if incremental sweep stage, mark it with special state.
// to avoid miss-marking objects inside them, because mark stage
// will skip scanning objects with "found" mark
// if we mark it with "found" mark, objects inside it will not be marked
// so they may be treated as unreferenced, which is not expected.
// be aware that it will be collected in next gc cycle
ret.val.gcobj->mark = in_incremental_sweep_stage
? nas_val::gc_status::found
? nas_val::gc_status::alloc_in_sweep_stage
: nas_val::gc_status::uncollected;
unused[index].pop_back();
return ret;

View File

@@ -66,7 +66,7 @@ struct gc {
const u64 max_incr[GC_TYPE_SIZE] = {
8192, // vm_str
8192, // vm_vec
4096, // vm_hash
8192, // vm_hash
2048, // vm_func
2048, // vm_upval
256, // vm_obj

View File

@@ -51,9 +51,12 @@ struct nas_map; // mapper
// nas_val includes gc-managed types
struct nas_val {
enum class gc_status: u8 {
uncollected = 0,
collected,
found
uncollected = 0, // will be collected by sweep
collected, // already collected and put into unused list
found, // marked as referenced
alloc_in_sweep_stage // mark it allocated in incremental sweep stage
// still scan in mark stage
// but do not sweep in this gc cycle
};
gc_status mark;

View File

@@ -24,10 +24,7 @@ var test_func = func(test_processes...) {
var end_info = runtime.gc.info();
var gc_total_end = end_info.total;
var duration = time_stamp.elapsedMSec();
if (duration == nil) {
println(time_stamp.elapsedMSec);
die("remaining issue: time_stamp.elapsedMSec() entry = 0x559.");
}
print(" ", duration, " ms,\tgc ",
int((gc_total_end-gc_total_begin)*100/duration), "%,\t",
int(1000/(duration/size(test_processes))*10)/10, " test(s)/sec",
@@ -113,7 +110,8 @@ var append_tree = func {
append(res, {
a: {b: {c:[1, 2, 3, 4]}},
d: {e: {}},
j: {k: {l:{m:[{a:{b:{c:[{}, {}]}}}]}}}
j: {k: {l:{m:[{a:{b:{c:[{}, {}]}}}]}}},
n: [[], []]
});
}
}
@@ -122,12 +120,12 @@ var append_deep_tree = func {
var res = {};
var tmp = [];
for (var i = 0; i < MAX_ITER_NUM; i += 1) {
tmp = [[[tmp]]];
tmp = [[[tmp, tmp]]];
}
res["vec"] = tmp;
tmp = {};
for (var i = 0; i < MAX_ITER_NUM; i += 1) {
tmp = {a : {a : {a : tmp}}};
tmp = {a : {a : {a : tmp, b : tmp}}};
}
res["hash"] = tmp;
return res;