mirror of
https://github.com/HeyPuter/gex.git
synced 2026-11-13 20:12:43 -10:00
page: say when a trap unwinds a provider's guest calls, and which resumes the Worker set before a wild branch
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_1896c5b302a54696aaa92c5f4047f20b
This commit is contained in:
1 parent
7e23c82a56
commit
f823644fce
2 files changed
+36
No files matched your search
@@ -2790,6 +2790,8 @@ export class Gex {
|
||||
* exception, so code the provider publishes at run time (its JIT, which imports it)
|
||||
* can catch it with `try_table`, and `provider_try` takes it when nothing did. */
|
||||
#provTag = null;
|
||||
/** Traps seen unwinding provider guest calls (reported up to 16). */
|
||||
#provLeaks = 0;
|
||||
#providerTag() {
|
||||
this.#provTag ??= new WebAssembly.Tag({ parameters: ['i32'] });
|
||||
return this.#provTag;
|
||||
@@ -2810,8 +2812,16 @@ export class Gex {
|
||||
ftab.get(f)(arg);
|
||||
return 0;
|
||||
} catch (err) {
|
||||
const open = e.gex_libprov_guest_calls();
|
||||
e.gex_libprov_guest_calls_set(calls);
|
||||
if (err instanceof WebAssembly.Exception && err.is(tag)) return err.getArg(tag, 0);
|
||||
// Anything else that unwinds a provider's guest calls abandons
|
||||
// frames the guest will return into (their return addresses stay
|
||||
// on its stack): say which trap, where it resumes, and from where.
|
||||
if (open > calls && (this.#provLeaks = (this.#provLeaks ?? 0) + 1) <= 16) {
|
||||
console.error(`[gex] a trap left through ${open - calls} provider guest call(s): ${err?.message ?? err}; ` +
|
||||
`resume ${BigInt.asUintN(64, BigInt(e.gex_resume_pc())).toString(16)}\n${err?.stack ?? ''}`);
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
},
|
||||
@@ -3644,6 +3654,15 @@ export class Gex {
|
||||
// alone it slid into the guest's stack and overwrote saved registers.
|
||||
this.#shim.exports.__stack_pointer.value = addrVal(this.#workerStack());
|
||||
const e = this.#shim.exports;
|
||||
// A trap that reached the run loop with a provider's guest call
|
||||
// still open abandoned the provider's frames (see provider_try).
|
||||
if ((e.gex_libprov_guest_calls?.() ?? 0) > 0) {
|
||||
if ((this.#provLeaks = (this.#provLeaks ?? 0) + 1) <= 16) {
|
||||
console.error(`[gex] a trap reached the run loop with ${e.gex_libprov_guest_calls()} provider guest call(s) open: ${err?.message ?? err}; ` +
|
||||
`resume ${BigInt.asUintN(64, BigInt(e.gex_resume_pc())).toString(16)}\n${err?.stack ?? ''}`);
|
||||
}
|
||||
e.gex_libprov_guest_calls_set(0);
|
||||
}
|
||||
// A slot the shim wants written before the guest goes back to it: its
|
||||
// module is instantiated with passive segments, so the code is present
|
||||
// and simply not in the table. Filling here costs one segment; at
|
||||
|
||||
@@ -7188,9 +7188,22 @@ fn resume() -> Option<u64> {
|
||||
RESUME.with(|c| c.get())
|
||||
}
|
||||
|
||||
thread_local! {
|
||||
/// This Worker's last resumes set (the shim's line that set it, pc), for
|
||||
/// the wild-branch report: who sent the guest where it went.
|
||||
static RESUME_RING: std::cell::RefCell<Vec<(u32, u64)>> = const { std::cell::RefCell::new(Vec::new()) };
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
fn set_resume(v: u64) {
|
||||
RESUME.with(|c| c.set(Some(v)));
|
||||
RESUME_RING.with(|r| {
|
||||
let mut r = r.borrow_mut();
|
||||
if r.len() == 16 {
|
||||
r.remove(0);
|
||||
}
|
||||
r.push((std::panic::Location::caller().line(), v));
|
||||
});
|
||||
// GEX_NT_RESUME_LOG: each (call site, pc) a resume was set from, once:
|
||||
// where the guest leaves wasm and comes back (an AOT-only run needs a
|
||||
// unit or region entry at every such pc).
|
||||
@@ -11001,6 +11014,10 @@ pub extern "C" fn gex_dispatch_miss(_ctx: i32, pc: i64) -> i32 {
|
||||
cgen::callouts_recent(),
|
||||
cgen::libprov::guest_call_open()
|
||||
));
|
||||
warn_line(&format!(
|
||||
"[gex] last resumes set (lib.rs line, pc): {:x?}\n",
|
||||
RESUME_RING.with(|r| r.borrow().iter().map(|&(l, v)| (l, v)).collect::<Vec<_>>())
|
||||
));
|
||||
}
|
||||
set_exit(h, 128 + 11);
|
||||
});
|
||||
|
||||
Reference in new issue
Block a user