Stage K-1: real kernel realloc; word-metrics defects closed (FABRIC-3.10.8 §4.1)
- Kernel sf_realloc() is a real realloc (copy min(old,new) via new kmalloc_usable_size(), free old, NULL-on-0 frees). It allocated fresh and nothing else: every growth leaked, and vm_state_push()'s call-state stack lost every saved state past depth 8 (found here). - Shim realloc() copies min(old,new) (over-read when growing). - Defect 9: FC bucket growth no longer leaks or patches a copy; no sf_xrealloc() (freed a block the index still held on failure). - Defect 5: heat snapshot heap-sized (was heats[1024], truncating). - Defect 6: word refused whole when its metrics can't be allocated. - Defect 7: vm_cleanup() (both) frees metrics' inner arrays. - Defect 8: most-likely-next kept incrementally; no full id scan. - Probe (removed): realloc keeps contents, heap returns exactly; call stack depth 20 intact; all three ISAs. Churn criterion NOT met: ~7 KB retained per churned VM (quota slots/word rows -- K-4 re-measures); a post-churn CONSOLE-CMD refusal attributed to the quota leak, K-4 retests. - Standard sequence on amd64/aarch64/riscv64: hashes, G, ledger unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
ef849906d9
commit
27c430e0ca
@@ -251,6 +251,20 @@ int transition_metrics_record(WordTransitionMetrics *metrics, uint32_t next_word
|
||||
metrics->transition_heat[next_word_id]++;
|
||||
metrics->total_transitions++;
|
||||
|
||||
/* FABRIC-3.10.8 K-1: keep the most-likely-next word current here, so
|
||||
* transition_metrics_update_cache() needn't scan the whole id space on
|
||||
* every transition. Counts only ever rise by one, so the leader changes
|
||||
* only when this word overtakes it (ties: the lower id, as the scan
|
||||
* picked). */
|
||||
{
|
||||
uint32_t best = metrics->most_likely_next_word_id;
|
||||
uint64_t bc = (best < metrics->transition_heat_cap) ? metrics->transition_heat[best] : 0;
|
||||
uint64_t nc = metrics->transition_heat[next_word_id];
|
||||
if (nc > bc || (nc == bc && next_word_id < best)) {
|
||||
metrics->most_likely_next_word_id = next_word_id;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -328,30 +342,30 @@ int64_t transition_metrics_get_probability_q48(const WordTransitionMetrics *metr
|
||||
* must match the size used at allocation time.
|
||||
*/
|
||||
void transition_metrics_update_cache(WordTransitionMetrics *metrics, uint32_t dict_size) {
|
||||
if (!metrics || !metrics->transition_heat || metrics->total_transitions == 0) {
|
||||
if (!metrics) return; /* K-1: was dereferenced in the branch below when NULL */
|
||||
if (!metrics->transition_heat || metrics->total_transitions == 0) {
|
||||
metrics->max_transition_probability_q48 = 0;
|
||||
metrics->most_likely_next_word_id = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
int64_t max_prob_q48 = 0;
|
||||
uint32_t max_idx = 0;
|
||||
|
||||
/* Find word with highest transition count. Bounded by the array's own
|
||||
* length (S-1b): it may lag dict_size until the next grow. */
|
||||
/* FABRIC-3.10.8 K-1: the leader (highest transition count, lowest id on
|
||||
* a tie) is kept current by transition_metrics_record(); this only
|
||||
* refreshes its probability. It used to scan every id up to dict_size
|
||||
* on every transition. One difference, by construction: the scan
|
||||
* compared probabilities, which are floored Q48.16 quotients, so once
|
||||
* total_transitions passes 65536 two different counts could floor
|
||||
* equal and the scan kept the lower id; the leader is by count.
|
||||
* Bounded by the array's own length (S-1b): it may lag dict_size. */
|
||||
uint32_t limit = (dict_size < metrics->transition_heat_cap) ? dict_size : metrics->transition_heat_cap;
|
||||
for (uint32_t i = 0; i < limit; i++) {
|
||||
if (metrics->transition_heat[i] > 0) {
|
||||
int64_t prob_q48 = transition_metrics_get_probability_q48(metrics, i);
|
||||
if (prob_q48 > max_prob_q48) {
|
||||
max_prob_q48 = prob_q48;
|
||||
max_idx = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
uint32_t best = metrics->most_likely_next_word_id;
|
||||
|
||||
metrics->max_transition_probability_q48 = max_prob_q48;
|
||||
metrics->most_likely_next_word_id = max_idx;
|
||||
if (best >= limit || metrics->transition_heat[best] == 0) {
|
||||
metrics->max_transition_probability_q48 = 0;
|
||||
metrics->most_likely_next_word_id = 0;
|
||||
return;
|
||||
}
|
||||
metrics->max_transition_probability_q48 = transition_metrics_get_probability_q48(metrics, best);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user