aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/rt.zc
diff options
context:
space:
mode:
authorGravatar zinc <zinc@downsta.ir> 2026-10-15 00:09:49 +0330
committerGravatar zinc <zinc@downsta.ir> 2026-10-15 00:09:49 +0330
commit684f40056c4d3dc7a586240d51294b167c9d0ddc (patch)
treedfb7142823b5b68406300c1f384b9f33c439fa0b /src/runtime/rt.zc
parentdestructors: heap(v), drop(v, f) / v.drop(f) / v.drop = f, struct drop method... (diff)
rt: the free paths take one F_HASDROP test, and dropfree does the drop and the clearing out of line
Diffstat (limited to 'src/runtime/rt.zc')
-rw-r--r--src/runtime/rt.zc8
1 files changed, 4 insertions, 4 deletions
diff --git a/src/runtime/rt.zc b/src/runtime/rt.zc
index afff233..968be87 100644
--- a/src/runtime/rt.zc
+++ b/src/runtime/rt.zc
@@ -828,7 +828,7 @@ int paylen(word p) { return p[-4] >> 32; }
// frees p and, recursively, every object p owns. the block stays quarantined.
int release(word p) {
word b = p - HDR; int n, i = 0; word w;
- if (b[1] & F_HASDROP) dropnow(p);
+ if (b[1] & F_HASDROP) dropfree(p);
n = paylen(p);
b[1] = (b[1] & ~7) | 2; // going: not live, and not free yet either, so a child's buddy check can't merge into it
while (i < n) {
@@ -837,7 +837,6 @@ int release(word p) {
w = p[i]; if (isobj(w) && !(w[-4] & F_SHARE) && w[-2] == p) release(w);
i++;
}
- if (b[1] & F_HASDROP) dclear(p);
b[1] = b[1] & 2097144; // quarantined (flags but the state, and the class; n is cleared, so len is 0 and indexing traps). the check word and the bytes stay; the next sweep reclaims it
return 0;
}
@@ -871,7 +870,7 @@ unchecked int recycle(.d p) {
}
if (!isobj(p) || (p[-4] & F_SHARE)) return 0;
b = p - HDR;
- if (b[1] & F_HASDROP) dropnow(p);
+ if (b[1] & F_HASDROP) dropfree(p);
n = paylen(p);
b[1] = (b[1] & ~7) | 2;
while (i < n) {
@@ -880,7 +879,6 @@ unchecked int recycle(.d p) {
w = p[i]; if (isobj(w) && !(w[-4] & F_SHARE) && w[-2] == p) recycle(w);
i++;
}
- if (b[1] & F_HASDROP) dclear(p);
if (dbg & 2) fill_w(p, 57005, n);
bdrop(b);
return 0;
@@ -987,6 +985,8 @@ int dropnow(word p) {
if (g) { g = g - 1; g(p); }
return 0;
}
+// the free paths' one test leads here: run the drop while p is live, then forget it
+int dropfree(word p) { dropnow(p); dclear(p); return 0; }
// p's block is going back: forget its entry and bits, so a reused address has no drop
int dclear(word p) {
int i = dfind(p);