Stage I: strip dead code -- pump drain loop, SWITCH-MARK-WORK, global interpret depth, native_switch_back_to (FABRIC-3.8 §4 row I)
Each shown dead three ways (FABRIC-3.5 §XXII): the pump loop by its condition, by construction (birth cap == switch table capacity, every birth registers) and at run time (probe silent through boot, G interleave, an 8-worker DoE trial and the relay); SWITCH-MARK-WORK by callers, capsules (source and baked), experiments/tools/logs; the depth counter and back_to field by having no readers. Kept: Hera's own pump drain (last timer-paced delivery, Hera only) and the always-0 readiness CSV columns (a DoE schema call). Acceptance on amd64/ aarch64/riscv64: G interleave unchanged, cfg-0 trial fail=0 2/2 dead, relay 3, idle growth 0; dict_hash set changed by the removed word (word_count 531) and identical across ISAs. FABRIC-3.8 stages A-I done. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
f152a91099
commit
dd23c3aa45
@@ -1325,3 +1325,49 @@ explicit instruction.
|
||||
observation, not investigated.
|
||||
- Stage F's remaining evidence (work proceeds with the console idle) is shown by Stage G's
|
||||
interleave and by these trials.
|
||||
- [x] **Stage I — strip the dead code (§4 row I).** 2026-09-24. Captain Bob: *"go ahead with
|
||||
stage I."* Per `FABRIC-3.5.md` §XXII's discipline, each removal's reachability was shown
|
||||
three ways, not by grep alone.
|
||||
|
||||
**Removed:**
|
||||
|
||||
| Item | Why dead |
|
||||
|---|---|
|
||||
| **The idle pump's drain loop** (`repl.c`, `sk_repl_idle()`), which drained every non-Hera live VM on Hera's stack (G3) | (1) **Static:** since C-b it acted only on a live **non-participant**. (2) **Construction:** births are refused at `stadium_max_vm_count()` live VMs (`capsule_birth.c:731`), the same capacity as the switch-signal table. Every birth registers (Stage E), stillborn VMs never go live, and `KILL`/reap unregister, so registration can't fail and no live non-participant can exist. (3) **Runtime:** a probe line in that branch (temporary, removed) printed **nothing** through a boot, the Stage G interleave, a full 8-worker cfg-4 trial (`fail=0`, 8/8 dead) and the WIREBIND relay (`logs/20260924-051657/amd64/`). |
|
||||
| **`SWITCH-MARK-WORK`** (the word, `mama_word_switch_mark_work`, and `sk_vm_switch_signal_mark_work()`) | (1) Its only caller, `MSG-SEND` in `capsules/common/messaging.4th`, was deleted in `FABRIC-3.6.md` Phase 4. (2) No capsule source, no baked capsule (`capsule_generated.c`: 0), no experiment, tool or committed log invokes it; only the design docs mention it. (3) Since C-b, eligibility **is** the queue, so the word had nothing left to mark. |
|
||||
| **The global interpret depth** (`g_vm_interpret_depth`, `sk_vm_at_outermost_interpret()`) | No caller since Stage A replaced it with the per-VM ownership gate. Only comments referred to it; they're updated. |
|
||||
| **`VM.native_switch_back_to`** (`vm.h`) | Written by `sk_vm_context_switch()`, read by nothing since C-b's trampoline stopped yielding to "whoever switched in" (the Stage B/FR probes, which read it, are long reverted). |
|
||||
|
||||
**Kept, deliberately:**
|
||||
- **Hera's own drain in the idle pump.** She is the one VM never switched to for her mail,
|
||||
since she's the one running there. It still runs at the `SK_IDLE_BEAT_INTERVAL`
|
||||
(timer-paced) cadence, and at her own word checkpoints. **This is the last
|
||||
timer-paced delivery left, and it applies only to Hera's own queue.** Moving it to
|
||||
`sk_vm_idle_point()` would need care with the readline `n > 0` mid-edit gate. Noted for
|
||||
Captain Bob.
|
||||
- **The three `*_readiness` DoE CSV columns** (always 0 since C-b). Dropping them changes
|
||||
the CSV layout the extractor and analysis read. That's a DoE-schema decision for the
|
||||
campaign relaunch, not a dead-code strip.
|
||||
|
||||
**Acceptance** (on every ISA: the Stage G interleave, a cfg-0 DoE trial, then the relay):
|
||||
`logs/20260924-054146/amd64/`, `-055249/aarch64/`, `-061024/riscv64/`.
|
||||
- The G interleave is byte-identical to Stage H on all three (A = 40, B = 40, 48 runs).
|
||||
- `MU-TRIAL … cfg=0 … nw=2 … fail=0`, with 2/2 `KILL … dead` and 0 refused.
|
||||
- All reach `[zuse@Hera] ok>` with zero `UNKNOWN WORD`, failures and faults.
|
||||
- Mint → WIREBIND → `USE` → `1 2 + .` → `3`.
|
||||
- Idle log growth: 0 bytes.
|
||||
- Clean build on all three plus hosted (`vm.h` is shared), no new warnings.
|
||||
- **The `dict_hash` set changes, as expected, because `SWITCH-MARK-WORK` is gone, and is
|
||||
identical across ISAs.** `word_count` drops by 2 because the word was registered twice
|
||||
in Hera's dictionary.
|
||||
|
||||
| | New | Stages G/H |
|
||||
|---|---|---|
|
||||
| `word_count` | 531 | 533 |
|
||||
| M7.1a | `0x572daac83b797332` | `0x330b28ce0f4e1c75` |
|
||||
| Hera | `0xda9742ce9c3376a2` | |
|
||||
| Hestia | `0x413e7d086f342d8b` | |
|
||||
| Artemis | `0xdfd68316d5f5ba85` | |
|
||||
|
||||
**FABRIC-3.8's staged plan (A–I) is complete.** What's next is the per-ISA DoE relaunch
|
||||
(seed 12345, 3 reps) on the rebuilt driver, then the merge to master.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Capsule Block Manifest — Auto-generated
|
||||
<!-- Generated by mkcapsule --manifest 2026-09-24T03:15:17Z -->
|
||||
<!-- Generated by mkcapsule --manifest 2026-09-24T10:09:49Z -->
|
||||
<!-- DO NOT EDIT — re-run mkcapsule --manifest to refresh. -->
|
||||
<!-- Hand-written justifications and immutability notes live -->
|
||||
<!-- in MANIFEST.md alongside this auto-generated index. -->
|
||||
|
||||
@@ -169,10 +169,6 @@ void sk_vm_switch_reap_pending(void);
|
||||
* CSV counters below. */
|
||||
void sk_vm_switch_signal_note_switch_performed(VMUuid target_id);
|
||||
|
||||
/* SWITCH-MARK-WORK's body. Stage C-b: no flag to set any more (the queue
|
||||
* is the eligibility); only asks for a fresh decision. */
|
||||
void sk_vm_switch_signal_mark_work(VMUuid vm_id);
|
||||
|
||||
/* DoE CSV read-only exposure (FABRIC-3.md §XXVIII Stage 3 follow-on,
|
||||
* 2026-09-13). Stage C-b: ticks_since_switch now counts beats of the
|
||||
* running VM since the last switch (§3.13.4), not ISR ticks; the per-VM
|
||||
|
||||
@@ -543,7 +543,9 @@ typedef struct VM VM;
|
||||
* one message per checkpoint, ruled 2026-09-21). Called from
|
||||
* execute_colon_word()'s existing cooperative checkpoint in vm_core.c,
|
||||
* gated the same way the switch-signal checkpoint already is
|
||||
* (sk_vm_at_outermost_interpret()).
|
||||
* (sk_vm_at_outermost_interpret() then; since FABRIC-3.8.md Stage A the
|
||||
* per-VM sk_vm_owns_outermost_frame(), and the global counter is removed,
|
||||
* Stage I).
|
||||
*
|
||||
* AMENDS SXLIII.5's own claim: "recursive drain is prevented for free"
|
||||
* via g_vm_interpret_depth is true (the SAME message cannot drain twice),
|
||||
|
||||
@@ -659,17 +659,6 @@ typedef struct VM
|
||||
* entered (no context parked yet); non-zero only
|
||||
* while VMRegistryEntry.state ==
|
||||
* VM_STATE_SWITCHED_OUT for this VM. */
|
||||
struct VM *native_switch_back_to; /**< Stage 3 correction (FABRIC-3.md §XXVIII,
|
||||
* 2026-09-13): who most recently switched INTO
|
||||
* this VM. Updated by sk_vm_context_switch() on
|
||||
* every switch-in (first-ever or resumed), so the
|
||||
* placeholder trampoline (sk_vm_switch_entry())
|
||||
* always yields back to whoever actually switched
|
||||
* in, not a stale value captured once at this
|
||||
* VM's very first entry -- a single global there
|
||||
* let a later switch-in from a different VM get
|
||||
* silently bounced to the original caller instead
|
||||
* of itself. */
|
||||
VMFrameStack frames; /**< FABRIC-3.8.md §3.12 (Stage FR, 2026-09-23):
|
||||
* this VM's execution frame stack -- the nested
|
||||
* levels running on its own native stack, each
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -333,15 +333,6 @@ void sk_vm_switch_signal_note_switch_performed(VMUuid target_id) {
|
||||
g_beats_since_switch = 0;
|
||||
}
|
||||
|
||||
void sk_vm_switch_signal_mark_work(VMUuid vm_id) {
|
||||
/* Stage C-b: eligibility is read from the kernel-Hermes queue itself,
|
||||
* so there is no has_work flag to set. Kept (SWITCH-MARK-WORK still
|
||||
* calls it) as a "something changed, decide again" hint; Stage I
|
||||
* strips it if nothing calls it. */
|
||||
(void)vm_id;
|
||||
g_decision_due = 1;
|
||||
}
|
||||
|
||||
uint64_t sk_vm_switch_signal_switch_count(void) {
|
||||
return g_switch_count;
|
||||
}
|
||||
|
||||
@@ -56,7 +56,6 @@
|
||||
#include "starkernel/capsule_vm_physics.h"
|
||||
#include "starkernel/vm/vm_internal.h"
|
||||
#include "starkernel/vm/stadium.h" /* item 4.2 -- STADIUM-* words */
|
||||
#include "starkernel/capsule_vm_switch_signal.h" /* FABRIC-3.md §XXVIII Stage 3 follow-on -- SWITCH-MARK-WORK */
|
||||
#include "starkernel/vm/stadium_words.h" /* item 4.2 -- stadium_words_resident_heat() */
|
||||
#include "starkernel/repl.h"
|
||||
#include "starkernel/capsule_generated.h"
|
||||
@@ -832,47 +831,12 @@ static void mama_word_vm_exec(VM *vm)
|
||||
/* Stack clean on exit */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief SWITCH-MARK-WORK ( name-caddr name-u -- )
|
||||
* FABRIC-3.md §XXVIII Stage 3 follow-on (2026-09-14): message-arrival
|
||||
* eligibility hook. Called from MSG-SEND (capsules/common/messaging.4th)
|
||||
* every time a message is sent to a VM, so the Stage 3 switch signal can
|
||||
* tell "has recently been sent something" apart from "has just been idle
|
||||
* long enough" before ever selecting it as a switch target. Silently
|
||||
* ignores a malformed or unknown name -- this fires on the hot path of
|
||||
* every message send, not a user-facing command, so it must never error
|
||||
* or spam the console.
|
||||
*/
|
||||
static void mama_word_switch_mark_work(VM *vm)
|
||||
{
|
||||
char name[VM_NAME_MAX];
|
||||
cell_t u, caddr;
|
||||
uint32_t i;
|
||||
VMRegistryEntry entry;
|
||||
|
||||
/* FABRIC-3.md §XXXII.6, 2026-09-15: this guard used to set vm->error on
|
||||
* underflow, contradicting this function's own doc comment above ("must
|
||||
* never error or spam the console") -- flagged as a special case in
|
||||
* §XXXII.3's triage, not just a missing diagnostic. Silently ignored,
|
||||
* matching every other malformed-input case in this same function. */
|
||||
if (vm->dsp < 1) return;
|
||||
|
||||
u = vm_pop(vm);
|
||||
caddr = vm_pop(vm);
|
||||
|
||||
if (u <= 0 || (uint32_t)u >= VM_NAME_MAX) return;
|
||||
|
||||
{
|
||||
const uint8_t *p = vm_ptr(vm, (vaddr_t)caddr);
|
||||
if (!p) return;
|
||||
for (i = 0; i < (uint32_t)u; i++) name[i] = (char)p[i];
|
||||
name[u] = '\0';
|
||||
}
|
||||
|
||||
if (capsule_vm_find_by_name_nocase(name, &entry) == 0) {
|
||||
sk_vm_switch_signal_mark_work(entry.vm_id);
|
||||
}
|
||||
}
|
||||
/* SWITCH-MARK-WORK (FABRIC-3.md §XXVIII Stage 3 follow-on) was removed at
|
||||
* FABRIC-3.8.md Stage I (2026-09-24). Its only caller, MSG-SEND in
|
||||
* capsules/common/messaging.4th, was deleted in FABRIC-3.6.md Phase 4; since
|
||||
* Stage C-b a VM's eligibility is its kernel-Hermes queue itself, so there
|
||||
* is nothing left for it to mark. No capsule (source or baked), experiment,
|
||||
* tool or committed log invokes it. */
|
||||
|
||||
/**
|
||||
* @brief VM-CALL ( cmd-caddr cmd-u vm-name-caddr vm-name-u -- n )
|
||||
@@ -2393,7 +2357,6 @@ void register_mama_forth_words(VM *vm)
|
||||
register_word(vm, "VM-PHYSICS-STATUS", mama_word_vm_physics_status);
|
||||
register_word(vm, "VM-STEP", mama_word_vm_step);
|
||||
register_word(vm, "VM-EXEC", mama_word_vm_exec);
|
||||
register_word(vm, "SWITCH-MARK-WORK", mama_word_switch_mark_work);
|
||||
register_word(vm, "VM-CALL", mama_word_vm_call);
|
||||
register_word(vm, "VM-HEAT", mama_word_vm_heat);
|
||||
register_word(vm, "VM-ERROR?", mama_word_vm_error_query);
|
||||
@@ -2458,7 +2421,6 @@ void register_mama_forth_words(VM *vm)
|
||||
register_word(vm, "VM-PHYSICS-STATUS", mama_word_vm_physics_status);
|
||||
register_word(vm, "VM-STEP", mama_word_vm_step);
|
||||
register_word(vm, "VM-EXEC", mama_word_vm_exec);
|
||||
register_word(vm, "SWITCH-MARK-WORK", mama_word_switch_mark_work);
|
||||
register_word(vm, "VM-CALL", mama_word_vm_call);
|
||||
register_word(vm, "VM-HEAT", mama_word_vm_heat);
|
||||
register_word(vm, "VM-ERROR?", mama_word_vm_error_query);
|
||||
@@ -2719,7 +2681,6 @@ void register_child_vm_words(VM *vm)
|
||||
register_word(vm, "STOP", mama_word_stop);
|
||||
register_word(vm, "EXEC", mama_word_exec);
|
||||
register_word(vm, "VM-EXEC", mama_word_vm_exec);
|
||||
register_word(vm, "SWITCH-MARK-WORK", mama_word_switch_mark_work);
|
||||
register_word(vm, "VM-CALL", mama_word_vm_call);
|
||||
register_word(vm, "VM-HEAT", mama_word_vm_heat);
|
||||
register_word(vm, "VM-ERROR?", mama_word_vm_error_query);
|
||||
|
||||
+12
-43
@@ -47,7 +47,6 @@
|
||||
#include "starkernel/vm/bootstrap/sk_vm_bootstrap.h"
|
||||
#include "starkernel/vm/kernel_hermes.h" /* FABRIC-3.6.md task 3.8 -- sk_hermes_send_one() */
|
||||
#include "starkernel/vm/switch.h" /* FABRIC-3.8.md §3.13.5 -- sk_vm_idle_point() */
|
||||
#include "starkernel/capsule_vm_switch_signal.h" /* §3.13.5 -- pump skips participants */
|
||||
#include "starkernel/vm/stadium.h" /* task 3.8 -- stadium_conserved() evidence print */
|
||||
#include "block_subsystem.h"
|
||||
#include "word_source/include/keyboard_words.h"
|
||||
@@ -954,48 +953,18 @@ static void sk_repl_idle(VM *active_vm)
|
||||
}
|
||||
|
||||
g_idle_pump_active = 1;
|
||||
{
|
||||
/* FABRIC-3.6.md Phase 4 (Stage E), 2026-09-22: the SK_MSG_PUMP_
|
||||
* BATCH cap this loop used to enforce existed to bound the cost
|
||||
* of the old MSG-TICK VM-EXEC dispatch -- a genuinely expensive
|
||||
* per-VM vm_interpret() call, confirmed live as a real O(N)
|
||||
* bottleneck at just 9 VMs on riscv64 (see this section's own
|
||||
* history above). sk_hermes_drain_checkpoint() (task 3.4) is not
|
||||
* that: its own fast path is a single global-counter read
|
||||
* (sk_hermes_pending_total == 0 -> return immediately,
|
||||
* kernel_hermes.c's own doc comment), so walking every live VM
|
||||
* every beat costs one cheap integer read per VM in the common
|
||||
* case (nothing in flight), not an O(N) wall -- the cap this
|
||||
* loop's own comment history worried about does not apply to
|
||||
* this call. Removed: every live VM (except mama, handled
|
||||
* separately below) is now visited every idle beat, matching
|
||||
* what task 3.9's own testing already exercised, without the
|
||||
* ceil(N/SK_MSG_PUMP_BATCH)-beat delivery latency the cap was
|
||||
* accidentally imposing on kernel-Hermes drain specifically. */
|
||||
uint32_t count = capsule_vm_registry_count();
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
VMRegistryEntry ent;
|
||||
/* FABRIC-3.8.md §3.4 / §3.13.5 (Stage C-b, G3): switch
|
||||
* participants are skipped -- their mail is delivered on their
|
||||
* own stacks, by a switch (sk_vm_idle_point() and the trampoline),
|
||||
* never drained here on Hera's. Only VMs not yet participants
|
||||
* (Stage E makes every born VM one) are still pumped here. */
|
||||
if (capsule_vm_registry_get_by_index(i, &ent) == 0 &&
|
||||
ent.state == VM_STATE_LIVE &&
|
||||
ent.vm_ptr != (void *)mama &&
|
||||
!sk_vm_switch_signal_is_participant(ent.vm_id)) {
|
||||
(void)sk_hermes_drain_checkpoint((VM *)ent.vm_ptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Hera's own kernel-Hermes queue needs draining too, same as every
|
||||
* other VM's -- she is excluded from the loop above not because she
|
||||
* has nothing to drain, but because she IS the pump: a self-
|
||||
* targeting call here runs directly, no VM-EXEC/reentrancy concern
|
||||
* (sk_hermes_drain_checkpoint() is a plain C call, not a dispatch
|
||||
* into anyone else's input buffer). */
|
||||
/* FABRIC-3.8.md Stage I (2026-09-24): the loop that used to drain every
|
||||
* other live VM's queue here, on Hera's stack (G3), is removed. Since
|
||||
* Stage E every born VM is a switch participant -- births are capped at
|
||||
* stadium_max_vm_count() live VMs (capsule_birth.c), the same capacity
|
||||
* as the switch-signal table, so registration cannot fail -- and a
|
||||
* participant's mail is delivered on its own stack by a switch, never
|
||||
* here. Shown dead three ways before removal: by the condition it
|
||||
* required (a live non-participant), by that construction, and at run
|
||||
* time (a probe printed nothing through a boot, the Stage G interleave,
|
||||
* a full 8-worker DoE trial and the WIREBIND relay). What remains is
|
||||
* Hera's own queue: she is the one VM that is never switched to for her
|
||||
* mail, since she is the one running here. */
|
||||
(void)sk_hermes_drain_checkpoint(mama);
|
||||
g_idle_pump_active = 0;
|
||||
|
||||
|
||||
@@ -49,8 +49,9 @@ extern uint64_t sk_vm_switch_prime(uint64_t stack_top, void *entry);
|
||||
* native stack belongs to. Read exactly once, synchronously, at the very
|
||||
* top of sk_vm_switch_entry() before any other first-entry could occur.
|
||||
* Safe to keep as a plain global (unlike the old g_switch_back_to this
|
||||
* file used to also carry -- see native_switch_back_to's own doc comment
|
||||
* in vm.h for why that one had to move to per-VM state): a VM's identity
|
||||
* file used to also carry, which moved to per-VM native_switch_back_to and
|
||||
* was then removed at FABRIC-3.8.md Stage I once the trampoline stopped
|
||||
* yielding to "whoever switched in"): a VM's identity
|
||||
* never changes across the lifetime of its own trampoline instance, only
|
||||
* who most recently switched into it does. */
|
||||
static VM *g_switch_entry_vm;
|
||||
@@ -236,11 +237,6 @@ int sk_vm_context_switch(VM *from, VM *to) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Recorded unconditionally (first-ever entry or a resume) so whoever
|
||||
* is parked at `to`'s native stack -- most often this placeholder
|
||||
* trampoline -- always knows who most recently switched into it. */
|
||||
to->native_switch_back_to = from;
|
||||
|
||||
if (to->native_stack_saved_sp == 0) {
|
||||
/* First-ever entry: synthesize the initial frame. */
|
||||
g_switch_entry_vm = to;
|
||||
|
||||
@@ -65,11 +65,6 @@
|
||||
#include "starkernel/vm/kernel_hermes.h" /* FABRIC-3.6.md task 3.4 -- sk_hermes_drain_checkpoint() */
|
||||
#include "starkernel/capsule_birth.h" /* capsule_vm_registry_get() */
|
||||
|
||||
/* FABRIC-3.md §XXVIII Stage 3 correction (2026-09-13): forward-declared
|
||||
* here because execute_colon_word() (uses it) appears earlier in this file
|
||||
* than g_vm_interpret_depth's definition (kept next to g_log_attrib_vm,
|
||||
* near vm_interpret() -- see that doc comment for the full rationale). */
|
||||
int sk_vm_at_outermost_interpret(void);
|
||||
int sk_vm_owns_outermost_frame(VM *vm); /* FABRIC-3.8.md §3.1 -- defined near vm_interpret() */
|
||||
#endif
|
||||
#include "word_source/include/vocabulary_words.h"
|
||||
@@ -940,8 +935,9 @@ void execute_colon_word(VM* vm)
|
||||
* so a switch never happens mid-unwind).
|
||||
*
|
||||
* Stage 3 correction (2026-09-13): also gated on
|
||||
* sk_vm_at_outermost_interpret() -- see g_vm_interpret_depth's own
|
||||
* doc comment above vm_interpret(). If this word is executing
|
||||
* sk_vm_at_outermost_interpret() (a global depth count, removed at
|
||||
* FABRIC-3.8.md Stage I -- superseded by the ownership gate
|
||||
* below). If this word is executing
|
||||
* nested inside a VM-EXEC/VM-CALL dispatch (from another VM's own
|
||||
* vm_interpret() call, still on the mainline stack), `vm` here does
|
||||
* not own the physical stack it's currently running on, so a real
|
||||
@@ -1174,19 +1170,11 @@ VM *vm_log_attributed_vm(void) {
|
||||
return (VM *)e.vm_ptr;
|
||||
}
|
||||
|
||||
/* FABRIC-3.md §XXVIII Stage 3 correction (2026-09-13): nesting depth of
|
||||
* vm_interpret() calls, tracked the same save/restore-adjacent way as
|
||||
* g_log_attrib_vm just above. A nested call (VM-EXEC/VM-CALL dispatching
|
||||
* into a different VM's own dictionary mid-interpret) runs on physical
|
||||
* stack memory it does not own -- the Stage 3 switch checkpoint in
|
||||
* execute_colon_word() below must never fire a real context switch there,
|
||||
* only at the outermost vm_interpret() call, or it parks a borrowed stack
|
||||
* region under the wrong VM's saved-context pointer (silent corruption,
|
||||
* not just the trampoline livelock this was first found chasing -- see
|
||||
* FABRIC-3.md for the full writeup). */
|
||||
static int g_vm_interpret_depth;
|
||||
|
||||
int sk_vm_at_outermost_interpret(void) { return g_vm_interpret_depth <= 1; }
|
||||
/* FABRIC-3.8.md Stage I (2026-09-24): the global vm_interpret() nesting
|
||||
* depth (g_vm_interpret_depth / sk_vm_at_outermost_interpret(), FABRIC-3.md
|
||||
* §XXVIII Stage 3) that used to live here is removed. It only approximated
|
||||
* the per-VM ownership rule below, and stopped meaning anything once VMs
|
||||
* interleave on their own stacks; since Stage A nothing read it. */
|
||||
|
||||
/* FABRIC-3.8.md §3.1 (Stage A, 2026-09-23): the real ownership invariant
|
||||
* the global depth test above was approximating. A checkpoint may drain or
|
||||
@@ -1252,7 +1240,6 @@ void vm_interpret_kind(VM* vm, const char* input, uint32_t kind)
|
||||
vm->error = 1;
|
||||
return;
|
||||
}
|
||||
g_vm_interpret_depth++;
|
||||
|
||||
/* Load into input buffer (cap + NUL) */
|
||||
size_t n = 0, cap = INPUT_BUFFER_SIZE ? INPUT_BUFFER_SIZE - 1 : 0;
|
||||
@@ -1303,7 +1290,6 @@ void vm_interpret_kind(VM* vm, const char* input, uint32_t kind)
|
||||
#endif
|
||||
}
|
||||
|
||||
g_vm_interpret_depth--;
|
||||
vm_frame_pop(frame_stack, frame_id); /* by ID -- a mismatch is logged as corruption */
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user