aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMistivia <i@mistivia.com>2025-06-23 14:06:15 +0800
committerMistivia <i@mistivia.com>2025-06-23 14:06:15 +0800
commit69e9065635b1c20fe0f973bdebeb2745171bace1 (patch)
tree02505a75859b2667b0f90f159470228357c1eb66 /src
parent957175b7f1bff57477ccd000c956bcbe06d159cf (diff)
optimize gc stack
Diffstat (limited to 'src')
-rw-r--r--src/interp.c49
1 files changed, 33 insertions, 16 deletions
diff --git a/src/interp.c b/src/interp.c
index 5a23d0b..7d89641 100644
--- a/src/interp.c
+++ b/src/interp.c
@@ -266,34 +266,51 @@ void Interp_gc(Interp *interp, SExpRef tmproot) {
// mark
while (!SExpRefVector_empty(&gcstack)) {
SExpRef ref = *SExpRefVector_last(&gcstack);
+ SExpRef child;
SExpRefVector_pop(&gcstack);
if (ref.idx < 0) continue;
SExp *obj = REF(ref);
if (obj->marked) continue;
obj->marked = true;
if (obj->type == kPairSExp) {
- SExpRefVector_push_back(&gcstack, obj->pair.car);
- SExpRefVector_push_back(&gcstack, obj->pair.cdr);
+ child = obj->pair.car;
+ if (child.idx >= 0 && !REF(child)->marked) SExpRefVector_push_back(&gcstack, child);
+ child = obj->pair.cdr;
+ if (child.idx >= 0 && !REF(child)->marked) SExpRefVector_push_back(&gcstack, child);
} else if (obj->type == kFuncSExp) {
- SExpRefVector_push_back(&gcstack, obj->func.args);
- SExpRefVector_push_back(&gcstack, obj->func.body);
- SExpRefVector_push_back(&gcstack, obj->func.env);
+ child = obj->func.args;
+ if (child.idx >= 0 && !REF(child)->marked) SExpRefVector_push_back(&gcstack, child);
+ child = obj->func.body;
+ if (child.idx >= 0 && !REF(child)->marked) SExpRefVector_push_back(&gcstack, child);
+ child = obj->func.env;
+ if (child.idx >= 0 && !REF(child)->marked) SExpRefVector_push_back(&gcstack, child);
} else if (obj->type == kEnvSExp) {
- SExpRefVector_push_back(&gcstack, obj->env.bindings);
- SExpRefVector_push_back(&gcstack, obj->env.parent);
+ child = obj->env.bindings;
+ if (child.idx >= 0 && !REF(child)->marked) SExpRefVector_push_back(&gcstack, child);
+ child = obj->env.parent;
+ if (child.idx >= 0 && !REF(child)->marked) SExpRefVector_push_back(&gcstack, child);
} else if (obj->type == kBindingSExp) {
- SExpRefVector_push_back(&gcstack, obj->binding.name);
- SExpRefVector_push_back(&gcstack, obj->binding.value);
- SExpRefVector_push_back(&gcstack, obj->binding.func);
- SExpRefVector_push_back(&gcstack, obj->binding.next);
+ child = obj->binding.name;
+ if (child.idx >= 0 && !REF(child)->marked) SExpRefVector_push_back(&gcstack, child);
+ child = obj->binding.value;
+ if (child.idx >= 0 && !REF(child)->marked) SExpRefVector_push_back(&gcstack, child);
+ child = obj->binding.func;
+ if (child.idx >= 0 && !REF(child)->marked) SExpRefVector_push_back(&gcstack, child);
+ child = obj->binding.next;
+ if (child.idx >= 0 && !REF(child)->marked) SExpRefVector_push_back(&gcstack, child);
} else if (obj->type == kMacroSExp) {
- SExpRefVector_push_back(&gcstack, obj->macro.args);
- SExpRefVector_push_back(&gcstack, obj->macro.body);
+ child = obj->macro.args;
+ if (child.idx >= 0 && !REF(child)->marked) SExpRefVector_push_back(&gcstack, child);
+ child = obj->macro.body;
+ if (child.idx >= 0 && !REF(child)->marked) SExpRefVector_push_back(&gcstack, child);
} else if (obj->type == kReturnSignal) {
- SExpRefVector_push_back(&gcstack, obj->ret);
+ child = obj->ret;
+ if (child.idx >= 0 && !REF(child)->marked) SExpRefVector_push_back(&gcstack, child);
} else if (obj->type == kTailcallSExp) {
- SExpRefVector_push_back(&gcstack, obj->tailcall.args);
- SExpRefVector_push_back(&gcstack, obj->tailcall.fn);
+ child = obj->tailcall.args;
+ if (child.idx >= 0 && !REF(child)->marked) SExpRefVector_push_back(&gcstack, child);
+ child = obj->tailcall.fn;
+ if (child.idx >= 0 && !REF(child)->marked) SExpRefVector_push_back(&gcstack, child);
}
}
SExpRefVector_free(&gcstack);