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

Method call

crates/wasmtime/src/runtime/vm/interpreter.rs:168–234  ·  view source on GitHub ↗

Invokes interpreted code. The `bytecode` pointer should previously have been produced by Cranelift and `callee` / `caller` / `args_and_results` are normal array-call arguments being passed around.

(
        mut self,
        mut bytecode: NonNull<u8>,
        callee: NonNull<VMOpaqueContext>,
        caller: NonNull<VMContext>,
        args_and_results: NonNull<[ValRaw]>,
    )

Source from the content-addressed store, hash-verified

166 /// and `callee` / `caller` / `args_and_results` are normal array-call
167 /// arguments being passed around.
168 pub unsafe fn call(
169 mut self,
170 mut bytecode: NonNull<u8>,
171 callee: NonNull<VMOpaqueContext>,
172 caller: NonNull<VMContext>,
173 args_and_results: NonNull<[ValRaw]>,
174 ) -> bool {
175 // Initialize argument registers with the ABI arguments.
176 let args = [
177 XRegVal::new_ptr(callee.as_ptr()).into(),
178 XRegVal::new_ptr(caller.as_ptr()).into(),
179 XRegVal::new_ptr(args_and_results.cast::<u8>().as_ptr()).into(),
180 XRegVal::new_u64(args_and_results.len() as u64).into(),
181 ];
182
183 let mut vm = self.vm();
184
185 let old_lr = unsafe { vm.call_start(&args) };
186
187 // Run the interpreter as much as possible until it finishes, and then
188 // handle each finish condition differently.
189 let ret = loop {
190 match unsafe { vm.call_run(bytecode) } {
191 // If the VM returned entirely then read the return value and
192 // return that (it indicates whether a trap happened or not.
193 DoneReason::ReturnToHost(()) => {
194 match unsafe { vm.call_end(old_lr, [RegType::XReg]).next().unwrap() } {
195 #[allow(
196 clippy::cast_possible_truncation,
197 reason = "intentionally reading the lower bits only"
198 )]
199 Val::XReg(xreg) => break (xreg.get_u32() as u8) != 0,
200 _ => unreachable!(),
201 }
202 }
203 // If the VM wants to call out to the host then dispatch that
204 // here based on `id`. Once that returns we typically resume
205 // execution at `resume`.
206 DoneReason::CallIndirectHost { id, resume } => {
207 unsafe {
208 self.call_indirect_host(id);
209 }
210
211 // After the host has finished take a look at what hostcall
212 // was just made. The `raise` hostcall gets special handling
213 // for its non-local transfer of control flow.
214 //
215 // Also note that for non-`raise` hostcalls the
216 // `state.resume_at_pc` value should always be `None`.
217 if u32::from(id) == HostCall::Builtin(BuiltinFunctionIndex::raise()).index() {
218 bytecode = self.take_resume_at_pc();
219 } else {
220 debug_assert!(self.vm_state().resume_at_pc.is_none());
221 bytecode = resume;
222 }
223 vm = self.vm();
224 }
225 // If the VM trapped then process that here and return `false`.

Callers 1

Calls 15

fromFunction · 0.85
raiseFunction · 0.85
vmMethod · 0.80
call_startMethod · 0.80
call_runMethod · 0.80
call_endMethod · 0.80
take_resume_at_pcMethod · 0.80
as_ptrMethod · 0.45
lenMethod · 0.45
unwrapMethod · 0.45
nextMethod · 0.45
get_u32Method · 0.45

Tested by

no test coverage detected