diff options
Diffstat (limited to 'src/compiler/expr.zc')
| -rw-r--r-- | src/compiler/expr.zc | 10 |
1 files changed, 10 insertions, 0 deletions
diff --git a/src/compiler/expr.zc b/src/compiler/expr.zc index a6cc55c..141ca16 100644 --- a/src/compiler/expr.zc +++ b/src/compiler/expr.zc @@ -657,6 +657,15 @@ word closure_layout(int closure_index, int count) { // the code that creates the closure runs, it allocates the block (code, then // captured values), writes the three code words and copies each captured // variable in. ctx_push / ctx_pop save and restore the enclosing function's +// a shared variable is reachable only from a function of its own hold block, which holds +// the block's lock for the whole call. a closure might run after the call returns. +int shared_use(int s) { + int rank = sflag[s] / F_SHARED_RANK; + if (fhold == rank && !nclo && infn) return 0; + if (fhold == rank && nclo) { serrn(sname[s], "is shared; a closure can't use it, because it may run after the hold block's lock is released"); return 0; } + serrn(sname[s], "is shared in a hold block; only the functions written inside that block can use it (they hold its lock)"); + return 0; +} // compiler state around the body. int closure() { char* xcf; @@ -1095,6 +1104,7 @@ int primary() { xcval = sval[s]; return C_PLAIN; } + if (s >= 0 && (skind[s] == K_GVAR || skind[s] == K_GARR) && (sflag[s] & F_SHARED)) shared_use(s); if (s >= 0 && skind[s] == K_GVAR) { if (cmode) { vf_symbols(); xvk = svkind[s]; xvv = svvalue[s]; vf_at(rsn - 1, xvk, xvv); } lit(sval[s]); |
