aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/compiler/builtins.zc2
-rw-r--r--src/compiler/decl.zc2
-rw-r--r--src/compiler/expr.zc7
-rw-r--r--src/compiler/stmt.zc4
-rw-r--r--src/runtime/rt.zc27
5 files changed, 26 insertions, 16 deletions
diff --git a/src/compiler/builtins.zc b/src/compiler/builtins.zc
index dd01bd8..9a89052 100644
--- a/src/compiler/builtins.zc
+++ b/src/compiler/builtins.zc
@@ -7,7 +7,7 @@ int kw_memdebug() {
stmtonly();
next();
if (is_id(s_on)) { mdbg = 1; f = 5; }
- else if (is_id(s_scrub)) { mdbg = 1; f = 7; }
+ else if (tk == T_ID && rt.eq_w(tv, "scrub")) { mdbg = 1; f = 7; } // s_scrub is the runtime function rt.scrub, not this word
else if (is_id(s_off)) { mdbg = 0; f = 0; }
else die("memdebug on, memdebug scrub or memdebug off");
next();
diff --git a/src/compiler/decl.zc b/src/compiler/decl.zc
index 36a307d..3a02b90 100644
--- a/src/compiler/decl.zc
+++ b/src/compiler/decl.zc
@@ -328,8 +328,8 @@ int fndef(int chk, int rty, int ret, int n) {
pt[np] = t;
if (np < 12) tags = tags + (t << (np + np));
np++;
- if (np >= 24) die("too many parameters");
if (!accept(s_comma)) break;
+ if (np >= 24) { die("too many parameters"); break; } // a 25th would not fit pn, pt, pty
}
}
expect(s_rp);
diff --git a/src/compiler/expr.zc b/src/compiler/expr.zc
index 1536744..4c77ceb 100644
--- a/src/compiler/expr.zc
+++ b/src/compiler/expr.zc
@@ -538,7 +538,7 @@ int enhcall(int s) {
// scan with the compiler lexer, restoring its source and lookahead. only functions containing a closure
// need cells; their scalars get cells from declaration time, so loop back edges and earlier references agree.
int capture_scan() {
- word old, f; int depth = 1, found = 0, docs = docs_on, record = grec;
+ word old, f; int depth = 1, found = 0, docs = docs_on, record = grec, sp = panic;
if (isp < 0 || R_SRC[isp * 32] == 0 || !is_op(s_lb)) return 0;
old = R_SRC + isp * 32;
src_push(1, capture_dummy, 0, 0); old = R_SRC + (isp - 1) * 32; f = R_SRC + isp * 32;
@@ -550,7 +550,7 @@ int capture_scan() {
else if (is_op(s_rb)) depth--;
else if (is_id(s_fn)) { peek(); if (pk_tk == T_OP && (pk_tv == s_lp || pk_tv == s_colon)) found = 1; }
}
- dry--; src_pop(); docs_on = docs; grec = record; return found;
+ dry--; src_pop(); docs_on = docs; grec = record; panic = sp; return found; // a lexer error in the dry scan must not leave panic set for the real parse
}
int capture_cell(int i, int copy) {
if (!capture_enabled || o3on || (ltag[i] & 16) || larr[i] || local_cell[i]) return 0;
@@ -1566,7 +1566,7 @@ int postfix_tail(int c) {
// --, and any unary operator a program added (- ! ~ built in).
int unary() {
int c, un, t, place, constant, value; word storage, dependency;
- if (tk == T_ID && (tv == s_u || tv == s_m || tv == s_d)) { // u*x, d*x, m*x: recast only when * is glued
+ if (tk == T_ID && (tv == s_u || tv == s_m || tv == s_d) && findloc(tv) < 0) { // u*x, d*x, m*x: recast only when * is glued and the tag is not a local's name
peek();
if (pk_tk == T_OP && pk_tv == s_star && pq_gl[0]) {
t = S_M; if (tv == s_u) t = S_U; if (tv == s_d) t = S_D;
@@ -1590,6 +1590,7 @@ int unary() {
else if (xfloat && isnum(t)) { op(OP_F2I); xfloat = 0; }
else xfloat = 0;
if (tbytes(t) && !samesz(t, xty)) { tnorm(t); xconst = 0; } // (u8)x cuts the value to size
+ xstr = t == tbstr; // (int*)s is a word pointer, not a byte string
if_value = 0;
xty = t; lv = 0; lvk = LV_NONE; xzero = 0; xbor = -1;
return C_PLAIN;
diff --git a/src/compiler/stmt.zc b/src/compiler/stmt.zc
index 505e466..a67b931 100644
--- a/src/compiler/stmt.zc
+++ b/src/compiler/stmt.zc
@@ -573,7 +573,7 @@ int kw_switch() {
if (!accept(s_comma)) break;
}
expect(s_rp);
- if (nb != pm_nf[gi]) serr("a case binds every field of its member");
+ if (nb && nb != pm_nf[gi]) serr("a case binds every field of its member"); // member() with no names matches by tag (spec 4.7.3)
v = pm_tag[gi];
if (v < 63) cov = cov | (1 << v);
laddr(lslot[tmp]); op(O_LD); op(O_LD); lit(v); op(O_SUB);
@@ -651,7 +651,7 @@ int kw_return() {
}
if_ret(xty, xzero);
if (fty && fty != tvoid) fcoerce(fty);
- if (fty == tvoid) tcerr("return value", tvoid, xty);
+ if (fty == tvoid) { tcerr("return value", tvoid, xty); op(O_DROP); lit(0); } // typecheck off: the value is ignored (spec 4.8.3)
else if (fty && !compat(fty, xty)) tcerr("return value", fty, xty);
}
if (nclo) {
diff --git a/src/runtime/rt.zc b/src/runtime/rt.zc
index 8c26161..7089e26 100644
--- a/src/runtime/rt.zc
+++ b/src/runtime/rt.zc
@@ -1346,7 +1346,7 @@ int scrub() {
// dbg bits: 1 header checks and allocation sites, 2 poison the payload on free
// (the word 57005, which is 0xDEAD), 4 interior pointers keep a quarantined
-// block (the mark walks back at most 64 words to a real header). off unless
+// block (obj_base finds its header from the size classes). off unless
// a program requests. sites are p ^ MAGIC so the collector does not treat them as pointers.
const int NSITE = 64;
@@ -1355,17 +1355,26 @@ int site_drop;
word[64] site_p; word[64] site_line;
// true when p is a freed block still held in quarantine.
word quar(word p) { return p >= HEAP_LO + HDR && p < hbump && p[-3] == (p ^ MAGIC) && !(p[-4] & 1); }
-// the object whose payload contains w, or 0. exact pointers and interiors.
+// the object whose payload contains w, or 0. exact pointers and interiors, at any
+// depth. every block of class k starts at HEAP_LO plus a multiple of 2^k words, so
+// the block holding w, if any, starts at w rounded down to one of those. the
+// candidates are tried from the largest class down: a header counts only when its
+// check word, size and class agree with k, and the first that holds w in its
+// payload is the block. a merge clears the upper half's header and a split rewrites
+// the header at the same address, so a stale header can only sit inside the
+// payload of the real block, which is found first.
word obj_base(int w) {
- int i = 0; word p; int n;
+ int k = 31, off, sz; word b, p;
if (w < HEAP_LO + HDR || w >= hbump) return 0;
- while (i <= 64) {
- p = w - i;
- if (p >= HEAP_LO + HDR && p < hbump && p[-3] == (p ^ MAGIC)) {
- n = p[-5] - HDR;
- if (w >= p && w < p + n) return p;
+ off = w - HEAP_LO;
+ while (k >= 3) {
+ sz = pow2[k];
+ b = HEAP_LO + off - off % sz;
+ p = b + HDR;
+ if (sz <= hbump - HEAP_LO && p < hbump && b[0] == sz && p[-3] == (p ^ MAGIC) && bclass(b) == k) {
+ if (w >= p && w < b + sz) return p;
}
- i++;
+ k--;
}
return 0;
}