diff --git a/lib/environ/src/func_environ.rs b/lib/environ/src/func_environ.rs index 588546defb..fefe075501 100644 --- a/lib/environ/src/func_environ.rs +++ b/lib/environ/src/func_environ.rs @@ -108,9 +108,9 @@ impl<'module_environment> FuncEnvironment<'module_environment> { fn get_memory_grow_sig(&self, func: &mut Function) -> ir::SigRef { func.import_signature(Signature { params: vec![ - AbiParam::new(I32), - AbiParam::new(I32), AbiParam::special(self.pointer_type(), ArgumentPurpose::VMContext), + AbiParam::new(I32), + AbiParam::new(I32), ], returns: vec![AbiParam::new(I32)], call_conv: self.target_config.default_call_conv, @@ -159,8 +159,8 @@ impl<'module_environment> FuncEnvironment<'module_environment> { fn get_memory32_size_sig(&self, func: &mut Function) -> ir::SigRef { func.import_signature(Signature { params: vec![ - AbiParam::new(I32), AbiParam::special(self.pointer_type(), ArgumentPurpose::VMContext), + AbiParam::new(I32), ], returns: vec![AbiParam::new(I32)], call_conv: self.target_config.default_call_conv, @@ -446,9 +446,8 @@ impl<'module_environment> cranelift_wasm::FuncEnvironment for FuncEnvironment<'m ); let mut real_call_args = Vec::with_capacity(call_args.len() + 1); - real_call_args.extend_from_slice(call_args); - // Append the callee vmctx address. + // First append the callee vmctx address. let vmctx = pos.ins().load( pointer_type, mem_flags, @@ -457,6 +456,9 @@ impl<'module_environment> cranelift_wasm::FuncEnvironment for FuncEnvironment<'m ); real_call_args.push(vmctx); + // Then append the regular call arguments. + real_call_args.extend_from_slice(call_args); + Ok(pos.ins().call_indirect(sig_ref, func_addr, &real_call_args)) } @@ -468,11 +470,15 @@ impl<'module_environment> cranelift_wasm::FuncEnvironment for FuncEnvironment<'m call_args: &[ir::Value], ) -> WasmResult { let mut real_call_args = Vec::with_capacity(call_args.len() + 1); - real_call_args.extend_from_slice(call_args); // Handle direct calls to locally-defined functions. if !self.module.is_imported_function(callee_index) { + // First append the callee vmctx address. real_call_args.push(pos.func.special_param(ArgumentPurpose::VMContext).unwrap()); + + // Then append the regular call arguments. + real_call_args.extend_from_slice(call_args); + return Ok(pos.ins().call(callee, &real_call_args)); } @@ -490,12 +496,15 @@ impl<'module_environment> cranelift_wasm::FuncEnvironment for FuncEnvironment<'m cast::i32(self.offsets.vmctx_vmfunction_import_body(callee_index)).unwrap(); let func_addr = pos.ins().load(pointer_type, mem_flags, base, body_offset); - // Append the callee vmctx address. + // First append the callee vmctx address. let vmctx_offset = cast::i32(self.offsets.vmctx_vmfunction_import_vmctx(callee_index)).unwrap(); let vmctx = pos.ins().load(pointer_type, mem_flags, base, vmctx_offset); real_call_args.push(vmctx); + // Then append the regular call arguments. + real_call_args.extend_from_slice(call_args); + Ok(pos.ins().call_indirect(sig_ref, func_addr, &real_call_args)) } @@ -511,7 +520,7 @@ impl<'module_environment> cranelift_wasm::FuncEnvironment for FuncEnvironment<'m let vmctx = pos.func.special_param(ArgumentPurpose::VMContext).unwrap(); let call_inst = pos .ins() - .call(memory_grow_func, &[val, memory_index, vmctx]); + .call(memory_grow_func, &[vmctx, val, memory_index]); Ok(*pos.func.dfg.inst_results(call_inst).first().unwrap()) } @@ -524,7 +533,7 @@ impl<'module_environment> cranelift_wasm::FuncEnvironment for FuncEnvironment<'m let (memory_size_func, index_arg) = self.get_memory_size_func(&mut pos.func, index); let memory_index = pos.ins().iconst(I32, index_arg as i64); let vmctx = pos.func.special_param(ArgumentPurpose::VMContext).unwrap(); - let call_inst = pos.ins().call(memory_size_func, &[memory_index, vmctx]); + let call_inst = pos.ins().call(memory_size_func, &[vmctx, memory_index]); Ok(*pos.func.dfg.inst_results(call_inst).first().unwrap()) } } diff --git a/lib/environ/src/module_environ.rs b/lib/environ/src/module_environ.rs index a8578b200b..517f565b07 100644 --- a/lib/environ/src/module_environ.rs +++ b/lib/environ/src/module_environ.rs @@ -235,8 +235,11 @@ impl<'data> cranelift_wasm::ModuleEnvironment<'data> for ModuleEnvironment<'data /// Add environment-specific function parameters. pub fn translate_signature(mut sig: ir::Signature, pointer_type: ir::Type) -> ir::Signature { - sig.params - .push(AbiParam::special(pointer_type, ArgumentPurpose::VMContext)); + // Prepend the vmctx argument. + sig.params.insert( + 0, + AbiParam::special(pointer_type, ArgumentPurpose::VMContext), + ); sig } diff --git a/lib/jit/src/action.rs b/lib/jit/src/action.rs index eace168443..3dd6c8a867 100644 --- a/lib/jit/src/action.rs +++ b/lib/jit/src/action.rs @@ -153,13 +153,16 @@ pub fn invoke( }; for (index, value) in args.iter().enumerate() { - assert_eq!(value.value_type(), signature.params[index].value_type); + // Add one to account for the leading vmctx argument. + assert_eq!(value.value_type(), signature.params[index + 1].value_type); } // TODO: Support values larger than u64. And pack the values into memory // instead of just using fixed-sized slots. + // Subtract one becase we don't pass the vmctx argument in `values_vec`. let value_size = mem::size_of::(); - let mut values_vec: Vec = vec![0; max(signature.params.len(), signature.returns.len())]; + let mut values_vec: Vec = + vec![0; max(signature.params.len() - 1, signature.returns.len())]; // Store the argument values into `values_vec`. for (index, arg) in args.iter().enumerate() { @@ -186,9 +189,9 @@ pub fn invoke( // Call the trampoline. if let Err(message) = unsafe { wasmtime_call_trampoline( + callee_vmctx, exec_code_buf, values_vec.as_mut_ptr() as *mut u8, - callee_vmctx, ) } { return Ok(ActionOutcome::Trapped { message }); diff --git a/lib/jit/src/compiler.rs b/lib/jit/src/compiler.rs index 2fab3d5120..54359ea9cc 100644 --- a/lib/jit/src/compiler.rs +++ b/lib/jit/src/compiler.rs @@ -135,13 +135,13 @@ fn make_trampoline( let pointer_type = isa.pointer_type(); let mut wrapper_sig = ir::Signature::new(isa.frontend_config().default_call_conv); - // Add the `values_vec` parameter. - wrapper_sig.params.push(ir::AbiParam::new(pointer_type)); // Add the `vmctx` parameter. wrapper_sig.params.push(ir::AbiParam::special( pointer_type, ir::ArgumentPurpose::VMContext, )); + // Add the `values_vec` parameter. + wrapper_sig.params.push(ir::AbiParam::new(pointer_type)); let mut context = Context::new(); context.func = ir::Function::with_name_signature(ir::ExternalName::user(0, 0), wrapper_sig); @@ -155,7 +155,7 @@ fn make_trampoline( builder.seal_block(block0); let mut callee_args = Vec::new(); - let (values_vec_ptr_val, vmctx_ptr_val) = { + let (vmctx_ptr_val, values_vec_ptr_val) = { let params = builder.func.dfg.ebb_params(block0); (params[0], params[1]) }; @@ -164,11 +164,12 @@ fn make_trampoline( let mflags = ir::MemFlags::trusted(); for (i, r) in signature.params.iter().enumerate() { let value = match r.purpose { + // i - 1 because vmctx isn't passed through `values_vec`. ir::ArgumentPurpose::Normal => builder.ins().load( r.value_type, mflags, values_vec_ptr_val, - (i * value_size) as i32, + ((i - 1) * value_size) as i32, ), ir::ArgumentPurpose::VMContext => vmctx_ptr_val, other => panic!("unsupported argument purpose {}", other), diff --git a/lib/runtime/src/instance.rs b/lib/runtime/src/instance.rs index b52e470874..043f2b9523 100644 --- a/lib/runtime/src/instance.rs +++ b/lib/runtime/src/instance.rs @@ -387,7 +387,7 @@ impl InstanceContents { }; // Make the call. - unsafe { wasmtime_call(callee_address, callee_vmctx) } + unsafe { wasmtime_call(callee_vmctx, callee_address) } .map_err(InstantiationError::StartTrap) } diff --git a/lib/runtime/src/libcalls.rs b/lib/runtime/src/libcalls.rs index ecbec99196..bc37e98817 100644 --- a/lib/runtime/src/libcalls.rs +++ b/lib/runtime/src/libcalls.rs @@ -90,9 +90,9 @@ pub extern "C" fn wasmtime_f64_nearest(x: f64) -> f64 { /// Implementation of memory.grow for locally-defined 32-bit memories. #[no_mangle] pub unsafe extern "C" fn wasmtime_memory32_grow( + vmctx: *mut VMContext, delta: u32, memory_index: u32, - vmctx: *mut VMContext, ) -> u32 { let instance_contents = (&mut *vmctx).instance_contents(); let memory_index = DefinedMemoryIndex::from_u32(memory_index); @@ -105,9 +105,9 @@ pub unsafe extern "C" fn wasmtime_memory32_grow( /// Implementation of memory.grow for imported 32-bit memories. #[no_mangle] pub unsafe extern "C" fn wasmtime_imported_memory32_grow( + vmctx: *mut VMContext, delta: u32, memory_index: u32, - vmctx: *mut VMContext, ) -> u32 { let instance_contents = (&mut *vmctx).instance_contents(); let memory_index = MemoryIndex::from_u32(memory_index); @@ -119,7 +119,7 @@ pub unsafe extern "C" fn wasmtime_imported_memory32_grow( /// Implementation of memory.size for locally-defined 32-bit memories. #[no_mangle] -pub unsafe extern "C" fn wasmtime_memory32_size(memory_index: u32, vmctx: *mut VMContext) -> u32 { +pub unsafe extern "C" fn wasmtime_memory32_size(vmctx: *mut VMContext, memory_index: u32) -> u32 { let instance_contents = (&mut *vmctx).instance_contents(); let memory_index = DefinedMemoryIndex::from_u32(memory_index); @@ -129,8 +129,8 @@ pub unsafe extern "C" fn wasmtime_memory32_size(memory_index: u32, vmctx: *mut V /// Implementation of memory.size for imported 32-bit memories. #[no_mangle] pub unsafe extern "C" fn wasmtime_imported_memory32_size( - memory_index: u32, vmctx: *mut VMContext, + memory_index: u32, ) -> u32 { let instance_contents = (&mut *vmctx).instance_contents(); let memory_index = MemoryIndex::from_u32(memory_index); diff --git a/lib/runtime/src/traphandlers.rs b/lib/runtime/src/traphandlers.rs index 3339320c09..ec3b5a7374 100644 --- a/lib/runtime/src/traphandlers.rs +++ b/lib/runtime/src/traphandlers.rs @@ -91,9 +91,9 @@ fn push_jmp_buf(buf: jmp_buf) { /// return values will be written. #[no_mangle] pub unsafe extern "C" fn wasmtime_call_trampoline( + vmctx: *mut VMContext, callee: *const VMFunctionBody, values_vec: *mut u8, - vmctx: *mut VMContext, ) -> Result<(), String> { // Reset JMP_BUFS if the stack is unwound through this point. let _guard = ScopeGuard::new(); @@ -106,8 +106,8 @@ pub unsafe extern "C" fn wasmtime_call_trampoline( push_jmp_buf(buf); // Call the function! - let func: fn(*mut u8, *mut VMContext) = mem::transmute(callee); - func(values_vec, vmctx); + let func: fn(*mut VMContext, *mut u8) = mem::transmute(callee); + func(vmctx, values_vec); Ok(()) } @@ -116,8 +116,8 @@ pub unsafe extern "C" fn wasmtime_call_trampoline( /// return values. #[no_mangle] pub unsafe extern "C" fn wasmtime_call( - callee: *const VMFunctionBody, vmctx: *mut VMContext, + callee: *const VMFunctionBody, ) -> Result<(), String> { // Reset JMP_BUFS if the stack is unwound through this point. let _guard = ScopeGuard::new();