MCPcopy Create free account
hub / github.com/bytecodealliance/wasmtime / compute_handler

Function compute_handler

crates/wasmtime/src/runtime/vm/throw.rs:18–124  ·  view source on GitHub ↗

Compute the target of the pending exception on the store. # Safety The stored last-exit state in `store` either must be valid, or must have a zeroed exit FP if no Wasm is on the stack.

(
    store: &mut StoreOpaque,
    throwing_tag_instance_id: InstanceId,
    throwing_tag_defined_tag_index: DefinedTagIndex,
)

Source from the content-addressed store, hash-verified

16/// The stored last-exit state in `store` either must be valid, or
17/// must have a zeroed exit FP if no Wasm is on the stack.
18pub unsafe fn compute_handler(
19 store: &mut StoreOpaque,
20 throwing_tag_instance_id: InstanceId,
21 throwing_tag_defined_tag_index: DefinedTagIndex,
22) -> Option<Handler> {
23 log::trace!(
24 "throwing: tag defined in instance {throwing_tag_instance_id:?} defined-tag {throwing_tag_defined_tag_index:?}"
25 );
26
27 // Get the state needed for a stack walk.
28 let (exit_pc, exit_fp, entry_fp) = unsafe {
29 (
30 *store.vm_store_context().last_wasm_exit_pc.get(),
31 store.vm_store_context().last_wasm_exit_fp(),
32 *store.vm_store_context().last_wasm_entry_fp.get(),
33 )
34 };
35
36 // Early out: if there is no exit FP -- which can happen if a host
37 // func, wrapped up as a `Func`, is called directly via
38 // `Func::call` -- then the only possible action we can take is
39 // `None` (i.e., no handler, unwind to entry from host).
40 if exit_fp == 0 {
41 return None;
42 }
43
44 // Walk the stack, looking up the module with each PC, and using
45 // that module to resolve local tag indices into (instance, tag)
46 // tuples.
47 let handler_lookup = |frame: &Frame| -> Option<(usize, usize)> {
48 log::trace!(
49 "exception-throw stack walk: frame at FP={:x} PC={:x}",
50 frame.fp(),
51 frame.pc()
52 );
53 let (store_code, rel_pc) = store.modules().store_code_by_pc(frame.pc())?;
54 let et = ExceptionTable::parse(store_code.code_memory().exception_tables())
55 .expect("Exception tables were validated on module load");
56 let (frame_offset, handlers) = et.lookup_pc(u32::try_from(rel_pc).unwrap());
57 let fp_to_sp = frame_offset.map(|frame_offset| -isize::try_from(frame_offset).unwrap());
58 for handler in handlers {
59 log::trace!("-> checking handler: {handler:?}");
60 let is_match = match handler.tag {
61 // Catch-all/default handler. Always come last in sequence.
62 None => true,
63 Some(module_local_tag_index) => {
64 let fp_to_sp =
65 fp_to_sp.expect("frame offset is necessary for exception unwind");
66 let fp_offset = fp_to_sp
67 + isize::try_from(
68 handler
69 .context_sp_offset
70 .expect("dynamic context not present for handler record"),
71 )
72 .unwrap();
73 let frame_vmctx = unsafe { frame.read_slot_from_fp(fp_offset) };
74 log::trace!("-> read vmctx from frame: {frame_vmctx:x}");
75 let frame_vmctx =

Callers 1

unwindMethod · 0.85

Calls 15

last_wasm_exit_fpMethod · 0.80
store_code_by_pcMethod · 0.80
pcMethod · 0.80
code_memoryMethod · 0.80
lookup_pcMethod · 0.80
read_slot_from_fpMethod · 0.80
get_exported_tagMethod · 0.80
to_raw_indicesMethod · 0.80
text_rangeMethod · 0.80
parseFunction · 0.50
newFunction · 0.50
getMethod · 0.45

Tested by

no test coverage detected